Pokazywanie postów oznaczonych etykietą maven2. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą maven2. Pokaż wszystkie posty

03 września 2011

Embeddable EJB 3.1 z Apache OpenEJB 4, Apache Maven 3 i IntelliJ IDEA 10.5

6 komentarzy
Opublikowałem właśnie nowy artykuł Embeddable EJB 3.1 z Apache OpenEJB 4, Apache Maven 3 i IntelliJ IDEA 10.5, który kontynuuje cykl przedstawiania nowych cech specyfikacji Enterprise JavaBeans (EJB) 3.1. Chodził za mną od kilku dni i potrzeba mi było zebrać się w sobie, aby w końcu usiąść i napisać go. W końcu jest!

Zapraszam do lektury i komentarzy. Dla zwrócenia uwagi napiszę, że w samym ziarnie MySession popełniłem kilka błędów architektonicznych, w których zakładam pewne zachowanie ziarna bezstanowego mimo, że takowej nie oferuje (bez świadomej i specyficznej konfiguracji kontenera). Ciekawym komu uda się zauważyć moją pomyłkę, albo kilka? Zachęcam do dyskusji.

09 marca 2011

Słabo typizowane DI w EJB 3.x - o beanName w @EJB jeszcze raz

0 komentarzy
Posiłkując się doświadczeniami z Embeddable EJB 3.1 z GlassFish 3.1 i NetBeans IDE 7.0 oraz Element beanName w @EJB do rozróżnienia deklaracji ziaren EJB stworzyłem przyczułek do dalszych doświadczeń ze specyfikacjami EJB 3.1 oraz CDI 1.0. Tym razem na warsztat wziąłem zbadanie mechanizmu przekazywania zależności (ang. DI, dependency injection) w EJB 3.x.

Potrzebowałem środowiska, w którym będę mógł uruchomić testy automatycznie bez konieczności zestawiania skomplikowanego środowiska uruchomieniowego. Zaletą takiego podejścia może być chociażby uruchomienie testów w dowolnym momencie, na dowolnym komputerze i przez dowolnego (nawet nowego!) członka zespołu. Starałem się utrzymać minimalny nakład pracy, aby łatwiej było przedstawić problem, z którym się zmagam.

Zainteresowany/-a szczegółami? Zapraszam do lektury mojego artykułu Słabo typizowane DI w EJB 3.x - o beanName w @EJB jeszcze raz. Uwagi bardzo mile widziane.

07 lutego 2011

Uruchomić zadanie co 5 sekund w EJB 3.1 ze @Schedule(second = "*/5", info="Every 5 seconds")?

13 komentarzy
Pomyślałby kto, że uruchomienie zadania w EJB 3.1 co 5 sekund wymaga jedynie stworzenia bezstanowego ziarna sesyjnego z metodą opatrzoną adnotacją @Schedule(second = "*/5", info="Every 5 seconds") i gotowe. Nic bardziej mylnego! Okazuje się, że domyślne wartości dla atrybutów @Schedule to zerowa sekunda, minuta i godzina, więc brak ich określenia sprawi, że kolejne uruchomienie będzie o północy następnego dnia. Można się nieźle przejechać podczas wdrożenia.

Więcej (kompletny projekt i kilka dodatkowych przemyśleń) w artykule Uruchomienie cyklicznego zadania w EJB 3.1 ze @Schedule.

p.s. Wciąż zastanawiam się nad moim rozdwojeniem językowym - polskojęzycznym (tutaj) i angielskojęzycznym (na http://blog.japila.pl). Głównym motywem był brak interakcji z czytelnikami, co potwierdziła statystyka na blog.japila.pl, gdzie przy 11 wpisach mam 22 komentarze. Inaczej niż tutaj i po cichutku liczę na choć szczątkowy odzew, np. co należałoby usprawnić w artykule, a szczególnie w sekcji dotyczącej testowania. Nie mam lepszego pomysłu na przetestowanie @Schedule niż to, co zaproponowałem w artykule. Dotknął ktoś tego problemu? Jakieś wskazówki na bardziej eleganckie rozwiązanie?

p.s.2. W kolejnych odcinkach dalej o usłudze budzika (ang. timer service) w EJB 3.1. Może jakieś podpowiedzi, np. z jakim kontenerem? Brak traktuję jako zachętę ku IBM WebSphere Application Server V8 lub Apache OpenEJB 3.2.

30 grudnia 2010

Embeddable EJB 3.1 z GlassFish 3.1 i NetBeans IDE 7.0

1 komentarzy
Biorąc pod uwagę liczbę dni do końca roku, ten wpis będzie co najwyżej przedostatnim wpisem na moim blogu, a na pewno ostatnim dotykającym tematu Java EE 6, EJB 3.1 i in.

Korzystając z okazji, chciałbym życzyć Tobie wszystkiego dobrego w nowym roku 2011 i nakłaniam do jeszcze większej aktywności. Nie czekaj, aż powiedzą, ale mów, proponuj, bądź liderem w swojej społeczności. Dla poszukujących natchnienia polecam lekturę wpisu na blogu Damiana Nowaka - Apprenticeship – długa droga ku Software Craftsmanship. Nie wiem, czy to styl pisania Damiana, czy może sama książka, ale tylko takich wpisów życzę nam w nadchodzącym roku. Niech kasa pójdzie w zapomnienie - niech będzie jej tyle, aby nie stanowiła kwestii do rozwiązania - a czas spędzajmy na tworzeniu - nowego i użytecznego oprogramowania, społeczności przez chociażby dzielenie się wiedzą. Nie ważne jaki był (i jeszcze będzie przez kolejne 2 dni) rok 2010, ale ważne, ile możesz zrobić, aby 2011 był jeszcze lepszy. Zalatuje socjotechniką, ale dobre myślenie poprawia mój nastrój, więc może i Twój również, a to może przełożyć się na coś wyjątkowego.

W takim tonie przedkładam Tobie do oceny mój nowy artykuł Embeddable EJB 3.1 z GlassFish 3.1 i NetBeans IDE 7.0, w którym...

Rozdział 22. Embeddable Usage specyfikacji Enterprise JavaBeans (EJB) 3.1 opisuje nową cechę specyfikacji, która pozwala na uruchomienie kontenera EJB i zarządzanych przez niego komponentów EJB poza serwerem aplikacyjnym Java EE 6 - jedynie na poziomie środowiska Java SE. W ten sposób autorzy specyfikacji przewidują (a my programiści im wierzymy) uproszczenie procesu testowania, przetwarzania wsadowego (w którym użycie transakcji jest kluczowe) czy użycie EJB w samodzielnych aplikacjach desktopowych. Innymi słowy, mamy wszystko, co oferuje kontener EJB 3.1 bez konieczności uruchamiania pełnego serwera aplikacyjnego Java EE, którego sama konfiguracja uruchomieniowa mogła przyprawić o ból głowy.

Zainteresowanych lekturą nie zatrzymuję już i jeszcze tylko na odchodne dorzucę nieśmiało, aby komentować, pytać i kwestionować. Wszyscy zostaną *odpowiednio* potraktowani :-)

20 grudnia 2010

EJB 3.1 z OpenEJB 3.1 i NetBeans IDE 7.0

3 komentarzy
Jest wiele sposobów na naukę nowych technologii i dobór odpowiednich narzędzi może znacząco usprawnić ten proces. W przypadku EJB 3.1 możemy skorzystać z projektu Apache OpenEJB 3.1, podpierając się NetBeans IDE 7.0 jako zintegrowanym środowiskiem programistycznym z asystentami tworzenia ziaren EJB z Apache Maven w tle.

Zastosowanie EJB 3.1 jest zwykle podyktowane względami praktycznymi, kiedy wybór serwera aplikacyjnego Java EE 6 mamy już za sobą i pozostaje wykorzystać jego usługi. Ich kompletność i gotowość do użycia najlepiej doświadczyć, kiedy konieczne jest wykorzystanie transakcji, podłączenia do bazy danych z możliwością przypisania komu i co wolno, udostępnić Web Service z wykorzystaniem REST w ramach aplikacji webowej czy podobne "deklaratywne czynności". Nie ma konieczności zestawiania gotowej konfiguracji usług, a konwencja ponad konfigurację znacznie przyspiesza dostarczanie kompletnych rozwiązań. Przenośność aplikacji jest również istotnym aspektem wyboru stosu technologicznego. Dodając do tego łatwość testowania aplikacji korporacyjnych i Java EE 6 (JEE6) wydaje się być idealną platformą aplikacyjną.

