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

27 października 2010

Geronimo, JMX i Groovy

3 komentarzy
Apache GeronimoDostałem zadanie rozpracowania dostępnych obiektów Java Management Extension (JMX) - MBeans - w serwerze aplikacyjnym Apache Geronimo. Osoba zlecająca potrzebowała monitorować Geronimo i kiedy dowiedziałem się o tym, od razu zaproponowałem wykorzystanie JMX. W końcu, po to ta technologia została stworzona.

I przyszło mi stworzyć klienta ("Trzeba było się nie wychylać", ktoś mógłby krzyknąć).

Przeglądając różne materiały dotyczące JMX API, brakowało mi spójnego przykładu. Natchnęło mnie, aby napisać własnego. Chwila namysłu i padło na...Groovy. W końcu do tego typu zadań świetnie się nadaje.

(Gdyby nie fakt, że poszukiwanie rozwiązania trwało i musiałem sobie przypomnieć programowanie w Groovy, zacząłbym od...) Po chwili miałem działające rozwiązanie w groovysh.
import javax.management.ObjectName
import javax.management.remote.JMXConnectorFactory as JmxFactory
import javax.management.remote.JMXConnector as JmxConn
import javax.management.remote.JMXServiceURL as JmxUrl

serverUrl = 'service:jmx:rmi://localhost/jndi/rmi://localhost:1099/JMXConnector'

url = new JmxUrl(serverUrl)
creds = ["system", "manager"] as String[]
env = ["jmx.remote.credentials":creds]
jmxc = JmxFactory.connect(url, env)

server = jmxc.MBeanServerConnection;

for (d in server.domains) { println d }

mbeanName = "geronimo:J2EEServer=geronimo,name=JVM,j2eeType=JVM"
mbean = new ObjectName(mbeanName)

println server.getAttribute(mbean, "kernelBootTime")

jmxc.close();
Trzeba jeszcze skrypcik lekko podrasować, aby użyć produkcyjnie, ale ogólny zarys już jest. Usprawnienia mile widziane.

Mam nieodparte wrażenie, że zastosowałem właściwe narzędzie do problemu. A jak Ty podszedłbyś/podeszłabyś do tematu?

p.s. Podczas rozpoczęcia konferencji warsjawa 2010 pozwoliłem sobie zrobić dygresję, taki drobny żarcik, odnośnie kobiet na sali, kiedy to na moje pytanie - już nie pamiętam jakie - padła odpowiedź damskim głosem. Natychmiast przypomniałem sobie skecz z Monty Pythona - Stoning i ledwo udało mi się utrzymać powagę. Skecz bajka! Że też zawsze musi mnie "natchnąć" w trakcie publicznych wystąpień (!)

10 listopada 2008

Nazwa puli połączeń w Geronimo 2.1.x

0 komentarzy
Trochę czasu minęło od mojego ostatniego spotkania z Apache Geronimo i jakimś cudem zawsze udawało mi się uniknąć spędzania czasu nad konfiguracją puli połączeń do bazy danych. Tym razem było inaczej.

Połączenia do bazy danych w aplikacjach Java EE 5 zaleca się, aby oprzeć o wykorzystanie puli połaczeń zarządzanej przez serwer aplikacyjny. Wprowadzenie dodatkowej warstwy abstrakcji między wirtualną nazwą puli połączeń, z której pobierane są połączenia bazodanowe, a jej fizyczną reprezentacją w serwerze aplikacyjnym pozwala na oddelegowanie zadań jej zarządzania do serwera oraz jej właściwą konfigurację przez administratora serwera. W niewielkich zespołach podział na programistę aplikacji i administratora serwera zazwyczaj nie istnieje (i stąd najczęściej wynikają pytania o sensowność takiego podejścia), ale w większych (albo mniejszych, ale bardziej rozsądnie podzielonych) oddelegowanie zadań do właściwych członków zespołu ma znaczenie, chociażby na ich wykonanie z należytą starannością i w planowanym czasie.

Tym razem, w moim niewielkim projekcie, przyszło mi tworzyć aplikację opartą o JPA oraz zestawić pulę połączeń w Geronimo. Zazwyczaj nazwę puli umieszcza się w przestrzeni jdbc w JNDI, więc moja pula połączeń dostępna była jako jdbc/UsosDev.

Wystarczy, więc użyć tej nazwy w pliku /META-INF/persistence.xml, w sekcji <jta-data-source>UsosDev</jta-data-source> i załatwione.

Kluczem jest zapamiętanie, że wszędzie tam, gdzie potrzebna jest nazwa JNDI puli połączeń korzystamy z nazwy puli podanej w polu Name of Database Pool w asystencie Geronimo database pool wizard.

Podczas uruchomienia Geronimo z opcją -vv, np. ./bin/geronimo.sh run -vv pojawi się komunikat o uruchomieniu puli:
 15:48:36,015 INFO  [KernelContextGBean] bound gbean console.dbpool/UsosDev/1.0/rar?J2EEApplication=null,JCAConnectionFactory=UsosDev,
JCAResource=console.dbpool/UsosDev/1.0/rar,ResourceAdapter=console.dbpool/UsosDev/1.0/rar,ResourceAdapterModule=console.dbpool/UsosDev/1.0/rar,
j2eeType=JCAManagedConnectionFactory,name=UsosDev at name console.dbpool/UsosDev/JCAManagedConnectionFactory/UsosDev
Atrybut name wskazuje, pod jaką nazwą została zarejestrowana pula. W powyższym przykładzie będzie to UsosDev, a ja przez kilka dłuższych chwil oczekiwałem jdbc/UsosDev (!) i stąd poniższy komunikat błędu:
 Deployer operation failed: Unable to resolve reference "JtaDataSourceWrapper"
