Serwus!
Trochę zaniedbałem mojego bloga... To pierwszy post od 10 miesięcy. W tym roku pewnie ostatni.
Ale od nowego roku szykuję nową ofensywę. Krótsze, częściej publikowane wpisy to coś, co sobie obiecuję. Zobaczymy, co z tego wyjdzie. Trzymajcie kciuki.
Kilka miesięcy temu zmieniłem pracodawcę na Google, więc ciekawych tematów nie powinno zabraknąć.
Tymczasem "stay tuned".
Wesołych!
I udanej zabawy sylwestrowej.
Noc z 31. grudnia na 1szego stycznia to chyba najlepsza noc dla hakerów. Obstawiacie jakieś spektakularne włamania?
niedziela, 26 grudnia 2010
niedziela, 7 lutego 2010
perwszy test z Apache JMeter
Temat testów wydajnościowych pojawia się od czasu do czasu w waszych komentarzach, mailach lub wiadomościach GG. Dzisiaj zaspokoję ciekawość tych, którzy chcieliby zacząć a nie bardzo wiedzą jak. Przedstawię przepis na prosty test wydajnościowy.
Składniki:
- przeglądarka WWW (u mnie będzie to Opera)
- Apache JMeter
- testowana aplikacja WWW
Przepis umożliwia testowanie każdego rodzaju aplikacji webowych. W moim przypadku będzie to prosta witryna składająca się z dwóch statycznych stron HTML.
a.html
i b.html
Uruchamiam te strony na serwerze Apache Tomcat.
Działa. Pora na JMetera. Dystrybuowany jest on jako archiwum zip lub tgz, więc z jego instalacją i uruchomieniem nie będzie problemu.
Posługuję się wersją 2.3.1.
W JMeterze można tworzyć testy na kilka sposobów. Najwygodniej jest je nagrać w przeglądarce WWW. Odbywa się to za pośrednictwem specjalnego serwera proxy. Dodaję go klikając prawym przyciskiem myszy na węźle WorkBench
i wybierając z podręcznego menu Add / Non-Test Elements / Http Proxy Server
Port zmieniam na 9999 (na 8080 jest uruchomiona moja aplikacja).
W sekcji URL Patterns to include dodaję wyrażenie regularne .*\.html. Dzięki temu w moim teście znajdą się tylko strony HTML. Warto dodać tutaj tylko strony generowane dynamiczne (jsp, php, jsf) ponieważ na sprawdzaniu ich wydajności najbardziej nam zależy.
Do węzła Test Plan dodaję grupę wątków Add / Thread Group. Tam zapiszą się nagrane żądania do mojej aplikacji.
Następnie uruchamiam serwer proxy klikając przycisk Start
Uruchamiam przeglądarkę WWW w której konfiguruję serwer proxy
i nagrywam test klikając w uruchomioną aplikację
Nagrany scenariusz znajduje się w grupie wątków. W moim przypadku składa się on z dwóch stron /test-app/a.html i /test-app/b.html.
Pora na sprawdzenie wydajności aplikacji. W ustawieniach grupy wątków zwiększam wartość Number of Threads (users) do 3.. Loop Count ustawiam na 20. Odpowiada to trzem użytkownikom, z których każdy 20 razy wykona scenariusz testowy.
Do swojej grupy wątków dodaję węzeł "raport z testów" (Add / Listener / Summary Report) w którym będę podglądał wyniki testów.
To w zasadzie wszystko. Zapisuję test i uruchamiam go wybierając akcję Start z menu Run.
Hm... Średnio strona mojej aplikacji generuje się 1 milisekundę. Całkiem nieźle.
Planowałem powtórzyć ten test na serwerze Apache WWW, ale wobec takich wyników na Tomcacie nie będzie to miało chyba większego sensu.
Stworzony plan testów zamieszczam tutaj.
Składniki:
- przeglądarka WWW (u mnie będzie to Opera)
- Apache JMeter
- testowana aplikacja WWW
Przepis umożliwia testowanie każdego rodzaju aplikacji webowych. W moim przypadku będzie to prosta witryna składająca się z dwóch statycznych stron HTML.
a.html
<html>
<body>
<h1>Serwus!</h1>
<a href = b.html>dalej</a>
</body>
</html>
i b.html
<html>
<body>
<h1>Druga strona</h1>
</body>
</html>
Uruchamiam te strony na serwerze Apache Tomcat.
Działa. Pora na JMetera. Dystrybuowany jest on jako archiwum zip lub tgz, więc z jego instalacją i uruchomieniem nie będzie problemu.
Posługuję się wersją 2.3.1.
W JMeterze można tworzyć testy na kilka sposobów. Najwygodniej jest je nagrać w przeglądarce WWW. Odbywa się to za pośrednictwem specjalnego serwera proxy. Dodaję go klikając prawym przyciskiem myszy na węźle WorkBench
i wybierając z podręcznego menu Add / Non-Test Elements / Http Proxy Server
Port zmieniam na 9999 (na 8080 jest uruchomiona moja aplikacja).
W sekcji URL Patterns to include dodaję wyrażenie regularne .*\.html. Dzięki temu w moim teście znajdą się tylko strony HTML. Warto dodać tutaj tylko strony generowane dynamiczne (jsp, php, jsf) ponieważ na sprawdzaniu ich wydajności najbardziej nam zależy.
Do węzła Test Plan dodaję grupę wątków Add / Thread Group. Tam zapiszą się nagrane żądania do mojej aplikacji.
Następnie uruchamiam serwer proxy klikając przycisk Start
Uruchamiam przeglądarkę WWW w której konfiguruję serwer proxy
i nagrywam test klikając w uruchomioną aplikację
Nagrany scenariusz znajduje się w grupie wątków. W moim przypadku składa się on z dwóch stron /test-app/a.html i /test-app/b.html.
Pora na sprawdzenie wydajności aplikacji. W ustawieniach grupy wątków zwiększam wartość Number of Threads (users) do 3.. Loop Count ustawiam na 20. Odpowiada to trzem użytkownikom, z których każdy 20 razy wykona scenariusz testowy.
Do swojej grupy wątków dodaję węzeł "raport z testów" (Add / Listener / Summary Report) w którym będę podglądał wyniki testów.
To w zasadzie wszystko. Zapisuję test i uruchamiam go wybierając akcję Start z menu Run.
Hm... Średnio strona mojej aplikacji generuje się 1 milisekundę. Całkiem nieźle.
Planowałem powtórzyć ten test na serwerze Apache WWW, ale wobec takich wyników na Tomcacie nie będzie to miało chyba większego sensu.
Stworzony plan testów zamieszczam tutaj.
niedziela, 17 stycznia 2010
SQuirreL SQL Hibernate plugin
SQuirreL SQL jest moim ulubionym klientem SQL. Umożliwia on również, wykonywanie zapytań HQL. Wtyczka udostępniające tę funkcjonalność dostępna jest w wersji 0.01, ale działa całkiem przyzwoicie. Podpowiada nazwy obiektów oraz ich właściwości. Umożliwia tłumaczenie zapytania HQL na zapytanie SQL oraz jego wykonanie.
Ponieważ sporo trudności przedstawia jej konfiguracja, opisze ją na przykładzie aplikacji wykorzystującej Spring Framework. Zakładam, że połączenie SQuirreL SQLa do bazy danych jest już skonfigurowane.
Wtyczka dystrybuowana jest wraz z instalacyjną wersją klienta SQuirreL SQL. Fakt jej zainstalowania można zweryfikować w menu Plugins/Summary.
Zgodnie z dokumentacją w pliku plugins/hibernate/readme.html wtyczce musimy dostarczyć obiekt klasy SessionFactoryImpl wskazując metodę o sygnaturze
public org.hibernate.impl.SessionFactoryImpl getSessionFactoryImpl()
która go udostępni.
Ponieważ moja aplikacja korzysta ze Springa, obiekt SessionFactoryImpl najlepiej pobrać z jego kontekstu. Klasa implementująca powyższą metodę wygląda zatem:
Blok try-catch jest zbędny, ale ułatwia diagnozowanie problemów przy uruchamianiu wtyczki pod warunkiem uruchomienia klienta SQuirreL SQL z wiersza poleceń.
Ścieżka do pliku ze Springowym kontekstem aplikacji poprzedzona jest podwójnym ukośnikiem, gdyż pierwszy z nich jest wycinany przez Springa.
To tyle jeżeli chodzi o kodowanie. Czas na wskazanie powyższej klasy we właściwościach SQuirreL SQLa. Otwieram zakładkę Hibernate z menu File/Global Preferencess, gdzie tworzę nową konfigurację przyciskiem New.
Wpisuję jej nazwę a następnie konfiguruję ścieżkę klas przyciskiem Add classpath entry. Wskazana ścieżka musi zawierać zarówno skompilowane klasy aplikacji jak i wymagane przez nią biblioteki.
Następnie zaznaczam opcję: Invoke the user defined provider method below i wskazuję napisaną niedawno klasę.
To tyle. Po naciśnięciu przycisku connect na zakładce Hibernate możemy już wykonywać zapytania HQL. Polecam zaznaczenie opcji Always format (formatowanie wynikowego SQLa) oraz Execute SQL (bez niej HQL zostanie jedynie przetłumaczony do SQLa) i można się już mierzyć z HQLem.
Ponieważ sporo trudności przedstawia jej konfiguracja, opisze ją na przykładzie aplikacji wykorzystującej Spring Framework. Zakładam, że połączenie SQuirreL SQLa do bazy danych jest już skonfigurowane.
Wtyczka dystrybuowana jest wraz z instalacyjną wersją klienta SQuirreL SQL. Fakt jej zainstalowania można zweryfikować w menu Plugins/Summary.
Zgodnie z dokumentacją w pliku plugins/hibernate/readme.html wtyczce musimy dostarczyć obiekt klasy SessionFactoryImpl wskazując metodę o sygnaturze
public org.hibernate.impl.SessionFactoryImpl getSessionFactoryImpl()
która go udostępni.
Ponieważ moja aplikacja korzysta ze Springa, obiekt SessionFactoryImpl najlepiej pobrać z jego kontekstu. Klasa implementująca powyższą metodę wygląda zatem:
package pl.matt.hibernate;
import org.hibernate.impl.SessionFactoryImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SessionFactoryProvider {
public org.hibernate.impl.SessionFactoryImpl getSessionFactoryImpl() {
try {
ApplicationContext ac = new FileSystemXmlApplicationContext("//home/mateusz/priv/workspace/blog/resources/application-context.xml");
SessionFactoryImpl out = (SessionFactoryImpl) ac.getBean("sessionFactory");
return out;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Blok try-catch jest zbędny, ale ułatwia diagnozowanie problemów przy uruchamianiu wtyczki pod warunkiem uruchomienia klienta SQuirreL SQL z wiersza poleceń.
Ścieżka do pliku ze Springowym kontekstem aplikacji poprzedzona jest podwójnym ukośnikiem, gdyż pierwszy z nich jest wycinany przez Springa.
To tyle jeżeli chodzi o kodowanie. Czas na wskazanie powyższej klasy we właściwościach SQuirreL SQLa. Otwieram zakładkę Hibernate z menu File/Global Preferencess, gdzie tworzę nową konfigurację przyciskiem New.
Wpisuję jej nazwę a następnie konfiguruję ścieżkę klas przyciskiem Add classpath entry. Wskazana ścieżka musi zawierać zarówno skompilowane klasy aplikacji jak i wymagane przez nią biblioteki.
Następnie zaznaczam opcję: Invoke the user defined provider method below i wskazuję napisaną niedawno klasę.
To tyle. Po naciśnięciu przycisku connect na zakładce Hibernate możemy już wykonywać zapytania HQL. Polecam zaznaczenie opcji Always format (formatowanie wynikowego SQLa) oraz Execute SQL (bez niej HQL zostanie jedynie przetłumaczony do SQLa) i można się już mierzyć z HQLem.
niedziela, 10 stycznia 2010
Hibernate NamingStrategy
Na jednym z ostatnich spotkań WJUGa pożaliłem się odrobinie osobie siedzącej po mojej prawej stronie na Hibernate. Były to żale bardziej estetyczne niż funkcjonalne a dotyczyły nazw generowanych przez to właśnie narzędzie ORM. Nie podobały mi się ani nazwy tabel ani kolumn ani kluczy obcych jakie nadaje Hibernate podczas tworzenia schematu bazy danych. Osoba słuchająca moich marudzeń powiedziała krótko i fachowo: "Obczaj naming strategy". Obczaiłem.
Domyślnie Hibernate tworzy nazwę tabeli taką samą jak nazwa klasy - encji, natomiast nazwę kolumny taką samą jak nazwa pola. Nazwy kluczy obcych generowane są w sposób nieokreślony: np. 'FK2F894B2DC512614D'.
Ja chciałbym, aby nazwy kolumn i tabel utrzymane były w konwencji z podkreśleniem (czyli np. user_data, default_color), nazwy tabel występowały w liczbie mnogiej, a nazwy kluczy obcych były jakkolwiek zrozumiałe (np. FK_EMP_COM dla klucza łączącego tabelę EMPLOYEES z COMPANIES).
Pierwsze spojrzenie na interfejs NamingStrategy pozbawiło mnie złudzeń. O czytelnych nazwach kluczy obcych mogę sobie pomarzyć. Wybrana strategia stosowana jest tylko do nazw kolumn i tabel. Dobre i to.
Szybki przegląd implementacji:
DefaultNamingStrategy
EJB3NamingStratefy
DefaultComponentSafeNamingStratefy
ImprovedNamingStrategy
wykazał, że trzy pierwsze odpadają w przedbiegach. Konwencja wielbłądzia zachowana. Z klasy UserData.java tworzy się tabela UserData.
Cała nadzieja w ImprovedNamingStrategy. Konwertuje ona nazwy na konwencję z podkreśleniem... i tyle. O liczbie mnogiej mogę póki co pomarzyć. Nie tylko z resztą ja więc chyba skończy się na napisaniu swojej implementacji.
Nazwy kluczy obcych pozostają nie ruszone. Nawet nie nagryzione. Jeżeli wiesz, jak można je zmienić, daj koniecznie znać.
Domyślnie Hibernate tworzy nazwę tabeli taką samą jak nazwa klasy - encji, natomiast nazwę kolumny taką samą jak nazwa pola. Nazwy kluczy obcych generowane są w sposób nieokreślony: np. 'FK2F894B2DC512614D'.
Ja chciałbym, aby nazwy kolumn i tabel utrzymane były w konwencji z podkreśleniem (czyli np. user_data, default_color), nazwy tabel występowały w liczbie mnogiej, a nazwy kluczy obcych były jakkolwiek zrozumiałe (np. FK_EMP_COM dla klucza łączącego tabelę EMPLOYEES z COMPANIES).
Pierwsze spojrzenie na interfejs NamingStrategy pozbawiło mnie złudzeń. O czytelnych nazwach kluczy obcych mogę sobie pomarzyć. Wybrana strategia stosowana jest tylko do nazw kolumn i tabel. Dobre i to.
Szybki przegląd implementacji:
DefaultNamingStrategy
EJB3NamingStratefy
DefaultComponentSafeNamingStratefy
ImprovedNamingStrategy
wykazał, że trzy pierwsze odpadają w przedbiegach. Konwencja wielbłądzia zachowana. Z klasy UserData.java tworzy się tabela UserData.
Cała nadzieja w ImprovedNamingStrategy. Konwertuje ona nazwy na konwencję z podkreśleniem... i tyle. O liczbie mnogiej mogę póki co pomarzyć. Nie tylko z resztą ja więc chyba skończy się na napisaniu swojej implementacji.
Nazwy kluczy obcych pozostają nie ruszone. Nawet nie nagryzione. Jeżeli wiesz, jak można je zmienić, daj koniecznie znać.
Subskrybuj:
Posty (Atom)