W tym artykule przedstawię uruchomienie bezinterfejsowego, niestanowego ziarna sesyjnego EJB (ang. no-interface stateless session bean) z użyciem projektu Apache OpenEJB 3.1.4, który stworzę w NetBeans IDE 7.0 (wersja rozwojowa z dnia 15.12.2010). Celem jest maksymalne zminimalizowanie czasu koniecznego do uruchomienia środowiska. Kolejną zaletą zastosowania OpenEJB jest możliwość wykonanywania wszystkich operacji projektowych (budowanie i testowanie) poza IDE, dzięki użyciu Apache Maven wspieranym przez NetBeans IDE 7 "z pudełka".

Więcej w artykule EJB 3.1 z OpenEJB 3.1 i NetBeans IDE 7.0.

27 listopada 2010

Wykład akademicki na PWSZ w Tarnowie - 29.11 od 9:30 do 18:00

5 komentarzy
W nadchodzący poniedziałek, 29.11 będę na Wydziale Informatyki Państwowej Wyższej Szkoły Zawodowej (PWSZ) w Tarnowie (ul. Eljasza Goldhammera) u Tomasza Potempy i jego studentów, z którym zorganizowaliśmy mój wykład dotyczący tematu Java i okolice. Głównymi odbiorcami mają być studenci 4 roku, którzy kończą semestr z końcem grudnia, aby w styczniu skupić się na pisaniu pracy inżynierskiej.

Jak to ze mną bywa przy tego typu otwartych tematach, pomysłów mam wiele i byłbym rad, o kilka wskazówek pod kątem możliwości czasowych i znaczenia rynkowego poszczególnych tematów. Celem nie jest przekazanie pełnego obrazu danego rozwiązania, ale raczej naszkicowanie możliwości, aby wybrać do dalszego rozpoznania to, co może być interesujące.

Mam do dyspozycji 2 bloki 5-godzinne (w sensie lekcyjnym nie zegarowym, czyli 45 minut). Można założyć, że w każdym bloku będzie to samo, ale to zależy od ogólnego zainteresowania uczestników oraz mojego przekonania o sensowności dalszego brnięcia w temat. Tym samym nie ma gwarancji, że drugi blok będzie odpowiadał merytorycznie pierwszemu.

Zaczynam o godzinie 9:30, aby zakończyć o 18:00 z 1-godzinną przerwą obiadową w okolicach 13:15. Okazuje się, że będzie okazja spotkać się z Tomkiem Łabuzem, którego można było poznać podczas konferencji Javarsovia 2010, podczas której prezentował temat "AOP, ThreadLocal i JPA".

Planuję przeprowadzić autorski cykl tematyczny, którego mottem byłoby "Od prostoty do większej prostoty, tj. w każdym kroku ukrywamy złożoność problemu". Nie planuję prezentować slajdów, a jedynie siedzieć przed komputerem, prezentując budowanie aplikacji i machając rekoma ze wstawkami krasomówczymi.

Konspekt

Środowiska programistyczne i uruchomieniowe, darmowe i komercyjne:
  • NetBeans IDE i Eclipse IDE
  • IBM Rational Application Developer 8 i IBM WebSphere Integration Developer 7
  • GlassFish i IBM WebSphere Application Server 8 
Klient bazodanowy - tradycyjne podłączenie do bazy danych z użyciem JDBC
  • Apache Derby (wbudowane)
  • MySQL
Hibernate - warstwa pośrednia między baza danych a aplikacja
  • ORM - zapytania bliższe programiście nie adminowi bazy danych
Hibernate + Spring Framework
  • zniesienie konieczności zarządzania bytami Hibernate
  • środowisko IoC/DI
Apache Maven - zarządzanie zależnościami projektowymi
  • zniesienie konieczności dbania o zależności poza ich deklarację
  • tworzenie projektu od zera
    • z linii poleceń
    • z IDE (NetBeans IDE)
Leiningen - Maven w Clojure
  • bez XML z językiem Clojure (wrócimy do niego niebawem)
GlassFish (w NetBeans IDE) i WAS 8 - serwer aplikacyjny JEE6 (z RAD8):
  • dostęp do bazy danych (zarządzanie transakcjami)
    • JPA
    • EJB31
  • servlet - obsługa HTTP
  • JSF - budowanie widoku
    • facelets
  • CDI
EJB 3.1
  • Apache OpenEJB
  • Serwer aplikacyjny - GlassFish i WAS8
OSGi - modularność
  • podział projektu na moduły w Apache Maven był podziałem funkcjonalnym (jak OSGi)
  • samodzielna aplikacja
Clojure - język funkcyjny
  • dynamiczne tworzenie aplikacji okienkowej
Service Component Architecture (SCA) i procesy BPEL (WID/WPS)
  • odseparowanie kontraktu (interfejsu) od implementacji
  • odseparowanie szczegółów komunikacyjnych od implementacji
Wyjeżdżam z Tarnowa dopiero we wtorek, więc jeśli ktoś reflektuje na spotkanie, proszę o kontakt.

19 lipca 2010

Clojure w aplikacji webowej Java EE 6 z Eclipse Helios, Apache Maven i Apache Tomcat

4 komentarzy
Ufff, udało się! Ależ radości przyniosło mi uruchomienie aplikacji webowej Java EE 6 z logiką napisaną w...Clojure! A później to spisywanie - tego najbardziej nie lubię, kiedy każdy szczegół ma znaczenie i trzeba przerabiać materiał kilkakrotnie. Chciałoby się to po prostu nagrać, zamiast spisywać (ale to po urlopie).

Właśnie ukończyłem prace nad nowym artykułem w moim Wiki - Clojure w aplikacji webowej Java EE 6 z Eclipse Helios, Apache Maven i Apache Tomcat, który przedstawia moje ostatnie doświadczenia z "produkcyjnym" wykorzystaniem Clojure z JEE6. Do całości dorzuciłem jeszcze integrację Eclipse Helios z Apache Maven (przez wtyczkę m2eclipse) i counterclockwise do obsługi Clojure. Powinno się podobać.

Nie przeciągając dłużej (i bez zbytniego zachwalania treści artykułu :-)) wierzę, że każdy znajdzie tam coś dla siebie. Niektórzy poznają Eclipse i jego środowisko (aż dwie wtyczki użyte), niektórzy samo uruchomienie aplikacji JEE6, a inni Clojure z Javą. Zapraszam do lektury i komentowania.

Jeszcze jutro recenzja książki o Springu i w nadchodzący czwartek znikam na długooczekiwany urlop. Jeszcze tylko 2 dni!

23 lutego 2010

Nowy serial "SCA praktycznie" - Zestawienie środowiska z Apache Tuscany i Eclipse IAM

3 komentarzy
Apache TuscanyPisałem o SCA wielokrotnie - cała masa wpisów w kategorii sca, więc przed zbliżającymi się konferencjami - Studenckim Festiwalu Informatycznym (SFI) 11-13. marca w Krakowie oraz 4Developers 26. marca w Poznaniu, ze mną w roli prelegenta o SCA, wystarczyło jedynie (?) odświeżyć sobie wiedzę nt. Apache Tuscany i zmian w nim.

Pomysł narodził się, kiedy w trakcie pisania redbooka (książki o technologiach IBM) dotyczącym IBM WebSphere Application Server V7 Feature Pack for Service Component Architecture (w skrócie SCA FeP) dostałem jednocześnie zaproszenie na obie konferencje. Mając głowę w SCA nie miałem wątpliwości, o czym chciałbym powiedzieć. Jest wiele tematów, które nazwałbym bardziej chwytliwymi i właśnie to był główny powód, dla którego postawiłem na SCA - niewielkie jego użycie w naszych rozwiazaniach. A może okazać się, że niepotrzebnie. Nadchodzą cieplejsze dni - wiosna, a po niej lato (nic odkrywczego), więc niejednemu marzy się większa aktywność poza komputerem. Gdyby tak móc zrzucić część naszych obowiązków na barki kogoś innego?! Albo jeszcze lepiej, gdyby tak coś, a nie ktoś, zrobił za nas większość roboty, na pewno byłoby więcej czasu (który i tak wielu zmarnowałoby na pierdoły w Sieci - biedaczyska :)).