in gbean pl.jaceklaskowski.statystyki/przyklad/1.0/war?J2EEApplication=null,PersistenceUnitModule=WEB-INF/classes/,
WebModule=pl.jaceklaskowski.statystyki/przyklad/1.0/war,j2eeType=PersistenceUnit,name=usosPU
to a gbean matching the pattern [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
due to: No matches for referencePatterns: [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
Unable to resolve reference "NonJtaDataSourceWrapper"
in gbean pl.jaceklaskowski.statystyki/przyklad/1.0/war?J2EEApplication=null,PersistenceUnitModule=WEB-INF/classes/,
WebModule=pl.jaceklaskowski.statystyki/przyklad/1.0/war,j2eeType=PersistenceUnit,name=usosPU
to a gbean matching the pattern [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
due to: No matches for referencePatterns: [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
org.apache.geronimo.common.DeploymentException: Unable to resolve reference "JtaDataSourceWrapper"
in gbean pl.jaceklaskowski.statystyki/przyklad/1.0/war?J2EEApplication=null,PersistenceUnitModule=WEB-INF/classes/,
WebModule=pl.jaceklaskowski.statystyki/przyklad/1.0/war,j2eeType=PersistenceUnit,name=usosPU
to a gbean matching the pattern [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
due to: No matches for referencePatterns: [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
Unable to resolve reference "NonJtaDataSourceWrapper"
in gbean pl.jaceklaskowski.statystyki/przyklad/1.0/war?J2EEApplication=null,PersistenceUnitModule=WEB-INF/classes/,
WebModule=pl.jaceklaskowski.statystyki/przyklad/1.0/war,j2eeType=PersistenceUnit,name=usosPU
to a gbean matching the pattern [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
due to: No matches for referencePatterns: [?name=jdbc/UsosDev#org.apache.geronimo.naming.ResourceSource]
at org.apache.geronimo.deployment.DeploymentContext.getConfigurationData(DeploymentContext.java:516)
at org.apache.geronimo.deployment.Deployer.install(Deployer.java:320)
at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:257)
at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:134)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.geronimo.gbean.runtime.ReflectionMethodInvoker.invoke(ReflectionMethodInvoker.java:34)
at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:130)
at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:850)
at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:237)
at org.apache.geronimo.deployment.plugin.local.AbstractDeployCommand.doDeploy(AbstractDeployCommand.java:116)
at org.apache.geronimo.deployment.plugin.local.DistributeCommand.run(DistributeCommand.java:61)
Teraz będę pamiętał! A może by tak zgłosić usprawnienie w komunikatach Geronimo i ostatecznie zapomnieć, aby zapamiętać, i nic nie pamiętać? ;-)

13 sierpnia 2008

Geronimo NetBeans Plugin bogatszy oraz NetBeans IDE 6.5 Beta

0 komentarzy
Nie powiem, żeby było lekko. Rozwój wtyczki Geronimo NetBeans Plugin (GNP) postępuje, ale idzie jak po przysłowiowej grudzie. Dzisiaj miałem przyjemność rozpoznać w jaki sposób NetBeans współpracuje z wtyczkami dla serwerów aplikacyjnych w kontekście kontekstów aplikacji webowych (powtórzenie zamierzone).

Podczas tworzenia aplikacji webowej wybieramy związany z nią serwer aplikacyjny.

Wybór serwera aplikacyjnego to między innymi związanie bibliotek Java EE dostarczanych przez serwer z projektem. Po prostu programista aplikacji nie musi dbać o ich definiowanie każdorazowo przy jej tworzeniu. Można potraktować związanie serwera z projektem jako definicję bibliotek projektowych oraz środowiska uruchomieniowego (które wyznacza, co można w IDE). Takie podejście nie jest niczym nadzwyczajnym w IDE, czy to będzie NetBeans, czy Eclipse, czy IntelliJ IDEA czy...tutaj nazwa Twojego ulubionego IDE.

Jedną z bolączek ostatnich dni podczas rozwoju wtyczki GNP był brak definicji kontekstu aplikacji webowej. Podczas definiowania projektu aplikacji pole Context Path było wypełnione, ale już po jej stworzeniu we właściwościach projektu było puste (!)

Rozwiązaniem okazało się zdefiniowanie klasy realizującej interfejs org.netbeans.modules.j2ee.deployment.plugins.spi.config.ContextRootConfiguration i stworzenie jej egzemplarzy przez fabrykę realizującą interfejs org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfigurationFactory, a wskazaną przez plik konfiguracyjny wtyczki - layer.xml (plik jest wskazany przez klucz OpenIDE-Module-Layer w META-INF/MANIFEST.MF). Wystarczyło trochę poszperać w javadoc oraz kodach źródłowych wtyczek do GlassFisha, JBossa i WebSphere Application Server, i wszystko stało się jasne. Jestem bliżej pełnego uruchomienia aplikacji webowej na Geronimo z poziomu NetBeans. Już się nie mogę doczekać. Muszę się jeszcze uzbroić w cierpliwość.

Dzisiejszy dzień jest również świętem dla projektu NetBeans, który opublikował wersję beta NetBeans IDE 6.5 Beta. A w nim:

NetBeans.org is proud to announce the availability of NetBeans IDE 6.5 Beta!

* Download Now
* Learn More
* Tutorials & Documentation

NetBeans IDE 6.5 Beta introduces several new features, including a robust IDE for PHP, JavaScript debugging for Firefox and IE, and support for Groovy and Grails. This release also includes a number of enhancements for Java, Ruby and Rails, and C/C++ development. Java feature highlights include: built-in support for Hibernate, Eclipse project import, and compile on save.


Jest tego trochę, więc zainteresowanych skróceniem czasu w projektach na żmudnym konfigurowaniu szkieletów aplikacyjnych, samych aplikacji i zarządzaniu serwerami aplikacyjnymi zachęcam do popróbowania się z NetBeans IDE 6.5 Beta (skoro jest to wersja BETA należy uważać jakie projekty poddamy próbie - warto zabezpieczyć się zapisując projekt w systemie kontroli wersji, aby nie było niespodzianek).

Dla żyjących na ostrzu technologicznego noża może się przydać odpowiedź na pytanie Which daily build is this equivalent to?:

None.
Beta clone has been created on August 4th. Only imported bug fixes were fixed in the clone - http://www.netbeans.org/issues/buglist.cgi?issue_type=DEFECT&resolution=FIXED&keywords=65_HR_FIX

And the Beta was built from this Beta clone, of course. Therefore it is like build from August 4th + bugfixes + branding.
The daily builds are different. Fixing of issues continues. There were 647 bugs fixed in the trunk from the 8/4 - http://www.netbeans.org/issues/buglist.cgi?issue_type=DEFECT&chfield=resolution&chfieldfrom=2008-08-04&chfieldto=Now&chfieldvalue=FIXED


Znalezione w archiwum grupy dyskusyjnej NetBeans users.

06 sierpnia 2008

Skróty klawiszowe w NetBeans, Geronimo 2.1.2, wolatylność i demo Hibernate Support in the NetBeans IDE

11 komentarzy
Ostatnie dni spędzam ślęcząc godzinami nad rozwojem wtyczki NetBeans dla Geronimo (GNbP - Geronimo NetBeans Plugin) i każdy dzień to jakaś "ciekawostka". Piszę w cudzysłowiu, bo praca z zarządcami klas (ang. classloader) w NetBeans to jak praca z Ajaxem normalnie "czystym relaksem" (prawdopodobnie w każdym bardziej złożonym środowisku miałbym podobne problemy, więc nie spodziewałbym się wielu ułatwień w tym obszarze, np. w Eclipse czy IntelliJ IDEA). A że nie stworzyłem sobie żadnych testów, to klepię wciąż to samo sprawdzając, czy tym razem jest lepiej. W końcu jest lepiej. Udało mi się w końcu przejść pomyślnie krok uruchomienia i zatrzymania Geronimo oraz dzisiaj uruchomiłem pierwszą aplikację webową (!) Jest jeszcze problem z automatycznym uruchomieniem przeglądarki ze względu na błąd związany z niezdefiniowaną zmienną ${url.client}, ale sama aplikacja jest już poprawnie uruchomiona. Kolejny kamień milowy zaliczony. Jeśli jesteś zainteresowany/-a kodami zapraszam do pobrania projektu z repozytorium SVN - http://svn.apache.org/repos/asf/geronimo/sandbox/geronimo-netbeans-plugin. Chętnie popracowałbym w parze, albo w ogóle w grupie równie zdeterminowanych co i ja (projekt rozpocząłem bodajże 1,5 roku temu, a postępy mierne!) ;-)

Tak sobie siedzę przed tym NetBeans i tak się złożyło, że w zasadzie Eclipse'a nie widziałem już dawno (poza jego komercyjnymi odpowiednikami, jak RAD czy WID). Czym więcej człowiek siedzi w wybranym IDE tym bardziej korci go próbowanie się z dostępnymi skrótami klawiszowymi. W którymś momencie spróbowałem skrótu psvm + TAB i jakie było moje zdumienie, kiedy w klasie pojawił się szablon metody main:
 public static void main(String[] args) {
}
Teraz już łatwo zrozumieć skąd ten skrót - psvm - public static void main. Nigdy nie udało mi się namierzyć tego w Eclipse (przyznaję, że nie poświęciłem temu wiele czasu, więc zapewne stąd nadal brak odpowiedzi). Plus dla NetBeans. Edytor javowy zawsze był domeną Eclipse, ale tym razem NetBeans rulez.

Tak sobie przeglądam kodu źródłowe wtyczek dla GF, WAS, WLS i JBAS w NetBeans i natrafiłem na taką konstrukcję (zmodyfikowaną na potrzeby wtyczki GNbP):
 static {
java.util.logging.Logger.getLogger("org.apache.geronimo.netbeans").setLevel(java.util.logging.Level.FINEST);
java.util.logging.Logger.getLogger("org.apache.geronimo.deployment.plugin.factories").setLevel(java.util.logging.Level.FINEST);
}
Bardzo spodobała mi się owa sztuczka, która polegająca na statycznej konfiguracji poziomu odnotowywanych zdarzeń aplikacji. W ten sposób zapominam o konfiguracji za pomocą jakiegoś tam pliku, gdzieś tam (świadomie podkreślam moją tymczasową niewiedzę, co musiałbym ustawić i gdzie). Po prostu mam gwarancję, że uruchomienie klasy zawierającej ten blok statyczny zapewni mi odpowiedni poziom komunikatów. Trudno mi znaleźć więcej zalet niż chwilowa niewiedza, gdzie umieścić odpowiedni plik konfiguracyjny, ale co tu dużo ukrywać, zachwyciłem się tą konstrukcją. Pewnie nie udałoby mi się odeprzeć zarzutu o braku możliwości zmiany bez kompilacji, co w dobie dynamicznych konfiguracji "w locie" (= w trakcie wykonywania aplikacji) jest nie do przecenienia, ale efekt zachwytu jest. Pomyślałem, aby odnotować tą ciekawostkę. Może się później przyda ponownie i już będę wiedział, gdzie jej szukać.

Kontynuując moją batalię z zawiłościami bardziej zaawansowanej pracy w środowisku NetBeans IDE 6.5 (przypominam, że wciąż w wersji rozwojowej) natrafiłem na kolejny skrót klawiszowy Ctrl+Shift+I, który, w przeciwieństwie do Alt+Shift+I, obsługuje dodanie brakujących importów w całej klasie/interfejsie bez konieczności ustawienia kursora na podkreślonym typie. Napotkałem również Ctrl + F12, czyli eclipsowe Ctrl+O, który otwiera widok na składowe - pola i metody - edytowanego typu (=klasa lub interfejs). A na koniec, już rozochocony moimi znaleziskami, postanowiłem sprawdzić skrót fore + TAB (wstawia szablon pętli for po Enumeration). Działa! I jest również w Eclipse, podobnie jak fori. Ciekawym, ilu z Was korzysta z takich udogodnień w swoim wybranym IDE. I ile z nich jest całkowicie nieintuicyjnych? Nie mogłem wyjść z podziwu, kiedy zobaczyłem z jakim niedowierzaniem i zdumieniem są przyjmowane te i inne sztuczki przez osobę całkowicie niezaznajomioną z nimi, a która dopiero rozpoczynała swoją działalność z Eclipse IDE. Po prostu nie mogła nadziwić się, że tak można (!) Zobaczyć rozradowaną minę kolegi...bezcenne! ;-)

Ja się zabawiam wtyczką GNbP, a tu proszę Apache Geronimo v2.1.2 - Released:

Apache Geronimo v2.1.2 have passed 100% SUN's Java Enterprise Edition 5.0 Certification Test Suite. Refer to Apache Geronimo v2.1.2 Release Notes for further details.

The Apache Geronimo project is pleased to announce the new v2.1.2 release. This release is primarily a maintenance upgrade that pulls together fixes not only for Geronimo but also other key components included in the server. Improvements have been made in the administrative console, GShell command line processing, messages, and numerous other areas. Details of the fixes included can be seen in the Release Notes. Many issues have also been resolved in newer versions of core components that have been included in this Geronimo release. Geronimo v2.1.2 component upgrades include Tomcat 6.0.16, CXF 2.0.8, JavaMail 1.5, MyFaces 1.2.3, WADI 2.0, and Yoko 1.0 among others.


Pierwszym zaskoczeniem był rozmiar paczki, gdzie poprzedni geronimo-jetty6-javaee5-2.1.1-bin.tar.gz to 71,2MB a geronimo-jetty6-javaee5-2.1.2-bin.tar.gz to 68,8MB. Czyżby Geronimo skorzystał z jakieś diety odchudzającej?! Oby nie okazało się, że w tym odchudzaniu zabrakło jakieś funkcjonalności. Okazuje się, że można dodać nowe (patrz Geronimo 2.1.2 Release Notes) i ostatecznie zmniejszyć rozmiar paczki dystrybucyjnej.

Wspominałem już o mojej analizie kodu źródłowego wtyczek NetBeans dla innych serwerów aplikacyjnych. Lektura źródeł zawsze kończy się dla mnie jakąś niespodzianką. Nikt nie mówi, że musi być ona przyjemna, ale tym razem była. Okazuje się, że raczej rzadko stosowana acz kluczowa klasa java.lang.ClassLoader udostępnia statyczną metodę getSystemClassLoader(), która zwraca systemowego zarządcę klas, który jest nadrzędny dla wszystkich nowych zarządców klas. Jest to zazwyczaj zarządca odpowiedzialny za uruchomienie aplikacji. W typowych aplikacjach desktopowych będzie to również zarządca dostępny przez Thread.currentThread().getContextClassLoader(). Co mnie jednak zdumiło w całym tym skomplikowanym świecie zarządców klas to możliwość nadpisania domyślnego zarządcy przez zmienną java.system.class.loader. Niby nic nadzwyczajnego, ale możliwość zdefiniowania własnego rozszerzenia środowiska uruchomieniowego naszych aplikacji javowych daje większe możliwości niż jego nieznajomość. Nawet jak nie wiadomo po co, to warto wiedzieć. A nuż się przyda. Największe jednak zdumienie wywołał fakt, że jest to statyczna metoda, której istnienia w ogóle nie byłem świadom. W zasadzie zaleca się korzystanie z Thread.currentThread().getContextClassLoader() do dynamicznego ładowania klas (co jest szeroko stosowane np. w OSGi), więc wiedza zdaje się być nikłej wartości praktycznej. A może komuś jednak udało się skorzystać z tej metody, albo wręcz z tej zmiennej środowiskowej? Koniecznie się tym należy pochwalić tu i teraz.

Na koniec chciałbym wyrazić swoją dezaprobatę na szastanie naszym językiem we wszystkie możliwe strony i bezkrytycznym naśladowaniem "wyuzdanych" tłumaczeń. Kilka przykładów z szerokiego świata javowego. Nie, nie wspomnę o kontrowersyjnym ziarnie jako odpowiedniku bean, czy szkielecie aplikacyjnym lub rusztowaniu, czy ostatni hit sezonu - stelażu - dla framework, ale o kilku bardziej wyuzdanych. Zacznijmy od customize. Ile to razy wokół mnie pada termin "kastomizacja". Czy nie można po prostu użyć słowa dopaso(wy)wanie?! Czyż nie ładniej brzmi i na pewno wyjaśnia co autor miał na myśli. Pewnie niejeden z nas przez moment miał zawrót głowy od "kastomizacja" czy "kastomizowalny", ale po chwili samemu rozpoczął krucjatę "kastomizacji". Proponuję zaprzestać jego używania raz na zawsze. Zgoda?

Kolejnym kandydatem na ustrzelenie, to nieszczęsne - zaadresowanie problemu jako odpowiednik angielskiej frazy address an issue, czyli obsłużyć problem. Wystarczy więc obsłużyć problem tłumaczeń, aby dopasować jeden język do drugiego i już jesteśmy bardziej rozumiani. W tym samym tonie miałem ostatnio okazję wysłuchania wypowiedzi szefa pewnego TFI na P w TVN CNBC (gość pod krawatem wyprasowany na kanty, gdzie się dało), który użył słowa, które wręcz zdusiło mnie za gardło - wolatylność. Po prostu odjęło mi mowę. Dopiero zaczynam moje potyczki ekonomiczne, ale jeśli mam doświadczać tej nowomowy znanej mi poniekąd z informatyki, to zapewne powinienem zacząć się przyzwyczajać do takich kwiatków? Pewnie Cię zaintrygowało czytelniku cóż może znaczyć owo słowo, więc zapraszam do wspaniałego wyjaśnienia słowa wolatylność w Wademekum LESZCZA !! ( Z PARKIETU). Autor wyjaśnił słowo nad wyraz wspaniale:

WOLATYLNOŚĆ (od ang. volatility) nowomowa ANALI, którzy chcą pokazać, ze obracają się w nie byle jakim towarzystwie. Normalny człowiek powie po prostu zmienność.

ANALe to analitycy rynków kapitałowych. Potrafią przyłożyć, nieprawdaż? W ten sposób zamiast zapraszać odstraszają. Czyż nie doświadczamy tego również i w naszej polskiej rzeczywistości programistycznej, z owymi frameworkami i beanami? Zgoda, szkielet aplikacyjny czy ziarno nie poprawia za bardzo sprawy, ale można liczyć na pewne skojarzenia u rozmówcy, niezaznajomionego z obowiązującą nomenklaturą. Właśnie o to chodzi. Niekoniecznie musi to wyjaśniać temat dokładnie, a wystarczy, aby sugerował znaczenie.

Na zakończenie dla spragnionych wsparcia Hibernate w NetBeans ciekawe demo Hibernate Support in the NetBeans IDE. Nie jest to bardzo wyrafinowane demo, ale pokazuje jak w prosty sposób można szybko stworzyć prototyp aplikacji wizualnie (trochę kodowania też jest, więc nie ma obawy, jeszcze nas nie pozwalniają po wdrożeniu NetBeans IDE w firmach). Pora wygodnie się rozsiąść, założyć ręce za głowę i włączyć prezentację. Warto chociażby dla samej nauki języka i trudnej sztuki prezentacji (jednoczesne kodowanie i mówienie nie należy do łatwych zadań). Zastanawiam się jakim powodzeniem cieszą się takie krótkie filmy-demo w porównaniu z artykułami ze zrzutami ekranów. Lepsze? Gorsze? Mam wrażenie, że ich odbiór jest przyjemniejszy, ale nie można ich wydrukować, i przeczytać w autobusie/metrze, więc jest trochę wad. Jeśli mniej niż zalet, to może warto wdrożyć taką formę prezentacji w Notatniku? Miłego oglądania!

01 sierpnia 2008

Urlop na Roztoczu oraz wtyczka NetBeans dla Geronimo

5 komentarzy
"Każdy ma swój urlop, miałem i ja - na Roztoczu" mógłbym parafrazować słowa pewnej reklamy. Tak, to prawda. Po długim ślęczeniu przed komputerem w końcu nadeszła pora na wymarzony urlop. Żona zafundowała mi rodzinny wyjazd na kilka dni na Lubelszczyznę, a dokładnie na Roztocze w Roztoczańskim Parku Narodowym we wsi Rudka k/Zwierzyńca.

Pierwszy dzień - terenu rozpoznanie. Drugi dzień - od rana kajakiem spływanie (Wieprzem). Trzeciego - spływu kontynuowanie. W międzyczasie wizyta w Zamościu, w którym rodzinie obiecałem wizytę na zamku, który...nie istnieje! Skąd ja wziąłem to przekonanie o zamku?! Sądziłem, że w Zamościu jest zamek, bo to takie historyczne miasto, a tu nic, zero zamków. Mimo wszystko warto było. Odwiedziliśmy bar mleczny przy Rynku Głównym, w którym jedzenie było przepyszne, a na samym Rynku pyszne gofry. W wolnej chwili wylegiwanie na plaży nad jeziorem "Stawy Echo" w samym Parku, przy stanowisku Konika Polskiego. Wszystko okraszone piwem Zwierzyniec za bagatela 4PLN za 0,5L w knajpie (!) Trudno się dziwić skoro browar piwa Zwierzyniec to właśnie miasto Zwierzyniec. Pogoda dopisała, więc wyjazd, mimo, że jedynie 5-dniowy, udał się wspaniale. Bez dostępu do komputera, braku telewizora, ze spaniem po 9 godzin i ciągle na dworze można niesamowicie wypocząć. Polecam! Jako podsumowanie wspaniałego miejsca na wypoczynek niech wystarczy (niewyraźne) zdjęcie z miejscowej lodziarni.

Potrafią rozbawić człowieka, nieprawdaż?! Po drodze na Roztocze (z Warszawy) przejeżdża się przez miasto chrząszcza - Szczebrzeszyn. Teraz, nie tylko potrafię wskazać kolejny Park Narodowy, ale i wiem, gdzie ów słynny Szczebrzeszyn leży. Jako ciekawostkę pobytu w zajeździe "W Starym Kinie" w Rudce codzienny brak Javy rekompensowało mi śniadanie z Mocha Java na ścianie.

Chyba jestem skazany na Javę.

W drodze powrotnej zawitaliśmy do Karczmy "Bida", która mimo swojej nazwy serwowała smakowite dania w porcjach znacząco przewyższających nasze oczekiwania. Przyzwyczajeni do typowych rozmiarów potraw w przydrożnych karczmach trzeba było widzieć nasze miny, kiedy na deser zamówiliśmy placki ziemniaczane i naleśniki, a podano nam zestawy obiadowe. Jedzenie pyszne i to w okazałych ilościach.

Po powrocie przejrzenie poczty, a tam ciekawostka związana z NetBeans IDE 6.5. Co jakiś czas NetBeans 6.5 (w fazie rozwojowej) zaskakuje. A to wsparcie dla nowych typów projektów, a to znaczna poprawa wyświetlania struktury katalogowej projektów podczas ich importu/otwarcia/itp., a tu jeszcze...wsparcie Apache Geronimo przez NetBeans IDE za pomocą wtyczki Geronimo 2 Application Server. Nikt się nie chwalił, nikt nie napisał, niedobrze. Taka funkcjonalność, a tak niewiele reklamy. Czyżby autorowi nie zależało na sprawdzeniu wtyczki w ogólnym użyciu?

Jeszcze nie próbowałem się z nią, ale może ktoś z Was już to zrobił?! Jakie wrażenia? Warto się jej przyjrzeć? Jaka wersja Apache Geronimo jest wspierana? Podobno rozwojowa wersja 2.2 nie jest.

p.s. W trakcie urlopu udało mi się zebrać w sobie i przeczytałem książkę "Bogaty Ojciec, Biedny Ojciec" Roberta T. Kiyosaki'ego. Książka przedstawia prawdy oczywiste na temat naszego podejścia do pieniędzy i pracy, która jest ich głównym źródłem, w bardzo nietypowy sposób. Nawet, jeśli wciąż liczysz, że praca jest dla Ciebie wszystkim, a ZUS zapewni Ci dostatek, warto zapoznać się z nią. Teraz wszędzie wokół mnie widzę tylko pasywa ;-) Pora zabrać się za stronę aktywów. Sugestie mile widziane.

21 czerwca 2008

Kolejne dni z JBoss Seam - trochę o geronimo-maven-plugin i @Name

0 komentarzy
Znudziło mnie to ciągłe
 c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Czyż nie prościej byłoby uruchomić przykład na wcześniej uruchomionym Geronimo (na osobnej konsoli) podczas wykonania integration-test? Pewnie, że prościej!

Zmieniam konfigurację wtyczki geronimo-maven-plugin w pom.xml na następującą:
 <executions>
<execution>
<id>undeploy-ear-as-module</id>
<phase>pre-integration-test</phase>
<goals>
<goal>undeploy-module</goal>
</goals>
<configuration>
<modules>
<module>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<type>war</type>
</module>
</modules>
</configuration>
</execution>
<execution>
<id>deploy-module</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy-module</goal>
</goals>
<configuration>
<moduleArchive>target/seam-richfaces-tree.war</moduleArchive>
<modulePlan>src/main/resources/geronimo-web.xml</modulePlan>
</configuration>
</execution>
</executions>
Z nią wystarczy wykonać integration-test, aby rozmieścić aplikację na Geronimo.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ mvn clean package integration-test
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building seam-richfaces-tree Maven Webapp
[INFO] task-segment: [clean, package, integration-test]
[INFO] ------------------------------------------------------------------------
...
[INFO] [geronimo:undeploy-module {execution: undeploy-ear-as-module}]
log4j:WARN No appenders could be found for logger (org.apache.geronimo.deployment.plugin.factories.BaseDeploymentFactory).
log4j:WARN Please initialize the log4j system properly.
[INFO] Module is already stopped: pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] Module is not deployed: pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] [geronimo:deploy-module {execution: deploy-module}]
[INFO] Using non-artifact based module archive: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war
[INFO] Using non-artifact based plan: c:\projs\sandbox\seam-richfaces-tree\src\main\resources\geronimo-web.xml
[INFO] Distributing module artifact: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war
with plan c:\projs\sandbox\seam-richfaces-tree\src\main\resources\geronimo-web.xml
[INFO] Starting modules...
[INFO] Starting module: pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] Started module(s):
[INFO] [0] pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 50 seconds
Wykonanie mvn clean package integration-test nie należy do najkrótszych poleceń, ale nie wykracza poza wiedzę mavenową, więc pod tym względem będzie bardziej zrozumiałe dla osób niezaznajomionych z Geronimo.

