29 kwietnia 2008

Tworzenie projektu aplikacji JSF z pomocą myfaces-archetype-trinidad

Mam wrażenie, że ten tydzień obfituje w rozpoznawanie archetypów mavenowych. Potrzebowałem szybko stworzyć aplikację JSF i mogło być szybko, gdyby nie fakt, że teraz zanim za cokolwiek się zabiorę, to mam tyle opcji, że nie wiem, co ostatecznie wybrać (nie wiem, co gorsze - nie wiedzieć z czego wybrać, bo ma się wiele opcji, czy nie znając żadnej?!). Weźmy jako przykład owe stworzenie aplikacji JSF - mogę skorzystać z NetBeans IDE (Właśnie! Miałem pobrać finalną wersję NetBeans IDE 6.1!), albo Eclipse IDE, albo jeszcze inne IDE, które byłoby dedykowane do pracy z JSF. Mogę również skorzystać z Apache Maven 2 i skorzystać z jednego z wielu archetypów dedykowanych do stworzenia aplikacji JSF dostarczanych przez Apache MyFaces - MyFaces Archetypes for Maven. A to tylko tak na szybko, bo pewnie jest jeszcze kilka innych opcji. Niejednokrotnie jestem pytany o moje wrażenia dotyczące bibliotek kontrolek JSF udostępniane przez MyFaces, więc nie wahając się długo odhaczyłem kolejne zadanie z mojej listy do ewaluacji - sprawdzić utworzenie aplikacji JSF z pomocą archetypu udostępnianego przez MyFaces myfaces-archetype-trinidad.

Archetyp myfaces-archetype-trinidad dostępny jest w repozytorium m2 jako org.apache.myfaces.buildtools.myfaces-archetype-trinidad. Ostatnia wersja to 1.0.1. Jak napisano w MyFaces Archetypes for Maven wystarczy uruchomić mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org i wybrać odpowiednią opcję do stworzenia aplikacji JSF z danymi rozszerzeniami - w moim przypadku będzie to 5: remote -> myfaces-archetype-trinidad (Simple Web application using Apache Myfaces and Trinidad).
 jlaskowski@work /cygdrive/c/projs/sandbox
$ mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [archetype:generate] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:generate]
Choose archetype:
1: remote -> myfaces-archetype-helloworld (Simple Web application using Apache Myfaces)
2: remote -> myfaces-archetype-helloworld-facelets (Simple Web application using Apache Myfaces and Facelets)
3: remote -> myfaces-archetype-helloworld-portlets (Simple Web application using Apache Myfaces and Portlets)
4: remote -> myfaces-archetype-jsfcomponents (Simple JSF Component using Apache Myfaces)
5: remote -> myfaces-archetype-trinidad (Simple Web application using Apache Myfaces and Trinidad)
Choose a number: (1/2/3/4/5): 5
Define value for groupId: : pl.jaceklaskowski.myfaces
Define value for artifactId: : myfaces-witajswiecie
Define value for version: 1.0-SNAPSHOT: : 1.0.0
Define value for package: : pl.jaceklaskowski.myfaces
Confirm properties configuration:
groupId: pl.jaceklaskowski.myfaces
artifactId: myfaces-witajswiecie
version: 1.0.0
package: pl.jaceklaskowski.myfaces
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: myfaces-archetype-trinidad:1.0.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: packageName, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: basedir, Value: c:\projs\sandbox
[INFO] Parameter: package, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: artifactId, Value: myfaces-witajswiecie
...
[INFO] ********************* End of debug info from resources from generated POM ***********************
[INFO] OldArchetype created in dir: c:\projs\sandbox\myfaces-witajswiecie
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
Teraz wystarczy jedynie mvn package i uruchomić aplikację z Jetty - mvn jetty:run (w zasadzie to mvn package jest wykonywany przez uruchomieniem Jetty, więc mogłoby być zaniechane).

Warto zauważyć, że pobierana wersja MyFaces Trinidad to 1.2.5, podczas gdy zgodnie ze stroną główną projektu mamy już wersję 1.2.7 (March 16, 2008 - MyFaces Trinidad 1.2.7 Released). Zaraz i tym się zajmę.
 jlaskowski@work /cygdrive/c/projs/sandbox/myfaces-witajswiecie
$ mvn package
...
[INFO] [war:war]
[INFO] Packaging webapp
[INFO] Assembling webapp[myfaces-witajswiecie] in [c:\projs\sandbox\myfaces-witajswiecie\target\myfaces-witajswiecie]
[INFO] Processing war project
[INFO] Webapp assembled in[422 msecs]
[INFO] Building war: c:\projs\sandbox\myfaces-witajswiecie\target\myfaces-witajswiecie.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
Uruchamiam aplikację.
 jlaskowski@work /cygdrive/c/projs/sandbox/myfaces-witajswiecie