W tym klimacie, pomyślałem sobie, że ja (ów ktoś z poprzedniego akapitu) i SCA (owe coś) damy Wam szansę z artykułem Service Component Architecture (SCA) praktycznie - zestawienie środowiska z Apache Tuscany i Eclipse IAM, z serii "SCA Praktycznie". Nigdy nie zgłębiałem protokołu Atom i nie sądziłem, że kiedykolwiek będę, a tu proszę, wystarczyło kilka pytań przy Redbooku, abym zechciał sprawdzić to w Apache Tuscany - darmowego kontenera SCA. Jeśli dodam, że z nim i binding.atom, możemy praktycznie poznać podejście REST, to nie mam złudzeń, że tyle akronimów wystarczy, aby skłonić Was do lektury. Zajmie niespełna kwadrans, a może zaoszczędzić całe godziny. Chętnie posłucham, czy faktycznie. Komentarze mile widziane - priv, albo do tego wpisu.

p.s. A czy Ty już oddałeś/-aś swój głos na Notatnik w konkursie Bloger 2009 Roku? Ja też lubię prezenty. ;-)

09 października 2009

Uruchomienie zdalnego klienta EJB wyłącznie w oparciu o interfejs biznesowy (bez implementacji)

2 komentarzy
Właśnie takiego obrotu sprawy sobie życzyłem. Publikuję wyniki moich doświadczeń szerszemu gronu z nadzieją, że komukolwiek zechce się poświęcić trochę czasu na prześledzenie mojego toku myślenia i samych wyników. Tak też było w przypadku mojego, ostatniego artykułu Jak długo korzystać z referencji bezstanowego komponentu sesyjnego EJB (na przykładzie EJB 3.0 i GlassFish v3). Jego celem było sprawdzenie zachowania się zdalnej referencji EJB3 podczas niedostępności serwera. Przeoczyłem jednak fakt, że aplikacja kliencka dystrybuowana była nie tylko ze zdalnym interfejsem biznesowym, ale również z jego implementacją jako bezstanowe ziarno sesyjne EJB. Nie długo trzeba było czekać, aby takiemu podejściu zaprotestował Łukasz Lenart:

Jedna uwaga, która ogólnie jest globalna do tego typu przykładów. Mianowicie klientowi dostarczasz nie tylko interfejs ale również implementację jako zależność, przez co używanie serwera aplikacyjnego do zdalnej komunikacji jest zbędnym narzutem. Nigdzie jeszcze nie znalazłem przykładu jak to zrobić bez dostarczania implementacji a tylko sam interfejs. Moje próby potwierdziły tylko, że tego nie da się zrobić w przypadku Glassfisha :-(

Problem, jaki wskazał Łukasz, polegał na dystrybuowaniu zdalnego klienta EJB3 w paczce, która zawierała nie tylko interfejs biznesowy, ale i jego implementację (!) Przyznaję, że nie pomyślałem o takim skonstruowaniu paczki dystrybucyjnej klienta, która nie zawierałaby implementacji komponentu EJB, z którego korzysta. Kiedy przeczytałem komentarz, a szczególnie jego ostatnie zdanie, nie miałem złudzeń czym się zająć.

Ten rodzaj reakcji jest zapewne największym podziękowaniem czytelników - dzielimy się własnymi reakcjami na proponowaną rzeczywistość. W końcu autor mógł nie wiedzieć, że da się lepiej, lub po prostu uważać to za nieistotne. Stwarza się w ten sposób okazję do wymiany doświadczeń w jedną (od autora) i drugą, zwrotną stronę (od czytelników), w której nie ma strony wiodącej (poza stroną inicjującą dyskusję, ale tutaj trudno wskazać, czy sam autor artykułu, czy komentarza nią jest - świetny temat na pracę doktorską z filozofii :-)). Tak czy owak, jest nad czym się pochylić i artykuł spełnia swoją rolę - nie jest jednostronny. Najważniejsze, że przy takim podejściu nikt nie traci, bo ja miałem kolejny temat, a Łukasz et al rozwiązanie. Idziemy tym samym naprzód i kolejne projekty stają jeszcze prostsze technologicznie.

Uwielbiam takie publiczne dywagacje, bo nigdy nie wiadomo z kim przyjdzie mi rozmawiać. W przypadku Łukasza to sprawa jest prosta - dostaje baty w bilarda, więc chciał się odegrać :P Ale nie tylko Łukasz zareagował! Dostałem prywatnie komentarz od Pawła Balczyńskiego, który znalazł błąd w jednym z listingów. Standardowe "U mnie działa" miało przez chwilę zastosowanie, ale fakt faktem błąd był (tylko dlaczego u mnie działało?!). Dzięki Paweł!

Zainteresowanych kolejnym doświadczeniem i jego wynikami zapraszam do lektury nowego artykułu Uruchomienie zdalnego klienta EJB wyłącznie w oparciu o interfejs biznesowy (bez implementacji). Teraz oczekuję kolejnej porcji pomysłów na udoskonalenie warsztatu. Komenatrze mile widziane - na priv, albo w komentarzu do tego wpisu.

03 października 2009

default-* execution dla różnych konfiguracji wtyczek w Apache Maven 2.2.1

7 komentarzy
Podczas moich ostatnich wojaży z projektami zarządzanymi Apache Maven 2 potrzebowałem możliwości zdefiniowania różnych konfiguracji dla wtyczki maven-surefire-plugin. Początkowo rozważałem taką konfigurację:
 <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/WyswietlanieKomunikatowClientTest.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>uruchom-WyswietlanieKomunikatowClientTest</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/WyswietlanieKomunikatowClientTest.java</include>
</includes>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
która oznacza, że domyślne wykonanie wtyczki, np. podczas wykonania mvn install, wykluczy wykonanie testów z WyswietlanieKomunikatowClientTest, podczas gdy uruchomienie mvn integration-test, albo wszystkich faz kolejnych, tj. verify, install czy deploy, już tak (warto zajrzeć na strony Introduction to the Build Lifecycle i Guide to Configuring Plug-ins#Configuring Build Plugins z dokumentacji Apache Maven, jeśli tematy są niejasne). I tutaj właśnie pojawił się problem - chcąc wykluczyć WyswietlanieKomunikatowClientTest musiałem wykonywać fazy niższe niż integration-test, a one wykluczają install. I na odwrót, wykonanie install wykona integration-test, a to nie było mi na rękę.

Zacząłem przeszukiwać Internet w poszukiwaniu rozwiązania dla konfiguracji bez phase w ramach execution wtyczki. Sądziłem, że gdzieś wokół takiego myślenia powinienem znaleźć rozwiązanie. I jakież było moje zdumienie, kiedy trafiłem na dokument Default Plugin Execution IDs, gdzie przeczytałem o podobnych dywagacjach. To odpowiadało moim potrzebom! Lektura dokumentu upewniła mnie, że mam szansę coś znaleźć w Mavenie. Na końcu dokumentu, w sekcji References, było wskazanie na dwa zgłoszenia JIRA dla Apache Maven. Pierwsze MNG-3401 niezwykle obiecujące, ale kolejne MNG-3203 odpowiadało dokładnie temu, czego poszukiwałem. Oba rozwiązane tyle tylko, że..."This should work both in Maven 2.2.0 and in Maven 3.x". U mnie niestety Maven w wersji 2.1.0:
 $ mvn -v
Apache Maven 2.1.0 (r755702; 2009-03-18 20:10:27+0100)
Java version: 1.6.0_14
Java home: c:\apps\java6\jre
Default locale: en_PL, platform encoding: Cp1250
OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"
Sądziłem, że pracuję z najnowszą wersją Mavena, więc nietrudno sobie wyobrazić, jak wielkie zrobiłem oczy, kiedy zobaczyłem, że wersja 2.2.1 jest już dostępna. To było dokładnie to, czego poszukiwałem. Rozwiązanie na miarę. Instalacja nowej wersji Apache Maven 2.2.1
 $ mvn -v
Apache Maven 2.2.1 (r801777; 2009-08-06 21:16:01+0200)
Java version: 1.6.0_14
Java home: c:\apps\java6\jre
Default locale: en_PL, platform encoding: Cp1250
OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"
zmiana konfiguracji projektu na następującą:
 <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<excludes>
<exclude>**/WyswietlanieKomunikatowKlientTest.java</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>default-test</id>
<configuration>
<includes>
<include>**/WyswietlanieKomunikatowKlientTest.java</include>
</includes>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
i jestem w domu! Problem rozwiązany! Teraz każdorazowe uruchomienie mvn install wykona konfigurację o identyfikatorze default-cli, a każdorazowe wykonanie mvn test, czyli dosłowne uruchomienie wtyczki surefire, która jest związana z fazą test, wykona konfigurację default-test. Dokładnie tak, jak sobie życzyłem. Warto zajrzeć do przykładowego wykonania obu poleceń i prześledzić wykonywanie wtyczek i ich execution, aby dokładnie poznać różnicę między nimi. Nie ma to jak rozwiązanie problemu w przysłowiowe 5 minut - dobrze zadane zapytanie w Google...bezcenne! :)