Można również tak:
 mvn geronimo:undeploy-module -DmoduleId=pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war \
geronimo:deploy-module -DmoduleArchive=target/seam-richfaces-tree.war \
-DmodulePlan=src/main/resources/geronimo-web.xml
Można i tak:
 mvn geronimo:undeploy-module geronimo:deploy-module
jednakże takie skrócenie wymaga podania parametrów środowiskowych w pom.xml w sekcji properties. A można jeszcze krócej?! Ciekawym podpowiedzi, jak możnaby to dalej skrócić (możnaby pokombinować z profilami w m2).

A wracając do Seama. Zabrałem się poważniej za lekturę książki Beginning JBoss® Seam: From Novice to Professional wydawnictwa Apress, którą mamy w Bibliotece Warszawskiego JUGa. Przez "poważniej" rozumiem silną wolę przeczytania książki i opublikowania recenzji. Pamiętam, że Brzezi (tak, to ten od "Skorzystaj z Google" z pl.comp.lang.java ;-)) przeczytał książkę, ale nie udało mi się go nakłonić do opublikowania swojej recenzji. W/g niego książka jest dla kompletnych nowicjuszy z JBoss Seam, więc idealna dla mnie. Jakkolwiek dotyczy wersji 1.1.0.GA, a pracuję z 2.0.3.CR1, to mimo wszystko spodziewam się zdobyć trochę wiedzy seamowej.