$ mvn -PjettyConfig clean jetty:run
...
[INFO] [jetty:run]
[INFO] Configuring Jetty for project: A custom project using myfaces
[INFO] Webapp source directory = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp
[INFO] web.xml file = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp\WEB-INF\web.xml
[INFO] Classes = C:\projs\sandbox\myfaces-witajswiecie\target\classes
2008-04-28 22:53:59.273::INFO: Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /myfaces-witajswiecie
[INFO] Tmp directory = determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] Webapp directory = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp
[INFO] Starting jetty 6.1.8 ...
2008-04-28 22:53:59.351::INFO: jetty-6.1.8
2008-04-28 22:53:59.491::INFO: No Transaction manager found - if your webapp requires one, please configure one.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.PRETTY_HTML' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.ALLOW_JAVASCRIPT' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.RENDER_VIEWSTATE_ID' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.STRICT_XHTML_LINKS' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getLongInitParameter
INFO: No context init parameter 'org.apache.myfaces.CONFIG_REFRESH_PERIOD' found, using default value 2
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.VIEWSTATE_JAVASCRIPT' found, using default value false
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig createAndInitializeMyFacesConfig
INFO: Tomahawk jar not available. Autoscrolling, DetectJavascript, AddResourceClass and CheckExtensionsFilter are disabled now.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig createAndInitializeMyFacesConfig
INFO: Starting up Tomahawk on the MyFaces-JSF-Implementation
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedStandardConfig
INFO: Reading standard config META-INF/standard-faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedClassloaderConfigurations
INFO: Reading config
jar:file:/C:/.m2/org/apache/myfaces/trinidad/trinidad-impl/1.2.5/trinidad-impl-1.2.5.jar!/META-INF/faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedWebAppConfig
INFO: Reading config /WEB-INF/faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: Starting up MyFaces-package : myfaces-api in version : 1.2.2 from path :
file:/C:/.m2/org/apache/myfaces/core/myfaces-api/1.2.2/myfaces-api-1.2.2.jar
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: Starting up MyFaces-package : myfaces-impl in version : 1.2.2 from path :
file:/C:/.m2/org/apache/myfaces/core/myfaces-impl/1.2.2/myfaces-impl-1.2.2.jar
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: MyFaces-package : tomahawk-sandbox not found.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: MyFaces-package : tomahawk not found.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.util.LocaleUtils toLocale
WARNING: Locale name in faces-config.xml null or empty, setting locale to default locale : en_PL
Apr 28, 2008 10:54:01 PM org.apache.myfaces.config.FacesConfigurator handleSerialFactory
INFO: Serialization provider : class org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory
Apr 28, 2008 10:54:01 PM org.apache.myfaces.webapp.AbstractFacesInitializer initFaces
INFO: ServletContext 'C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp\' initialized.
2008-04-28 22:54:01.739::INFO: Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.
Otwieram przeglądarkę na stronie http://localhost:8080/myfaces-witajswiecie/faces/index.jspx i mam podstawową aplikację JSF z wykorzystaniem MyFaces Trinidad.


Po wpisaniu Jacek Laskowski i wciśnięciu press me pojawiła się kolejna strona z okienkiem dialogowym.


Pozostaje jeszcze uaktualnić wersję Trinidada i ponownie uruchomić. Dla uproszczenia aktualizacji wersji autorzy archetypu umieścili numery wersji w sekcji properties w pliku pom.xml, tak że nie jest konieczna ich aktualizacja w kilku miejscach (można również uruchomić aplikację z poziomu mvn z podaniem wersji z linii poleceń, co ma tę zaletę, że nie modyfikujemy konfiguracji w pom.xml, a możemy bawić się własnymi wersjami). Uaktualniam trinidad.version do 1.2.7
 <trinidad.version>1.2.7</trinidad.version>
i ponownie uruchamiam aplikację. Też działa! Aplikacja jest gotowa do rozbudowania. Dalej to już czyste programowanie w JSF z MyFaces Trinidad, tym razem jednak już zapewne z pomocą jakiegoś IDE. Zawsze krążyłem koło kontrolek Trinidad, aby rozpoznać co oferują, więc teraz nadarza się okazja i to zadanie wykreślić z listy oczekujących.

Pytanie konkursowe: Jak nazywa się archetyp do automatycznego tworzenia aplikacji JSF opartej o MyFaces i Trinidad? oraz znacznie trudniejsze: Dlaczego do uruchomienia aplikacji musiałem podać adres http://localhost:8080/myfaces-witajswiecie/faces/index.jspx zamiast http://localhost:8080/myfaces-witajswiecie? Jedno z pytań, które możnaby dodatkowo zadać w kontekście tego wpisu to W jaki sposób uruchomić stworzoną aplikację z wersją Trinidad 1.2.7 bez modyfikacji pom.xml? Nagród nie ma.