p.s. Jak tak dalej pójdzie, to niedługo zejdę na serce. Tyle wrażeń jednego dnia na pewno niekorzystanie wpływa na moje zdrowie :) A to tylko przy takim, pojedynczym wydarzeniu, a przecież nie było ono moim jedynym. Informatycy to strasznie podatny na zawał serca lud ;-)

p.s.2. Skoro przy temacie zarządzania projektami, to natrafiłem ostatnio na gradle. Używa ktoś tego? Chętnie wysłucham wrażeń. Komentarze, listy na priv mile widziane.

12 czerwca 2009

OpenEJB 3.1.x, EJB 3.1, @ApplicationException oraz maven.surefire.debug

1 komentarzy
Pewnie zastanawiasz się, skąd ta różnorodność tematyczna w temacie, co? Dla mnie też było to niemałym zaskoczeniem, kiedy uzmysłowiłem sobie, ile rozwiązań przewinęło mi się dzisiaj, aby rozwiązać wydawałoby się początkowo banalne zgłoszenie OPENEJB-980 @ApplicationException inheritance. Najpierw sądziłem, że to kwestia prześwietlenia dostępnych klas w poszukiwaniu adnotacji @ApplicationException. I tutaj pierwsze bliższe spotkanie z ASM, który wykorzystywany jest w Apache XBean do prześwietlania klas bez konieczności ładowania ich do pamięci JVM z użyciem Reflection API. Wystarczy uruchomić ASM, który poprzez wykorzystanie wzorca projektowego Visitor pozwala na gromadzenie informacji o przetwarzanej klasie. W ten sposób do pamięci PermGen, gdzie trzymane są wszystkie definicje wczytanych klas, nie trafiają definicje, które nie są w użyciu i nie puchnie ona niepotrzebnie.

Miałem już listę klas, które są oznaczone adnotacją @ApplicationException oraz ich potomków. Przyszła więc pora na obsługę samego wyjątku, który niezgodnie z zasadami mechanizmu adnotacji w Javie powinien być oznaczony przez @java.lang.annotation.Inherited, gdyby miał być faktycznie dziedziczony (zdanie w 3. trybie warunkowym z opuszczeniem "if" możecie znaleźć w komentarzu Davida Blevinsa do zgłoszenia - "Had the annotation intended to be inherited it would have been annotated with @Inherited which causes the annotation to be propagated to all the subclasses as described"). W rzeczywistości jednak taka zmiana trafiła do specyfikacji EJB 3.1, w której, mimo, że adnotacja !ApplicationException nie jest @Inherited może taką być przez element inherited z wartością logiczną (domyślnie jest true, czyli jest propagowany w dół hierarchii dziedziczenia). W swoim komentarzu, Dave zaprezentował krótki przykład, który pokazuje, gdzie jest problem (początkowo miałem problemy z dokładnym zrozumieniem tematu, aż do tej chwili, kiedy pojawił się ten przykład - może i Tobie się przyda, o czym ja).

Zajrzałem do specyfikacji EJB 3.1 PFD (ang. Proposed Final Draft) z 24. lutego 2009, rozdział "14.2.1 Application Exceptions" (str. 378). W EJB 3.1, przypisanie wyjątku kontrolowanego (ang. checked exception) jako wyjątku aplikacyjnego dotyczy również wszystkich wyjatków pochodnych. Wystarczy jednak skorzystać z elementu inherited z wartością false, aby dziedziczenie wyłączyć (alternatywnie można użyć elementu application-exception w deskryptorze XML). Zastanawiam się skąd ta decyzja. Pewnie nadanie @Inherited do adnotacji @ApplicationException złamałoby kontrakt, a dodanie elementu już nie (?)

Na stronie 380 specyfikacji EJB 3.1 PFD pokazany jest przykład z wyjątkiem aplikacyjnym dziedziczonym (ExceptionA) oraz nie (ExceptionC). Kolejne miejsce do nauki przez przykład. Jest krótki, więc zdecydowanie nie ma się nad czym zastanawiać, tylko zapoznać się z nim.

Wprowadziłem odpowiednie zmiany w Apache OpenEJB, więc kolejne wersje będą to honorowały (na razie ignorowana jest wartość "inherited" i wszystko jest tak, jakby było "inherited=true"). Jako gotowy przykład do uruchomienia proponuję zajrzeć do aplikacji demonstracyjnej towarzyszącej zmianie applicationexception. Mając klienta Subversion oraz Apache Maven 2, wystarczy
 svn co https://svn.apache.org/repos/asf/openejb/trunk/openejb3/examples/applicationexception
cd applicationexception
mvn test
UWAGA: Zmiany potrzebne do uruchomienia przykładu nie są jeszcze rozpropagowane po repozytoriach mavenowych, więc z pewnością zakończy się BUILD FAILURE. Dodatkowo, początkowe uruchomienie pobiera wiele (chyba zdecydowanie za wiele) zależności ze zdalnych repozytoriów, więc przygotuj się na dłuższą przerwę. Najlepiej po prostu ściągnąć źródła OpenEJB i give it a try.

Pozostaje jeszcze wyjaśnić maven.surefire.debug z tytułu wpisu. Pisząc test jednostkowy do tej zmiany użyłem adnotacji @Test(expected = ValueRequiredException.class), która instruuje JUnit, że w teście oczekuje się zgłoszenia wyjątku ValueRequiredException. Początkowo nie wiedziałem, dlaczego ta zmiana to za mało i każdorazowe uruchomienie Mavena kończyły się BUILD ERROR. Doprowadzało mnie to do szału, aż znalazłem rozwiązanie - wyrzucenie "extends TestCase" z definicji klasy testowej ThrowBusinessExceptionImplTest (!) Jeszcze uaktualniłem JUnit do wersji 4.6 oraz maven-surefire-plugin do 2.4.2 i wszystko zaczęło działać poprawnie. W międzyczasie rozglądałem się za dostępnymi, specjalnymi ustawieniami w Mavenie, które mogłyby mi pomóc (wiedziałem, że to może być coś związanego z Mavenem, albo samym testem, ale nie wiedziałem dokładnie co), aż natrafiłem na stronę Debugging Tests. Zamiast definiować konfigurację śledzenia (debugowania) testu w pom.xml wystarczy skorzystać z parametru maven.surefire.debug. Test jest zatrzymywany i oczekuje na podłączenie klienta JDWP...ekhm...zdalnego debuggera. Można również skorzystać z mvnDebug i parametru forkMode, o czym również nie wiedziałem. Do tej pory, kopiowałem konfigurację uruchomienia z włączonym debug do wtyczki maven-surefire-plugin w pom.xml, a tu proszę, rozwiązanie gotowe i pod ręką.

Ze zgłoszenia OPENEJB-980 pozostaje mi jeszcze obsłużyć element inherited w @ApplicationException i temat będzie całkowicie zamknięty. Uwagi mile widziane i pożądane. Nie jest to zmiana najwyższych lotów, a wpisy Łukasza Lenarta Jak cię widzą, tak cię piszą czy Pawła Szulca Testing and Testable Code Presentation tylko mnie utwierdziły, że jeszcze wiele przede mną w temacie dobrych testów jednostkowych.