Dzisiaj zacząłem od utworzenia klasy z adnotacją @Name, ale nie miałem wiele szczęścia z jej uruchomieniem. Wrócę do tematu jutro.

Pytanie konkursowe: Dlaczego uważasz, że warto poznać JBoss Seam? ;-)

20 czerwca 2008

Podboje JBoss Seam ciąg dalszy - minimalna konfiguracja działa!

0 komentarzy
Wczorajsze boje z JBoss Seam 2.0.3.CR1 - JBoss Seam, Apache Geronimo z Eclipse Ganymede i Apache Maven 2 zakończyły się poprawnym rozmieszczeniem aplikacji, jednakże próba uruchomienia strony witaj.seam zakończyła się pustą stroną XHTML.

Porównując różnice między aplikacją utworzoną wcześniej z seam-gen (Uruchomienie projektu seamowego w Eclipse Ganymede z JBoss Tools i Geronimo Eclipse Plugin) a z mavenowym archetypem maven-archetype-webapp natknąłem się na różnicę w web.xml:
 <filter>
<filter-name>Seam Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Nie znalazłem dokumentacji, dlaczego miałbym potrzebować SeamFilter, a mimo to postanowiłem spróbować uruchomienia w ciemno. Po dodaniu zmiany do web.xml i uruchomieniu
 c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Bez zmian. Strona wciąż nie wyświetla się.

Porównując dalej aplikacje okazało się, że moja nowa aplikacja seamowa nie posiadała pliku faces-config.xml (!) Aż trudno uwierzyć, że żaden z elementów Seama czy MyFaces nie zgłosił jego braku.
 <?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<application>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config>
Skorzystanie z FaceletViewHandler wymaga zadeklarowania zależności w pom.xml (zależność znajduje się w repozytorium repository.jboss.org).
 <dependency>
<groupId>com.sun.facelets</groupId>
<artifactId>jsf-facelets</artifactId>
<version>1.1.15.B1</version>
</dependency>
i zbudowaniu aplikacji
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ mvn clean package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building seam-richfaces-tree Maven Webapp
[INFO] task-segment: [clean, package]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory c:\projs\sandbox\seam-richfaces-tree\target
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [war:war]
[INFO] Packaging webapp
[INFO] Assembling webapp[seam-richfaces-tree] in [c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree]
[INFO] Processing war project
[INFO] Webapp assembled in[157 msecs]
[INFO] Building war: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
a następnie jej rozmieszczeniu na wcześniej uruchomionym Geronimo
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
Deployed pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war @
/seam-richfaces-tree
Na konsoli Geronimo można zaobserwować
 19:13:04,953 INFO  [ServletContextListener] Welcome to Seam 2.0.3.CR1