Z ciekawostek na koniec - podczas testowania przykładu z pustym repozytorium mavenowym zauważyłem, że Apache Maven 2.1.0 pobiera zależności...równolegle (chyba tylko tak mogę interpretować, co zauważyłem - oznaczone na czerwono poniżej). A może jednak nie? To co miałoby to być?!

15 maja 2009

Rozwiązywanie niezgodności binarnych z maven-shade-plugin

2 komentarzy
Moim ciągle niezrealizowanym zadaniem jest poznanie dwóch rozwiązań do zmiany bajtkodu (klas javowych w postaci binarnej) - asm i cglib. Pamiętam wystąpienie Piotra Kobzdy na ten temat podczas Javarsovii 2007, w którym chciałem uczestniczyć bardziej aktywniej niż to było mi dane - obowiązki organizatora i moja wrodzona natura gaduły dały się poznać. Skończyło się na krótkich urywkach wystąpienia Piotra i temat zamarł jako zbyt zaawansowany, a może po prostu z powodu niewielkiej wartości praktycznej - w końcu asm/cglib nie są tak często wykorzystywane wprost jak chociażby równie ciekawe rozwiązania typu Grails. Jest wiele podobnych tematów, których znajomość pomaga, ale nie będąc warunkiem koniecznym odkłada się je na półkę na bliżej nieokreśloną przyszłość. Możnaby mnożyć takich perełek bez liku, chociażby programowanie w języku funkcyjnym, albo nawet tak podstawowe jak wzorce projektowe. Znajomość innego myślenia pomaga w zrozumieniu problemów, w których nie mają zastosowania, ale przez swoją odmienność prowokują do bardziej wytężonego wysiłku umysłowego i wtedy, nieoczekiwanie otwierają się nieużywane dotąd obszary naszego umysłu. Przypomina mi to rozmowę z nowicjuszami, których często zbywa się sądząc, że mogą jedynie zająć czas, ale którzy, przez swoje nietypowe pytania dotykające podstaw, okazują się być idealnymi katalizatorami myślenia - jeśli tylko wytrwamy z ich niewiedzą możemy paradoksalnie uporządkować sobie swoją (nie)wiedzę. Paradoksalnie, Ci niewprawieni w boju, owi nowicjusze nie są jeszcze tak ograniczeni jak my - wiedza rozwija, ale jednocześnie nakłada na nas swoje ograniczenia.

Zaletą pracy przy projektach otwartych jest możliwość rozwiązywania problemów na długo wcześniej niż pojawią się we własnych projektach komercyjnych. Mamy możliwość doświadczenia innego sposobu myślenia i pojawiają się zaskakujące rozwiązania - zaskakujące swoją prostotą i odmiennością. To każdy lubi.

Powrót do mojej działalności w Apache OpenEJB zacząłem od czyszczenia mojego backlogu. Lista nie jest pokaźna, ale niezwykle leciwa. Jednym z zadań było rozwiązanie problemu niezgodności binarnej ASM między wersjami 1.5.3 a nowszymi, które wykorzystywane są przez OpenEJB i inne projekty, np. wszechobecny Hibernate, które mogłyby być użyte wspólnie z nim w ramach pojedynczej aplikacji, co nieuchronnie prowadzi do błędu:

java.lang.NoSuchMethodError: org.objectweb.asm.ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V

Jest to odprysk prac nad wsparciem dla @ApplicationException - Optional @ApplicationException inheritance, gdzie wymagana jest nowa wersja Apache XBean, która przychodzi z asm/cglib, więc w połączeniu ze wspomnianym Hibernate może narobić niezłego zamieszania. Jest kilka opcji rozwiązania i panowie ze SpringSource opisali trzy - ASM version incompatibilities, using Spring @Autowired with Hibernate. Jeśli Twój projekt jest oparty na Apache Maven możesz skorzystać z kolejnego rozwiazania opartego na wtyczce maven-shade-plugin, co opisałem w artykule Rozwiązywanie niezgodności binarnych z maven-shade-plugin. Znajdziesz w nim opis problemu i przedstawienie rozwiązania. Z wiadomych względów zdecydowanie polecam! :)

13 maja 2009

[WARNING] Using platform encoding... i project.build.sourceEncoding w Apache Maven 2.1.0

5 komentarzy
Migracja do nowej wersji Apache Maven 2.1.0 nie powinna nastręczać wielu problemów, ale nawet przy ich braku zaleca się przejrzenie komunikatów z budowania projektu. Z pewnością spotkamy się z nowym komunikatem na poziomie WARNING:

[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!

Pojawia się on dwukrotnie w trakcie wykonania wtyczki maven-resources-plugin. Wystarczy jednak dodać do pom.xml następujący wycinek:
 <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
aby o temacie zapomnieć. Więcej szczegółów bezpośrednio u źródła w POM Element for Source File Encoding.

Dla zainteresowanych - stworzenie nowego projektu mavenowego to polecenie:
 $ mvn archetype:generate -B \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.0 \
-DgroupId=pl.jaceklaskowski -DartifactId=maven-encoding -Dversion=1.0
Teraz wystarczy zbudować projekt poleceniem mvn package (zamiast mvn install, który kopiuje artefakt projektowy do lokalnego repozytorium):
 $ mvn package
...
[INFO] [resources:resources]
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
...
[INFO] [resources:testResources]
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
...
[INFO] Building jar: c:\projs\sandbox\maven-encoding\target\maven-encoding-1.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
Po dodaniu project.build.sourceEncoding do pom.xml WARNING idzie w odstawkę. Od tej pory, dzienniki powinny być czyste.

11 maja 2009

Apache Maven: ${basedir} w pom.xml w projekcie wielomodułowym

3 komentarzy
To już nie pierwszy raz, kiedy testy jednostkowe w projekcie zarządzanym przez Apache Maven działają, kiedy są uruchomione z katalogu projektu, ale już nie, kiedy są uruchomione z katalogu projektu macierzystego. Za przykład możnaby wziąć projekt examples/webservices-ws-security z Apache OpenEJB, który wywołuje sun.security.tools.KeyTool - narzędzie, które jest narzędziem zewnętrznym w stosunku do mavena i dla którego ścieżki względne w pom.xml mają znaczenie. Jeśli więc umieścimy taki fragment w pom.xml:
 <property name="server.alias" value="serveralias"/>
<property name="server.keypass" value="serverPassword"/>
<property name="server.keystore" value="target/classes/META-INF/serverStore.jks"/>
<property name="server.storepass" value="keystorePass"/>
<property name="server.dname" value="'cn=serveralias'"/>

<java classname="sun.security.tools.KeyTool">
<arg line="-genkey" />
<arg line="-alias ${server.alias}" />
<arg line="-keypass ${server.keypass}" />
<arg line="-keystore ${server.keystore}" />
<arg line="-storepass ${server.storepass}" />
<arg line="-dname ${server.dname}" />
<arg line="-keyalg ${keyalg}" />
<permissions>
<grant class="java.security.AllPermission" />
</permissions>
</java>
to oczywiście zmienna server.keystore jest względna i czuła na miejsce uruchomienia poleceń mvn - w katalogu projektu wszystko jest cacy, ale już poza nim (chociażby w katalogu wyżej) pojawi się błąd braku wskazanego pliku (ścieżka wskaże nieistniejący plik, a nawet poszczególne katalogi)!

Szczęśliwie, rozwiązanie jest pod ręką - zmienna ${basedir}. Wystarczy poprzedzić ścieżki względne zmienną ${basedir}, aby uniezależnić je od miejsca wykonania poleceń w projekcie.

Ostatecznie zmiana dotyczy jedynie server.keystore z ${basedir}:
 <property name="server.keystore" value="${basedir}/target/classes/META-INF/serverStore.jks"/>
Poza tym, żadnych innych zmian.

Więcej o ${basedir} w dokumentacji Apache Maven - POM Reference::The BaseBuild Element Set oraz Maven Getting Started Guide (szukaj "basedir").

Wciąż pod wpływem Apache Maven, czy może powrót do korzeni, czyli Apache Ant z Apache Ivy? A może Apache Buildr? Zauważam coraz częściej potrzebę łączenia kilku narzędzi do zarządzania projektem, czyli Maven dobry, ale jest wciąż miejsce dla Ant, a nieśmiało zerkam w stronę Buildr.

15 września 2008

Bundle.findEntries() i spring-osgi-bundle-archetype w akcji - monitorowanie pakunków OSGi z określoną strukturą katalogową

2 komentarzy
Spring Dynamic Modules (dalej Spring-DM) umożliwia tworzenie ziaren springowych jako pakunki OSGi umożliwiając skorzystanie z cech obu środowisk - Spring Framework i OSGi. Tak określiłbym motto projektu. Jednym z elementów wspomagających tworzenie aplikacji korporacyjnych ze Spring-DM jest stworzenie środowiska uruchomieniowego, w którym cechy OSGi są integralną częścią środowiska. W ten sposób aplikacja webowa może być dystrybuowana w postaci pakunku (wystarczy jedynie dopisanie kilku nagłówków w META-INF/MANIFEST.MF) i uruchomiona w ramach Platformy OSGi (Equinox, Felix czy Knopflerfish). Teoretycznie (jeszcze) możemy sobie wyobrazić sytuację, w której poszczególne części aplikacji są dystrybuowane jako pakunki OSGi, które z kolei składają się na większy pakunek OSGi będący nota bene aplikacją webową. "A po co?" - możnaby zapytać. Odpowiedź sama się nasuwa - wprowadzenie/podniesienie modularności w aplikacji. Jeśli weźmiemy za przykład aplikację webową, to jej jedną z części mogą być servlety zgrupowane jako pakunek OSGi, który dzięki mechanizmom OSGi moglibyśmy podmienić...w trakcie działania naszej aplikacji (!) Czyż nie jest to cecha, której wprowadzenia pożądalibyśmy w naszych aplikacjach? Z pewnością!

W moim nowym artykule Bundle.findEntries() i spring-osgi-bundle-archetype w akcji - monitorowanie pakunków OSGi z określoną strukturą katalogową przedstawiłem funkcjonowanie metody org.osgi.framework.Bundle.findEntries(), której zadaniem jest zwrócenie zawartości odpytywanego pakunku jako listę URLi. W ten sposób możemy prześwietlić zawartość pakunków i poznać ich strukturę katalogową. Dodając do tego możliwość rejestracji słuchacza zdarzeń instalacja/odinstalowanie pakunków przy pomocy org.osgi.framework.BundleListener mamy doskonały sposób na monitorowanie zmian na Platformie OSGi i weryfikację, czy zainstalowany właśnie pakunek nie jest przypadkiem specjalnego traktowania przez naszą aplikację monitorującą. Zgłoszenie zdarzenia podmiany (=odinstalowania i instalacji) pakunku ponownie powoduje wzbudzenie BundleListener i wykonanie właściwej akcji. Mam wrażenie, że jest to jedyny tego typu szkielet aplikacyjny, który znosi z nas obowiązek własnoręcznego tworzenia mechanizmu monitorowania zmian w środowisku - w OSGi wystarczy jedynie implementacja BundleListener. Więcej w samym artykule. Miłej lektury!

01 września 2008

Mavenowe pluginGroup - sposób na skrócenie nazw wtyczek

0 komentarzy
Podczas mojej ponad 2-tygodniowej walki z migracją aplikacji opartej o Struts1 do JSF pojawiło się kilka rzeczy, z którymi przyszło mi się borykać po raz pierwszy (ech, cudnie móc tak godzinami nie wiedzieć, co się dzieje z aplikacją, kiedy to właśnie powinna działać, szczególnie przed prezentacją klientowi ;-)). Jednym z tych najbardziej zmuszających do wysiłku umysłowego wyzwań było połączenie stron JSP ("typowe" JSF) z XHTML (JSF w wykonaniu facelets). Każdorazowe przeniesienie funkcjonalności z jednej technologii "wizualizacji" stron na drugą, to po prostu hard-core, a w tle jeszcze Struts. Nawet zaczęło mnie to irytować, a aplikacja to zwykły CRUD, gdzie Struts był niezwykle niechlujnie wykorzystany. Aż mi się szkoda zrobiło tego Strutsa ;-) Ale nie o tym ja.

Tak podczas tych zmagań natrafiłem na ciekawostkę, której rozwiązania nie sądziłem, że w ogóle mógłbym oczekiwać - uruchamianie wtyczek Apache Maven 2 spoza org.apache.maven.plugins z linii poleceń bez deklaracji w pom.xml. Często przychodzi mi uruchamiać wtyczki mavenowe w ten sposób, więc z tym większą ulgą przyjąłem nowinę, że można skrócić nazwę wtyczki i...moje cierpienia.
 jlaskowski@work ~
$ mvn jetty:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin 'org.apache.maven.plugins:maven-jetty-plugin' does not exist or no valid version could be found
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
Innymi słowy, wtyczki mavenowe spoza groupId - org.apache.maven.plugins - nie są rozpozna(wa)ne domyślnie przez Mavena. Można oczywiście uruchomić wtyczkę podając jej pełną nazwę w formacie groupId:artifactId:goal, tj. w tym przypadku byłoby to mvn org.mortbay.jetty:jetty-maven-plugin:run, ale chciałoby się krócej, nieprawdaż? (w tym przypadku niepomyślne wykonanie nie było spowodowane nieprecyzyjnym wskazaniem na wtyczkę, ale po prostu brakiem środowiska do jej uruchomienia, czyli brakiem projektu mavenowego).
 jlaskowski@work ~
$ mvn org.mortbay.jetty:jetty-maven-plugin:run
[INFO] Scanning for projects...
[INFO] artifact org.mortbay.jetty:jetty-maven-plugin: checking for updates from central
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [org.mortbay.jetty:jetty-maven-plugin:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing jetty:run
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Cannot execute mojo: resources. It requires a project with an existing pom.xml, but the build is not using one.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
Okazuje się, że rozwiązaniem jest...zapoznanie się z dokumentacją (przysiągłbym, że ją czytałem, a przynajmniej przeglądałem). Na rozwiązanie najpierw trafiłem w dokumentacji wtyczki maven-jetty-plugin (odszukaj "Note: Maven by default looks for plugins"), a później wystarczyło już poszukać pluginGroups w Configuring Maven to Search for Plugins z pomocą Settings Reference i ostatecznie uzupełniłem settings.xml o następującą sekcję pluginGroups:
 <?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<pluginGroups>
<pluginGroup>org.mortbay.jetty</pluginGroup>
</pluginGroups>
</settings>
i wykonanie "skrótowe" wtyczki jetty-maven-plugin z mvn jetty:run kończy się już pomyślnie (z dokładnością do BUILD ERROR z powodu braku projektu).
 jlaskowski@work ~
$ mvn jetty:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] org.mortbay.jetty: checking for updates from central
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [jetty:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing jetty:run
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Cannot execute mojo: resources. It requires a project with an existing pom.xml, but the build is not using one.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
Ciekawe ilu osobom owe "wydłużone" wskazanie wtyczek z linii poleceń sprawiało trudność w zaakceptowaniu zachowania Mavena?

23 sierpnia 2008

maven-jetty-plugin i JPA ze springowym SimpleLoadTimeWeaver

0 komentarzy
W mojej krucjacie ku stworzeniu aplikacji webowej z użyciem minimalnego zestawu uruchomieniowego, z facelets oraz maven-jetty-plugin dotarłem do momentu, w którym koniecznym stało się wykorzystanie jakiegoś rozwiązania ORM (mapującego dane relacyjne na obiektowe i vice versa). Nie będę zbyt odkrywczy, jeśli napiszę, że padło na JPA (Java Persistence API). Przypomnę, że nie mam do dyspozycji serwera aplikacyjnego Java EE 5, np. Apache Geronimo, więc postanowiłem skorzystać ze Spring Framework. Zwrócenie się ku Spring Framework było podyktowane chęcią utrzymania minimalnego zestawu uruchomieniowego, którego uruchomienie sprowadzało się do mvn clean jetty:run. Konfigurację JPA oparłem na opisanej w artykule Apache Wicket z JPA z pomocą Spring Framework i Apache Maven 2. Jedyną znaczącą zmianą w stosunku do konfiguracji z artykułu było skorzystanie ze Spring Framework 2.5.5. Ku mojemu zaskoczeniu pierwsze uruchomienie zakończyło się wyjątkiem:
 31  faceletsPU  WARN   [main] openjpa.Runtime - An error occurred while registering a ClassTransformer with PersistenceUnitInfo: 
name 'faceletsPU', root URL [file:/C:/projs/sandbox/facelets-spring/target/classes/].
The error is logged along with this warning. Load-time class transformation will not be available.
java.lang.IllegalStateException: Must start with Java agent to use InstrumentationLoadTimeWeaver. See Spring documentation.
at org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver.addTransformer(InstrumentationLoadTimeWeaver.java:88)
at org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer(SpringPersistenceUnitInfo.java:80)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createContainerEntityManagerFactory(PersistenceProviderImpl.java:126)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createContainerEntityManagerFactory(PersistenceProviderImpl.java:53)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:224)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1368)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
Rozwiązaniem okazało się zmiana atrybutu loadTimeWeaver w konfiguracji org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean na org.springframework.instrument.classloading.SimpleLoadTimeWeaver, czyli ostatecznie sekcja dotycząca konfiguracji fabryki zarządcy utrwalania w applicationContext.xml wygląda następująco:
 <bean id="entityManagerFactory" 
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="oracleDS" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
</property>
</bean>
Więcej informacji o konfiguracji JPA w Spring Framework, w rozdziale 12.6 "JPA" dokumentacji The Spring Framework - Reference Documentation.

22 sierpnia 2008

Blogorrhea, konfiguracja resource-ref dla Jetty z maven-jetty-plugin oraz APINI Knowledge Base

0 komentarzy
Zatem już wiadomo - cierpię na dolegliwość zwaną Blogorrhea, która objawia się "wyjątkową aktywnością blogera publikującego w jakimś okresie dużą liczbę wpisów". Czyżbym był jedynym, który cierpi na tę dolegliwość, czyli innymi słowy doświadcza tylu ciekawostek dziennie, że ma, o czym pisać i chce mu się tym podzielić z innymi?! Nie sądzę. Dobrze jednak wiedzieć, na co się choruje i spróbować wyleczyć (jeśli uleczalne) niż cierpieć i nie móc temu zaradzić (tu, taka analogia do osób chcących, ale niemogących - chociaż może lepiej nie pisać, niż trafić do kategorii blogasków ;-)). Skąd taka cisza o tym serwisie helionica.pl? Czyżby Helion nie wierzył w cel jego popularyzacji?! Nawet w książkach z Helionu nie zauważyłem wskazania na ten serwis. Ja tam zamierzam skorzystać z tej wiedzy przy kolejnych moich artykułach. Na Helionicę natrafiłem czytając artykuł Radka Holewy Spring i wstrzykiwanie zależności między bean'ami o różnych zasięgach, w którym można znaleźć wiele polskich odpowiedników dla terminów angielskojęzycznych. Nawet znalazło się miejsce dla rusztowania aplikacyjnego jako odpowiednika framework, a sądziłem, że termin pójdzie w odstawkę. Gratuluję Radek dobrego smaku :P

Podczas tworzenia aplikacji webowej z facelets w roli głównej i wspierającym Apache Maven 2, testowym środowiskiem uruchomieniowym naturalnie stał się Jetty poprzez maven-jetty-plugin. Wystarczy zdefiniować następującą sekcję plugin w pom.xml i można uruchamiać aplikację z mvn jetty:run.
 <plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<systemProperties>
<systemProperty>
<name>jetty.home</name>
<value>./src</value>
</systemProperty>
<systemProperty>
<name>java.security.auth.login.config</name>
<value>src/etc/login.conf</value>
</systemProperty>
</systemProperties>
<jettyConfig>src/etc/jetty.xml</jettyConfig>
</configuration>
</plugin>
Zmiana strony xhtml nie wymaga ponownego uruchomienia Jetty (cf. scanIntervalSeconds), ale klasy niestety już tak. Mimo wszystko możliwość testowania aplikacji w ten sposób znosi początkowe trudności konfiguracji serwera aplikacyjnego (co może stanowić nie lada wyzwanie czasowe). Owa błogość trwała do momentu, kiedy byłem zmuszony skonfigurować dostęp do bazy danych. Powiało grozą, gdyż nigdy wcześniej nie konfigurowałem Jetty, a już na pewno nie w trybie uruchamiania z poziomu wtyczki maven-jetty-plugin. Szczęśliwie strach ma wielkie oczy i konfiguracja dostępu do bazy danych, to dodanie następujących sekcji Array oraz New do pliku wskazanego przez jettyConfig dla maven-jetty-plugin w pom.xml:
 <Array id="plusConfig" type="java.lang.String">
<Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
<Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
<Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
<Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
</Array>
<New id="facelets-webapp" class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="ConfigurationClasses">
<Ref id="plusConfig" />
</Set>
</New>
<New id="faceletsDB" class="org.mortbay.jetty.plus.naming.Resource">
<Arg>jdbc/faceletsDB</Arg>
<Arg>
<New class="oracle.jdbc.pool.OracleConnectionPoolDataSource">
<Set name="URL">jdbc:oracle:thin:@localhost:1521:DEVEL</Set>
<Set name="User">jacek</Set>
<Set name="Password">laskowski</Set>
</New>
</Arg>
</New>
Oczywiście konieczne jest dodanie klas sterownika bazy danych do ścieżki klas (ang. classpath) Jetty (w moim przypadku konieczne było dodanie ojdbc14.jar dla Oracle 8.2.0.8). Dodanie biblioteki do lokalnego repozytorium mavenowego poleceniem mvn install:install-file:
 jlaskowski@work /cygdrive/c
$ mvn install:install-file -Dfile=ojdbc14.jar -DgroupId=oracle \
-DartifactId=ojdbc14 -Dversion=9.2.0.8 -Dpackaging=jar
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'install'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [install:install-file] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [install:install-file]
[INFO] Installing c:\ojdbc14.jar to C:\.m2\oracle\ojdbc14\9.2.0.8\ojdbc14-9.2.0.8.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
i następującej sekcji dependencies do plugin dla maven-jetty-plugin w pom.xml:
 <dependencies>
<dependency>
<groupId>oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>9.2.0.8</version>
</dependency>
</dependencies>
kończy pomyślnie temat widoczności klas przez Jetty. Istnieje również możliwość dodania sterownika bazodanowego jako zależności maven-jetty-plugin z kwalifikatorem zasięgu - scope - z wartością system, co zniesie konieczność jego instalacji do lokalnego repozytorium mavena.

Na koniec (a może właśnie od tego powinniśmy zacząć, aby osoba konfigurująca środowisko dla naszej aplikacji była świadoma wymagania) odnotowujemy referencję bazy danych używaną w aplikacji poprzez resource-ref w WEB-INF/web.xml:
 <resource-ref>
<res-ref-name>jdbc/faceletsDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
I tyle. Mogę kontynuować pracę z facelets i maven wzbogaconymi o dostęp do bazy Oracle. Więcej informacji o konfiguracji JNDI w dokumentacji Jetty - Using JNDI Resources with jetty6.

Dostałem na skrzynkę wskazanie na ciekawy produkt APINI Knowledge Base polskiej firmy Verax Systems (nie obawiam się podejrzeń o ukrytą kryptoreklamę, gdyż robię to całkowicie świadomię, aby promować polskie innowacje). Autor wiadomości (pracownik firmy) pisał: "Jacku, przy okazji przeszukiwania Internetu zauważyłem twój pomysł na system Knowledge Base. Mieliśmy podobny problem z gromadzeniem i wymiana informacji, a ponieważ jesteśmy firmą produkującą soft, napisaliśmy na własne potrzeby i nie tylko taki system." I dalej "Szczególnie zachęcam do zapoznania się z multimedialną prezentacją systemu tj. z krótkim filmem o podstawowych funkcjonalnościach systemu oraz o korzyściach płynących z zastosowania tego rozwiązania.". Zabrało mi to niecałe 5 minut (przy aktualnie użytkowanym, niezwykle wolnym łączu w sieci UPC) i przyznaję, że system zrobił na mnie niezwykle pozytywne wrażenie. Zastanawiałem się jak pozycjonują się względem Confluence Wiki czy MediaWiki, ale niestety nie otrzymałem odpowiedzi, więc temat otwarty. Mimo wszystko pomyślałem, że warto wypromować produkt polskiej firmy (chociaż nazwa i domena *.com wcale na to nie wskazują). Chciałbym móc napisać, że jest darmowa wersja dla społeczności javowej, ale nic o tym nie wiem. Może spróbować wykorzystać produkt do stworzenia wspomnianej bazy wiedzy javowej? Czy może lepiej pozostać przy darmowej dla niedochodowych organizacji licencji dla Confluence Wiki, albo wręcz użyć MediaWiki?