...
19:13:29,046 INFO [Initialization] initializing Seam
...
19:13:30,312 INFO [Initialization] done initializing Seam
...
19:13:30,359 INFO [MyfacesConfig] Starting up Tomahawk on the MyFaces-JSF-Implementation
19:13:30,921 INFO [AbstractFacesInitializer] ServletContext
'C:\geronimo\repository\pl\jaceklaskowski\seam\seam-richfaces-tree\1.0\seam-richfaces-tree-1.0.war\' initialized.
Uruchomienie http://localhost:8080/seam-richfaces-tree/witaj.seam i...



Działa! Od razu mi lepiej ;-)

W międzyczasie "uzbroiłem" stronę witaj.xhtml w szablon Facelets.
 <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
template="szablon.xhtml">

<ui:define name="body">
<p>Witaj Nieznajomy!</p>
</ui:define>

</ui:composition>
gdzie szablon wskazywany przez atrybut template wskazuje na plik szablon.xml:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:s="http://jboss.com/products/seam/taglib">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Strona powitalna</title>
</head>

<body>

<div class="body">
<ui:insert name="body"/>
</div>

</body>
</html>
Wytłumaczenie działania facelets i jego szablonu pozostawiam dla dociekliwych jako zadanie domowe. Sądzę, że działanie facelets w tym zakresie powinno być samowyjaśniające.

Uważne oko mogło zauważyć, że pracuję z Firefox 3.0. Nie ukrywam, że jestem zachwycony szybkością jego działania. Mając bardzo bogatą bazę odnośników (wiele z nich to artykuły do przeczytania) praca z 2.0.0.14 była udręką, bo przy jednocześnie otwartych 10 pojedyńczych przeglądarkach strasznie spowalniała. Dodając do tego niezwykle powolne otwieranie zakładek (Ctrl+T) w zasadzie całkowicie z nich zrezygnowałem. Otworzenie nowej zakładki przez Ctrl+T zajmowało ponad 15-30 sekund, podczas gdy otwarcie przez menu pod prawym klawiszem myszy było błyskawiczne. Niestety, nie zawsze mogłem otworzyć zakładkę przez menu, więc szybciej uruchamiałem nowe okno. Teraz, z FF 3.0 sprawa jest całkowicie rozwiązana. Otwieranie zakładek, zajętość pamięci oraz szybkość renderowania stron są przygniatające. Strony wyświetlane są z prędkością światła. Na prawdę warto było przenieść się na FF 3.0. Polecam!

Pytanie konkursowe: Jaka technologia realizuje warstwę prezentacji w JBoss Seam? I uzupełniające: Jaki projekt oferuje mechanizm szablonów dla JBoss Seam? (zwróć uwagę na różnicę między technologia a projekt).

19 czerwca 2008

JBoss Seam, Apache Geronimo z Eclipse Ganymede i Apache Maven 2

5 komentarzy
Postanowiłem trochę popróbować się z JBoss Seam 2.0.3.CR1 w trochę odmienny sposób niż z seam-gen. Nie ukrywam, że kiedy zobaczyłem te wszystkie katalogi po zaimportowaniu do Eclipse Ganymede trochę się przestraszyłem skomplikowanej struktury katalogowej aplikacji. Niby Seam miał mi ją odchudzić, a tych katalogów i plików jakby więcej. I jeszcze ta czerwona ikonka oznaczająca błąd w projekcie (zmienna nie jest rozwiązywana i w zasadzie błąd jest nieistotny).

Zabrałem się za utworzenie aplikacji seamowej od zera z użyciem Eclipse JEE Ganymede RC3 (i właśnie jak pisałem wersję okazało się, że pojawiła się już kolejna wersja RC4! Nie zasypują gruszek w popiele). Celem było określenie kroków, jakie konieczne są, aby zestawić projekt seamowy w Eclipse.

Zacząłem od Ctrl+N, Dynamic Web Project, podałem nazwę projektu (Project name), przypisałem serwer (Target Runtime) i Finish. Potrzebowałem jeszcze zdefiniować zależności seamowe w projekcie. Java > Build Path > User Libraries, przycisk New..., podałem nazwę JBoss Seam, następnie Add JARs. Kiedy zacząłem dodawać wszystkie zależności pomyślałem sobie, że prościej byłoby po prostu zadeklarować w projekcie pojedyńczą bibliotekę, której dalsze zależności byłyby pobrane automatycznie, za mnie. Do głowy przyszedł Apache Maven 2.

I znowu od zera. Na wzór myfaces-trinidad-tree z EJB 3.0 Redbook opublikowany i doświadczenia z trinidadowym tr:tree postanowiłem stworzyć aplikację seamową, która realizowałaby podobną funkcjonalność - prezentowanie danych z bazy danych w strukturze drzewiastej jak lista katalogów czy podobnie.
 mvn archetype:create \
-DarchetypeArtifactId=maven-archetype-webapp \
-DgroupId=pl.jaceklaskowski.seam \
-DartifactId=seam-richfaces-tree
i mam aplikację. Import do Eclipse (z zainstalowaną wtyczką m2eclipse) - File > Import > Maven Projects, gdzie wskazuję na katalog z właśnie utworzoną aplikacją (C:\projs\sandbox\seam-richfaces-tree).

Pozostaje zadeklarować zależności seamowe w pom.xml i do można tworzyć aplikację. Dobrym projektem wzorcowym, gdzie potrzebne zależności są przejrzyście zadeklarowane wraz z ich wersjami i repozytoriami to po prostu plik root-2.0.3.CR1.pom, który jest POMem dla projektu JBoss Seam. Trochę informacji można znaleźć w zdeaktualizowanym dokumencie Seam published to Maven. Podglądając Java Build Path nowozaimportowanego projektu w Eclipse można dowiedzieć się o minimalnych wymaganiach Seama odnośnie zależności zewnętrznych - Build Path > Configure Build Path > Libraries > Maven Dependencies (widok po kilku zmianach, o których za chwilę).

Pobieżna lektura 1.2. Your first Seam application: the registration example, gdzie dowiaduję się o koniecznych zmianach w deskryptorze web.xml związanych z rejestracją słuchaczy (listeners) inicjujących niezbędne elementy aplikacji seamowej.

Pierwsze zaskoczenie spoza obszaru Seama to edytor deskryptora web.xml, ale sądzę, że to zasługa zbioru wtyczek JBoss Tools niż samego Eclipse Ganymede (może ktoś to potwierdzić?).

Podnoszę wersję aplikacji webowej do 2.5 (z 1.3 domyślnie deklarowanej przez archetyp maven-archetype-webapp - na zrzucie powyżej już po poprawce). W zasadzie to kopiuję zawartość Example 1.5. z dokumentacji Seama.

Wykonuję mvn package dla pewności, że wszystko poprawnie zestawione (chociaż wtyczka m2eclipse w Eclipse robi dokładnie to samo po każdej zmianie, to mimo wszystko jakiś taki nieufny dzisiaj jestem i ciągnie mnie do linii poleceń - nawet mój syn dzisiaj zauważył, że wciąż mam otwartego Cygwina).
 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
</web-app>
Każdorazowe wywołanie adresu z rozszerzeniem seam spowoduje wzbudzenie servletu facesowego (czytaj: fejsowego) - Faces Servlet, który zmodyfikuje adres na stronę o rozszerzeniu xhtml, która potencjalnie będzie wykorzystywała Facelets jako konstrukcji dla stron seamowych. Oczywiście strona xhtml nie musi być pisana z użyciem facelets - może to być po prostu zwykła strona xhtml. Sprawdzam.

Zaznaczając katalog src/main/webapp, spod prawego klawisza myszy wybieram New > Other... (Ctrl+N), a dalej Web > HTML, przycisk Next, podaję nazwę nowego pliku witaj.xhtml, ponownie Next, gdzie wybieram New XHTML File (1.0 strict) - nigdy nie wiem, jaka jest różnica między 1.0 strict a transitional i kończę przyciskiem Finish. Dodaję Witaj nieznajomy... do strony.
 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Witaj Nieznajomy!</title>
</head>
<body>
Witaj Nieznajomy!
</body>
</html>
i w końcu nadeszła pora spróbować uruchomić aplikację semi-seamową (semi, gdyż jedynym łącznikiem między aplikacją a Seamem jest zadeklarowanie łączenia w deskryptorze web.xml w postaci listener-class jako org.jboss.seam.servlet.SeamListener).

Zastanawiam się jak teraz uruchomić aplikację z poziomu Eclipse?! Czyżby pozostawało mi jedynie skorzystać z mvn clean jetty:run?
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ mvn clean 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] ------------------------------------------------------------------------
[INFO] Total time: < 1 second
No tak, brakuje konfiguracji wtyczki jetty w projekcie. Po konfiguracji wtyczki (więcej w Konfiguracja wtyczki maven-jetty-plugin w artykule Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty) uruchomienie kończy się błędem (!)
 [INFO] Starting jetty 6.1.10 ...
2008-06-18 22:44:23.549::INFO: jetty-6.1.10
2008-06-18 22:44:23.705::WARN: Could not instantiate listener com.sun.faces.config.ConfigureListener
java.lang.ClassNotFoundException: com.sun.faces.config.ConfigureListener
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195)
at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255)
at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274)
at org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:375)
Brakuje bibliotek JSF w aplikacji webowej. Ponownie Java Build Path > Add Library > JSF Libraries, a tam JavaServer Faces Libraries can only be configured for Dynamic Web projects with the JSF faces installed. I tu decyzja, która zajęła mnie już do końca dnia - spróbuję uruchomić aplikację z poziomu mavena z...Apache Geronimo 2.1.1 z wbudowanym Jetty (alternatywnie można skorzystać z Apache Geronimo dystrybuowanym z Apache Tomcat). Powód? Przynajmniej dwa - po pierwsze konfigurację bibliotek JSF mam wtedy z głowy, gdyż są one obowiązkowym elementem każdego serwera Java EE 5 i po drugie nigdy tego jeszcze nie przedstawiałem, więc najwyższa pora. Serwer aplikacyjny Java EE 5, jakim jest Apache Geronimo jest zobligowany wymaganiem specyfikacji Java EE 5 do dostarczania odpowiednich bibliotek JSF bez konieczności nakładania dodatkowego obowiązku troszczenia się o to przez same aplikacje webowe.

Konfiguracja pom.xml z wykorzystaniem wtyczki geronimo-maven-plugin i tym razem mvn integration-test do uruchomienia aplikacji z Geronimo. Dokumentacja wtyczki geronimo-maven-plugin jest trochę nieświeża, więc wymaga uaktualnienia, co załatwiam krótko - mam pobrane źródła wtyczki, wykonuję mvn site w buildsupport/geronimo-maven-plugin i cieszę się świeżutką dokumentacją w buildsupport/geronimo-maven-plugin/target/site. Ostatecznie plik pom.xml prezentuje się następująco:
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.seam</groupId>
<artifactId>seam-richfaces-tree</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>seam-richfaces-tree Maven Webapp</name>
<url>http://www.jaceklaskowski.pl</url>
<repositories>
<repository>
<id>repository.jboss.org</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
<version>2.0.3.CR1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>seam-richfaces-tree</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.geronimo.buildsupport</groupId>
<artifactId>geronimo-maven-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<assemblies>
<assembly>
<id>geronimo-jetty</id>
<groupId>org.apache.geronimo.assemblies</groupId>
<artifactId>geronimo-jetty6-javaee5</artifactId>
<version>2.1.1</version>
<classifier>bin</classifier>
<type>zip</type>
</assembly>
<assembly>
<id>geronimo-tomcat</id>
<groupId>org.apache.geronimo.assemblies</groupId>
<artifactId>geronimo-tomcat6-javaee5</artifactId>
<version>2.1.1</version>
<classifier>bin</classifier>
<type>zip</type>
</assembly>
</assemblies>
<defaultAssemblyId>geronimo-jetty</defaultAssemblyId>
<optionSets>
<optionSet>
<id>default</id>
<options>
<option>-XX:MaxPermSize=128m</option>
</options>
</optionSet>
<optionSet>
<id>morememory</id>
<options>
<option>-Xmx512m</option>
<option>-XX:MaxPermSize=128m</option>
</options>
</optionSet>
</optionSets>
</configuration>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start-server</goal>
</goals>
<configuration>
<assemblyId>geronimo-jetty</assemblyId>
<logOutput>true</logOutput>
<background>true</background>
<verifyTimeout>300</verifyTimeout>
<refresh>true</refresh>
<veryverbose>true</veryverbose>
<options>morememory</options>
</configuration>
</execution>
<execution>
<id>deploy-ear</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy-module</goal>
</goals>
<configuration>
<moduleArchive>target/seam-richfaces-tree.war</moduleArchive>
<modulePlan>src/main/resources/geronimo-web.xml</modulePlan>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Uruchomienie mvn clean intergration-test, które trochę potrwa zanim Geronimo znajdzie się na dysku, więc warto pomyśleć o przerwie 10-minutowej, w trakcie której zostanie pobrany z Sieci (w końcu to ~76MB).

Po chwili...

Na razie wszystko działa, jeśli chodzi o wystartowanie serwera z aplikacją.

Czas na utworzenie planu dla Geronimo, gdzie nadamy nazwę modułowi dla łatwiejszej jej administracji. Należy rozróżnić pojęcia war od modułu, gdzie moduł jest bytem pierwszej kategorii w Geronimo (reprezentowanym przez zestaw GBeanów), gdzie każdy inny typ aplikacji, jak war, ear, ejb-jar jest jedynie bardziej specjalizowanym modułem. Geronimo rozpoznaje byty, którymi zarządza jedynie poprzez zestaw GBeans i tylko to dla niego się liczy. Samo określenie zestawu GBeans jako war, ear czy podobnie to wymaganie wybranej specyfikacji, w tym przypadku Java EE, którą Geronimo realizuję. Możemy sobie wyobrazić sytuację, że Geronimo będzie realizowało inną specyfikację i jej realizacja również będzie oparta o GBeans. Plik plan jest dokumentem konfiguracyjnym modułu, gdzie konfigurujemy środowisko aplikacji łącznie z mapowaniem logicznych nazw w aplikacji na ich serwerowe zasoby.
 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2">
<moduleId>
<groupId>pl.jaceklaskowski.seam</groupId>
<artifactId>seam-richfaces-tree</artifactId>
<version>1.0</version>
<type>war</type>
</moduleId>
</environment>
<context-root>/seam-richfaces-tree</context-root>
</web-app>
Możnaby skorzystać z dobrodziejstw Mavena do dynamicznej podmiany wartości moduleId podczas budowania aplikacji, aby nie kopiować ich i tym samym utrzymywać w dwóch miejscach - niektóre z nich mogą się zmienić podczas rozwoju aplikacji, jak numer wersji aplikacji. Pozostawiam temat jako zadanie domowe dla ochotnika ;-)

Po chwili konfiguracji, uruchamiania, itp. uruchomienie aplikacji kończy się...wyjątkowo.
 Deployer operation failed: AbstractWebModuleBuilder: 
Could not load listener class: com.sun.faces.config.ConfigureListener
org.apache.geronimo.common.DeploymentException: AbstractWebModuleBuilder:
Could not load listener class: com.sun.faces.config.ConfigureListener
at org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder.createWebAppClassFinder(AbstractWebModuleBuilder.java:791)
at org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder.createWebAppClassFinder(AbstractWebModuleBuilder.java:759)
at org.apache.geronimo.web25.deployment.AbstractWebModuleBuilder.configureBasicWebModuleAttributes(AbstractWebModuleBuilder.java:836)
at org.apache.geronimo.jetty6.deployment.JettyModuleBuilder.addGBeans(JettyModuleBuilder.java:365)
at org.apache.geronimo.j2ee.deployment.SwitchingModuleBuilder.addGBeans(SwitchingModuleBuilder.java:165)
at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.buildConfiguration(EARConfigBuilder.java:647)
at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:254)
at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:133)
Wynika to z faktu, że domyślną implementacją specyfikacji JavaServer Faces (na której oparty jest Seam) jest implementacja referencyjna Suna - JSF RI. Pozostaje "zdjąć" wymaganie na com.sun.faces.config.ConfigureListener w deskryptorze (czym mniej zależności od niestandardowych klas i interfejsów tym lepiej dla kondycji naszej aplikacji, nieprawdaż?). Ponowne uruchomienie i...
 [INFO] Starting modules...
[INFO] Starting module: pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
org.apache.geronimo.kernel.config.LifecycleException:
start of pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war failed
at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:566)
at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:530)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Caused by: org.apache.geronimo.gbean.InvalidConfigurationException:
Configuration pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war failed to start
due to the following reasons:
The service J2EEApplication=null,WebModule=pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war,
j2eeType=Servlet,name=Faces Servlet did not start because javax.servlet.ServletException:
java.lang.IllegalStateException: No Factories configured for this Application.
This happens if the faces-initialization does not work at all -
make sure that you properly include all configuration settings necessary for a basic faces application
and that all the necessary libs are included.
Also check the logging output of your web application and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use some special
web-containers which do not support registering context-listeners via TLD files and a context listener
is not setup in your web.xml.
A typical config looks like this;
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
Nie jest jednak tak wspaniale z tą niezależnością technologiczną, jak mogłoby się wydawać. Pora zatem uzależnić aplikację od Apache MyFaces i dopisać odpowiednią sekcję do deskryptora wdrożenia web.xml zgodnie z treścią komunikatu.
 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
</web-app>
I tak mógłbym cały czas próbować uruchamiać aplikację bazując na błędach, które są zgłaszane przez wtyczkę mavenową dla Geronimo, gdzie wciąż widniał komunikat o potencjalnym braku konfiguracji <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>, aż po bodajże 10-tym razie, bez pomysłów i prawie całkowicie zrezygnowany (wyjątkowo szybko się zniechęcam), spojrzałem do dziennika zdarzeń (log) - target/geronimo-logs/org.apache.geronimo.mavenplugins.geronimo.server.StartServerMojo.log, którego utworzenie nakazałem przez konfigurację parametru logOutput (z wartością true) w pom.xml, a tam:
 Geronimo startup complete