14 lipca 2008

Klasyfikatory w Maven 2 oraz polonizacja NetBeans IDE

2 komentarzy
Już jakiś czas minął od zgłoszenia usprawnienia związanego z niedostępnością dokumentacji javadoc w dystrybucji Apache Wicket (WICKET-1587 Include javadoc in the distro). Okazało się, że właśnie dzisiaj zamknięto moje zgłoszenie jako Duplicate ze wskazaniem na kolejne zgłoszenie WICKET-543 need javadocs embedded in the Wicket 1.3 zip file. W WICKET-543 zgłoszenie kończy się wskazaniem na plik dokumentacji w publicznym repozytorium mavenowym Wicketa - http://repo1.maven.org/maven2/org/apache/wicket/wicket. Wystarczy, więc pobrać dokumentację javadoc (lub jeszcze lepiej kodów źródłowych, które są tam również umieszczone) i sprawa wydaje się zamknięta.

W/g mnie nie rozwiązuje to głównego problemu niedostępności dokumentacji w samej paczce dystrybucyjnej Wicketa, bo nie wszyscy przecież korzystają z Mavena do zarządzania projektami, a nawet pracując z nim można nie zorientować się, gdzie jest dostępna dokumentacja do pobrania. Może jest to jednak efekt "nowych" czasów, gdzie jeśli nie korzystasz z Mavena toś...i tu należałoby umieścić coś niestosownego, bo przecież każdy wie jak z niego korzystać, albo jak pobrać plik z jego repozytorium. Nieprawdaż?! Ja jednak należę do tych (nie)szczęśników, którzy zazwyczaj pracują z Mavenem, jeśli idzie o zestawianie projektów poza IDE, więc mogę przychylić się do tego rozwiązania jako satysfakcjonujące. W Eclipse dostępna jest wtyczka m2eclipse, która umożliwia pobranie źródeł dla zadanych zależności (Maven > Download Sources), ale już w NetBeans mimo, dostępności wtyczki Mavenide-NetBeans, nie znalazłem podobnej funkcjonalności. Pozostaje rozpoznać temat z poziomu linii poleceń i zdefiniować odpowiednie polecenie dla NetBeans, bądź innego IDE w użyciu, jeśli dedykowane menu nie istnieje.

Rozróżnienie artefaktów pochodzących z pojedyńczego projektu (modułu) odbywa się z użyciem klasyfikatora (ang. classifier), które jest kolejnym elementem rozróżniania artefaktów w Maven 2 zgodnie z zasadą nazewniczą przedstawioną w rozdziale POM Relationships. Najbardziej powszechnym użyciem klasyfikatora to wskazanie pliku z dokumentacją javadoc (klasyfikator: javadoc) oraz źródłami (klasyfikator: sources). Deklaracja zależności w projekcie mavenowym odbywa się w pliku pom.xml, np.:
 <dependencies>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket</artifactId>
<version>1.4-m3</version>
</dependency>
</dependencies>
i dotyczy zazwyczaj artefaktów, które są plikami jar (domyślna wartość dla elementu dependency/type to jar) z pustym klasyfikatorem. Wskazanie na zasób (artefakt) o klasyfikatorze javadoc wymaga skorzystania z elementu classifier z wartością javadoc. Pytanie, które należy w tym momencie zadać, to przypadek użycia, w którym chcielibyśmy skorzystać z możliwości zadeklarowania zależności projektu od klasyfikatora javadoc czy sources (pozostałe klasyfikatory pozostawiam do własnego przemyślenia). Dla przypadku wyłącznego pobrania javadoc czy źródeł z centralnego repozytorium Mavena korzysta się z pomocy dodatkowego parametru konfiguracyjnego wtyczki, która umożliwia skorzystanie z danego typu klasyfikatora (udostępnia rozwiązanie przypadku użycia, w którym dany klasyfikator gra znaczącą rolę).

Weźmy jako przykład pracę z javadoc. Jeśli chciałbym skorzystać z javadoc do umieszczenia jej w dystrybucji mojego projektu skorzystam z wtyczki maven-assembly-plugin, która potrafi "złożyć" plik wynikowy paczki dystrybucyjnej projektu, potencjalnie z dołączeniem dokumentacji javadoc dla wybranej zależności. W przypadku korzystania z dokumentacji javadoc czy źródeł w środowisku Eclipse wtyczka maven-eclipse-plugin generująca definicję projektu eclipsowego na podstawie pom.xml pozwala na określenie wymagania podpięcia javadoc czy źródeł do projektu - parametry -DdownloadJavadocs=true i -DdownloadSources=true, odpowiednio (patrz Attach Library Sources and Javadocs).

Wniosek jest jeden: w zależności od wymagań zazwyczaj nie przyjdzie Tobie skorzystanie z artefaktu o zadanym klasyfikatorze bezpośrednio, a raczej pośrednio, poprzez zależność w pom.xml czy konfigurację wtyczki. Jeśli jednak potrzebujemy pobrać pojedyńczy plik z repozytorium mavenowego, np. z dokumentacją javadoc, wystarczy skorzystać z wget czy podobnego narzędzia. To jednak sprowadza temat do bardzo znanej i lubianej kwestii doboru właściwego narzędzia do danego zadania. Kwesię obsługi javadoc w projekcie mavenowym zdaje się, że mam(y) rozwiązaną.

Kiedy teraz przyjdzie mi pracować z projektem mavenowym w środowisku Eclipse bez pomocy wtyczki m2eclipse wystarczy uruchomić polecenie
 mvn eclipse:eclipse -DdownloadSources=true  -DdownloadJavadocs=true
i zaimportować projekt, aby móc cieszyć się z pomocy kontekstowej javadoc oraz możliwości przejścia do kodów źródłowych dla klas zależności projektowej. Warto było zgłosić usprawnienie do Wicketa, aby w końcu rozpoznać to wszystko. Teraz już wszystko powinno być jasne.

Od kilku dobrych miesięcy trwają prace nad polonizacją NetBeans IDE 6. Prace trwają i mimo nadchodzącej wersji NetBeans IDE 6.5 (od 14-tego rozpoczynają się prace w NetCAT 6.5), wciąż nie ma produkcyjnej wersji NetBeans w języku polskim. Jeśli jesteś zainteresowany/-a posiadaniem spolszczonego NetBeansa i chciał(a)byś mieć swój udział w projekcie tłumaczenia przyłącz się do zespołu polonizującego NetBeans. Proponuję zacząć już dzisiaj.

10 lipca 2008

Mapowanie encji w JPA - Strategia złączeniowa

1 komentarzy
Dobrym miernikiem nabytej wiedzy o Korporacyjnej Javie 5 (Java EE 5) może być podejście do egzaminów SCBCD, SCWCD czy SCEA , ale również aktywne uczestnictwo w grupach dyskusyjnych poruszających tą tematykę. Jedną z takich grup jest grupa dyskusyjna użytkowników serwera aplikacyjnego Java EE 5 - Apache Geronimo - user@geronimo.apache.org. Ostatnie pytanie error writing tuple to database "the owning entity is not mapped" geronimo 2.1.1 zdopingowało mnie do dokładniejszego przyjrzenia się tematowi odwzorowywania hierarchii dziedziczenia obiektowego klas encji na struktury relacyjne w bazie danych. W zasadzie teoretycznie temat został przedstawiony w mojej relacji z lektury specyfikacji Java Persistence API (JPA) - Java Persistence - Rozdział 2 Entities zakończony, ale pewnie z braku przykładów czułem pewien niedosyt.

Tak rozpoczyna się kolejny artykuł mojego autorstwa Mapowanie encji w JPA - Strategia złączeniowa, do lektury którego zapraszam. Uwagi/komentarze i pomysły dalszych materiałów mile widziane. Miłej lektury!