10:34:01,031 INFO [ServletContextListener] Welcome to Seam 2.0.3.CR1
...
10:34:23,265 ERROR [log] Failed startup of context
org.apache.geronimo.jetty6.handler.TwistyWebAppContext@71eb24{/seam-richfaces-tree,
file:/C:/projs/sandbox/seam-richfaces-tree/target/geronimo-jetty6-javaee5-2.1.1/
repository/pl/jaceklaskowski/seam/seam-richfaces-tree/1.0/seam-richfaces-tree-1.0.war/}
java.lang.RuntimeException: Could not create Component: org.jboss.seam.core.validators
at org.jboss.seam.init.Initialization.addComponent(Initialization.java:989)
at org.jboss.seam.init.Initialization.installComponents(Initialization.java:911)
at org.jboss.seam.init.Initialization.init(Initialization.java:589)
at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:34)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:540)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:510)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
at org.apache.geronimo.jetty6.JettyWebAppContext$StartCommand.lifecycleMethod(JettyWebAppContext.java:366)
...
Caused by: java.lang.NoClassDefFoundError: [Lorg/hibernate/validator/InvalidValue;
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2395)
at java.lang.Class.privateGetPublicMethods(Class.java:2519)
at java.lang.Class.getMethods(Class.java:1406)
at org.jboss.seam.Component.hasAnnotation(Component.java:1070)
at org.jboss.seam.Component.(Component.java:229)
at org.jboss.seam.Component.(Component.java:217)
at org.jboss.seam.init.Initialization.addComponent(Initialization.java:974)
... 76 more
Wniosek jeden, brakuje zależności aplikacji (bibliotek pomocnicych), które świadomie początkowo zawęziłem wyłącznie do org.jboss.seam.jboss-seam (sekcja dependencies w pom.xml). Teraz zaczyna się żmudna praca analityka cudzej pracy i odgadywania zależności projektu JBoss Seam. Najłatwiej byłoby po prostu dodać wszystkie seamowe zależności opisane w dokumencie Seam published to Maven w sekcji Using Seam with Maven, ale ja postanowiłem zawęzić konfigurację zależności do niezbędnego minimum. Analizując root-2.0.3.CR1.pom odnajduję wskazanie na brakującą zależność Hibernate Validator.
 <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.GA</version>
</dependency>
Po tej zmianie w pom.xml uruchomienie mvn clean pre-integration-test kończy się z BUILD SUCCESSFUL.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ mvn clean pre-integration-test
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building seam-richfaces-tree Maven Webapp
[INFO] task-segment: [clean, pre-integration-test]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory c:\projs\sandbox\seam-richfaces-tree\target
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [war:war]
[INFO] Packaging webapp
[INFO] Assembling webapp[seam-richfaces-tree] in [c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree]
[INFO] Processing war project
[INFO] Webapp assembled in[234 msecs]
[INFO] Building war: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war
Downloading: http://download.java.net/maven/1//woodstox/poms/wstx-asl-3.2.1.pom
Downloading: http://people.apache.org/repo/m2-incubating-repository//woodstox/wstx-asl/3.2.1/wstx-asl-3.2.1.pom
Downloading: http://repo1.maven.org/maven2/woodstox/wstx-asl/3.2.1/wstx-asl-3.2.1.pom
Downloading: http://repository.jboss.org/maven2/woodstox/wstx-asl/3.2.1/wstx-asl-3.2.1.pom
Downloading: http://repo1.maven.org/maven2/woodstox/wstx-asl/3.2.1/wstx-asl-3.2.1.pom
[INFO] [geronimo:start-server {execution: start-server}]
[INFO] Using assembly configuration: geronimo-jetty
[INFO] Using assembly artifact: org.apache.geronimo.assemblies:geronimo-jetty6-javaee5:zip:bin:2.1.1:provided
[INFO] Using geronimoHome: C:\projs\sandbox\seam-richfaces-tree\target\geronimo-jetty6-javaee5-2.1.1
[INFO] Installing assembly...
[INFO] Expanding:
C:\.m2\org\apache\geronimo\assemblies\geronimo-jetty6-javaee5\2.1.1\geronimo-jetty6-javaee5-2.1.1-bin.zip into
C:\projs\sandbox\seam-richfaces-tree\target
[INFO] Starting Geronimo server...
[INFO] Selected option set: morememory
[INFO] Redirecting output to:
c:\projs\sandbox\seam-richfaces-tree\target\geronimo-logs\org.apache.geronimo.mavenplugins.geronimo.server.StartServerMojo.log
[INFO] Waiting for Geronimo server...
log4j:WARN No appenders could be found for logger (org.apache.geronimo.mavenplugins.geronimo.ServerProxy).
log4j:WARN Please initialize the log4j system properly.
[INFO] Geronimo server started in 0:00:32.094
[INFO] [geronimo:deploy-module {execution: deploy-ear}]
[INFO] Using non-artifact based module archive: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war
[INFO] Using non-artifact based plan: c:\projs\sandbox\seam-richfaces-tree\src\main\resources\geronimo-web.xml
[INFO] Distributing module artifact: c:\projs\sandbox\seam-richfaces-tree\target\seam-richfaces-tree.war with plan
c:\projs\sandbox\seam-richfaces-tree\src\main\resources\geronimo-web.xml
[INFO] Starting modules...
[INFO] Starting module: pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] Started module(s):
[INFO] [0] pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 minutes 5 seconds
To lubię. Teraz mogłoby paść pytanie jak sprawdzić działanie aplikacji? Mamy możliwość automatycznego uruchomienia testów za pomocą Selenium albo Twill (książka o nich czeka na lekturę w Bibliotece Warszawskiego JUGa) albo po prostu uruchomienie Geronimo oddzielnie, poza projektem i na nim wykonanie rozmieszczenia aplikacji. Sprawdzam trop.

Uruchamiam Geronimo z ./bin/geronimo.sh run -vv.
 jlaskowski@work /cygdrive/c/geronimo
$ ./bin/geronimo.sh run -vv
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
11:27:19,015 DEBUG [BasicKernel] Starting boot
...
a następnie w innej konsoli:
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Na konsoli Geronimo pojawiają się wtedy komunikaty:
 11:35:01,859 INFO  [ServletContextListener] Welcome to Seam 2.0.3.CR1
...
a po chwili
 Caused by: java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
No tak! Przecież w samej dokumentacji Seama w rozdziale Chapter 2. Getting started with Seam, using seam-gen była o tym wzmianka, aby podnieść parametry pamięci dla serwera aplikacyjnego, do uruchomienia Seama, np. -Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256.

Zatrzymuję serwer Geronimo (zwykłe Ctrl+C wystarczy, chociaż szybciej po prostu kill -9 czy podobnie) i ponownie uruchamiam już z podniesionymi parametrami dotyczącymi pamięci.
 jlaskowski@work /cygdrive/c/geronimo
$ GERONIMO_OPTS="-Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256" ./bin/geronimo.sh run -vv
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
11:41:23,343 DEBUG [BasicKernel] Starting boot
...
Geronimo startup complete
I wykonanie polecenia rozmieszczającego aplikację na Geronimo.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
Error: Unable to distribute seam-richfaces-tree.war:
org.apache.geronimo.kernel.config.ConfigurationAlreadyExistsException:
Configuration already exists:
pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war

Configuration already exists:
pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
Może być konieczne najpierw odinstalowanie modułu (=aplikacji webowej) po wcześniejszej niepomyślnej instalacji zakończonej OOME.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ c\:/geronimo/bin/deploy.sh -u system -p manager undeploy \
pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
Module pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
uninstalled.

Undeployed pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war
I podejście finalne, podsumowujące prace - deploy.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ c\:/geronimo/bin/deploy.sh -u system -p manager deploy \
target/seam-richfaces-tree.war src/main/resources/geronimo-web.xml
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: var\temp
Using JRE_HOME: c:\apps\java5\jre
Deployed pl.jaceklaskowski.seam/seam-richfaces-tree/1.0/war @
/seam-richfaces-tree
I jest gites! Sprawdzam jeszcze konsolę Geronimo:
 11:50:12,656 INFO  [ServletContextListener] Welcome to Seam 2.0.3.CR1
...
11:50:32,000 INFO [Initialization] initializing Seam
...
11:50:32,406 INFO [Initialization] Installing components...
...
11:50:32,812 INFO [Contexts] starting up: org.jboss.seam.navigation.pages
11:50:32,890 INFO [Pages] no pages.xml file found: /WEB-INF/pages.xml
11:50:32,890 INFO [Contexts] starting up: org.jboss.seam.security.facesSecurityEvents
11:50:32,890 INFO [Initialization] done initializing Seam
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.PRETTY_HTML' found, using default value true
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.ALLOW_JAVASCRIPT' found, using default value true
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS' found, using default value true
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.RENDER_VIEWSTATE_ID' found, using default value true
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.STRICT_XHTML_LINKS' found, using default value true
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.CONFIG_REFRESH_PERIOD' found, using default value 2
11:50:32,921 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.VIEWSTATE_JAVASCRIPT' found, using default value false
11:50:32,921 INFO [MyfacesConfig] Tomahawk jar not available. Autoscrolling, DetectJavascript, AddResourceClass and CheckExtensionsFilter are disabled now.
11:50:32,921 INFO [MyfacesConfig] Starting up Tomahawk on the RI-JSF-Implementation.
11:50:32,921 INFO [MyfacesConfig] Starting up Tomahawk on the MyFaces-JSF-Implementation
11:50:32,921 ERROR [MyfacesConfig] Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.
11:50:33,125 INFO [AbstractFacesInitializer] ServletContext
'C:\geronimo\repository\pl\jaceklaskowski\seam\seam-richfaces-tree\1.0\seam-richfaces-tree-1.0.war\' initialized.
Mimo ostatniego błędu można uznać rozmieszczenie aplikacji za pomyślne. Jeszcze tylko zajrzeć przeglądarką pod adres http://localhost:8080/seam-richfaces-tree/.
I koniec. Czyżby? Nie, jeszcze nie! W końcu to jedynie przykładowy index.jsp, który tworzony jest w ramach zestawiania projektu mavenowym archetypem maven-archetype-webapp. Mimo to Seam już się wzbudził, co można zaobserwować na konsoli Geronimo.
 11:53:03,343 INFO  [Contexts] starting up: org.jboss.seam.web.session
11:53:03,343 INFO [Contexts] starting up: org.jboss.seam.security.identity
Aby go jednak na dobre rozruszać musielibyśmy przynajmniej zajrzeć pod adres http://localhost:8080/seam-richfaces-tree/witaj.seam.

Błąd! Jednak zajmę się tym ostatnim komunikatem błędu
 ERROR [MyfacesConfig] Both MyFaces and the RI are on your classpath. 
Please make sure to use only one of the two JSF-implementations.
Tylko skąd on się bierze?! W katalogu WEB-INF/lib nie ma nic co wskazywałoby na obecność JSF RI.
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ ls -l target/seam-richfaces-tree/WEB-INF/lib/
total 5208
-rwx------+ 1 jlaskowski None 443432 Apr 18 13:31 antlr-2.7.6.jar
-rwx------+ 1 jlaskowski None 26361 Jun 7 12:23 asm-1.5.3.jar
-rwx------+ 1 jlaskowski None 16757 Apr 18 13:31 asm-attrs-1.5.3.jar
-rwx------+ 1 jlaskowski None 282338 Jun 7 12:23 cglib-2.1_3.jar
-rwx------+ 1 jlaskowski None 175426 Jun 7 23:44 commons-collections-2.1.1.jar
-rwx------+ 1 jlaskowski None 38015 Apr 18 12:04 commons-logging-1.0.4.jar
-rwx------+ 1 jlaskowski None 303207 Jun 18 22:19 dom4j-1.6.1-jboss.jar
-rwx------+ 1 jlaskowski None 208048 Apr 18 13:30 ehcache-1.2.3.jar
-rwx------+ 1 jlaskowski None 29309 Jun 18 22:19 el-api-1.0.jar
-rwx------+ 1 jlaskowski None 2242529 Jun 19 11:18 hibernate-3.2.4.sp1.jar
-rwx------+ 1 jlaskowski None 60992 Jun 19 11:18 hibernate-validator-3.0.0.GA.jar
-rwx------+ 1 jlaskowski None 459663 Jun 18 22:19 javassist-3.3.GA.jar
-rwx------+ 1 jlaskowski None 133493 Jun 18 22:19 jboss-el-2.0.1.GA.jar
-rwx------+ 1 jlaskowski None 869271 Jun 18 22:19 jboss-seam-2.0.3.CR1.jar
-rwx------+ 1 jlaskowski None 8812 Jun 7 12:23 jta-1.0.1B.jar
Jest kilka jarów, które są niepotrzebne - jta, el-api, commons-logging, commons-collections, cglib, asm* oraz antlr, które są dostępne w Geronimo, ale gdzie jest cokolwiek związanego z JSF RI?! Wykluczam wspomniane jary - nie zaszkodzi, a może przypadkiem pomoże ;-)
 jlaskowski@work /cygdrive/c/projs/sandbox/seam-richfaces-tree
$ ls -l target/seam-richfaces-tree/WEB-INF/lib/
total 4644
-rwx------+ 1 jlaskowski None 443432 Apr 18 13:31 antlr-2.7.6.jar
-rwx------+ 1 jlaskowski None 303207 Jun 18 22:19 dom4j-1.6.1-jboss.jar
-rwx------+ 1 jlaskowski None 2242529 Jun 19 11:18 hibernate-3.2.4.sp1.jar
-rwx------+ 1 jlaskowski None 60992 Jun 19 11:18 hibernate-validator-3.0.0.GA.jar
-rwx------+ 1 jlaskowski None 459663 Jun 18 22:19 javassist-3.3.GA.jar
-rwx------+ 1 jlaskowski None 133493 Jun 18 22:19 jboss-el-2.0.1.GA.jar
-rwx------+ 1 jlaskowski None 869271 Jun 18 22:19 jboss-seam-2.0.3.CR1.jar
Po zmianach w pomie od razu lepiej - komunikat poszedł sobie (zapewne zaraz, kiedy pozbyłem się el-api-1.0.jar).
 12:26:15,593 INFO  [Contexts] starting up: org.jboss.seam.security.facesSecurityEvents
12:26:15,593 INFO [Initialization] done initializing Seam
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.PRETTY_HTML' found, using default value true
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.ALLOW_JAVASCRIPT' found, using default value true
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS' found, using default value true
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.RENDER_VIEWSTATE_ID' found, using default value true
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.STRICT_XHTML_LINKS' found, using default value true
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.CONFIG_REFRESH_PERIOD' found, using default value 2
12:26:15,625 INFO [MyfacesConfig] No context init parameter 'org.apache.myfaces.VIEWSTATE_JAVASCRIPT' found, using default value false
12:26:15,625 INFO [MyfacesConfig] Tomahawk jar not available. Autoscrolling, DetectJavascript, AddResourceClass and CheckExtensionsFilter are disabled now.
12:26:15,625 INFO [MyfacesConfig] Starting up Tomahawk on the MyFaces-JSF-Implementation
12:26:15,875 INFO [AbstractFacesInitializer] ServletContext
'C:\geronimo\repository\pl\jaceklaskowski\seam\seam-richfaces-tree\1.0\seam-richfaces-tree-1.0.war\' initialized.
Nie poprawiło to jednak wyświetlania strony - wciąż ten błąd z pustą stroną, która teoretycznie jest xhtmlową.

Spróbuję z jboss-seam-ui w pom.xml. Nic! Ponownie ten sam błąd! Temat zostawiam na później.

Kompletny pom.xml prezentuje się następująco:
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.seam</groupId>
<artifactId>seam-richfaces-tree</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>seam-richfaces-tree Maven Webapp</name>
<url>http://www.jaceklaskowski.pl</url>
<repositories>
<repository>
<id>repository.jboss.org</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
<version>2.0.3.CR1</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam-ui</artifactId>
<version>2.0.3.CR1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.GA</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
</exclusion>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>seam-richfaces-tree</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.geronimo.buildsupport</groupId>
<artifactId>geronimo-maven-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<assemblies>
<assembly>
<id>geronimo-jetty</id>
<groupId>org.apache.geronimo.assemblies</groupId>
<artifactId>geronimo-jetty6-javaee5</artifactId>
<version>2.1.1</version>
<classifier>bin</classifier>
<type>zip</type>
</assembly>
<assembly>
<id>geronimo-tomcat</id>
<groupId>org.apache.geronimo.assemblies</groupId>
<artifactId>geronimo-tomcat6-javaee5</artifactId>
<version>2.1.1</version>
<classifier>bin</classifier>
<type>zip</type>
</assembly>
</assemblies>
<defaultAssemblyId>geronimo-jetty</defaultAssemblyId>
<optionSets>
<optionSet>
<id>default</id>
<options>
<option>-XX:MaxPermSize=128m</option>
</options>
</optionSet>
<optionSet>
<id>morememory</id>
<options>
<option>-Xmx512m</option>
<option>-XX:MaxPermSize=128m</option>
</options>
</optionSet>
</optionSets>
</configuration>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start-server</goal>
</goals>
<configuration>
<assemblyId>geronimo-jetty</assemblyId>
<logOutput>true</logOutput>
<background>true</background>
<verifyTimeout>300</verifyTimeout>
<refresh>true</refresh>
<veryverbose>true</veryverbose>
<options>morememory</options>
</configuration>
</execution>
<execution>
<id>deploy-ear</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy-module</goal>
</goals>
<configuration>
<moduleArchive>target/seam-richfaces-tree.war</moduleArchive>
<modulePlan>src/main/resources/geronimo-web.xml</modulePlan>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Dla dociekliwych kompletna aplikacja seam-richfaces-tree jako projekt mavenowy do pobrania jako seam-richfaces-tree.zip. Chętni do poprawek mile widziani.

Pytanie konkursowe: Jak nazywa się wtyczka mavenowa do zarządzania Apache Geronimo?