Thursday Dec 11, 2008

TOTD # 59: Alternative JSF implementations on GlassFish - MyFaces and Tomahawk


GlassFish comes bundled with an industry grade implementation of Java Server Faces codenamed Mojarra. It is the most complete, up-to-date and well-tested JSF implementation and used pretty extensively. GlassFish v2 and v3 Prelude ships with JSF 1.2.x-compliant implementation that is defined as part of Java EE 5. GlassFish v3 trunk contains JSF 2.0-compliant implementation that is getting defined as part of Java EE 6. The latest version of Mojarra can be installed from the Update Center.

But GlassFish does not restrict you to Mojarra and instead it embraces other JSF implementations easily. This blog uses MyFaces, an alternate JavaServer Faces implementation from Apache, to demonstrate that. If you are interested in a brief summary of what it takes to use these alternate implementations on GlassFish then scroll to the end of this entry.

MyFaces also provides several component libraries such as Tomahawk, Trinidad, and Tobago for building web applications. This blog shows how MyFaces Tomahawk samples can be deployed on GlassFish v2 and v3. The basic integration hooks between GlassFish and other JSF implementations remain the same and are independent of the component library.

Lets get started and understand all the glory!

Download MyFaces Tomahawk samples from here. The download consists of 4 WAR files and they are unzipeed in the current directory. So create a new directory and then unzip the bundle if you want to organize it slightly better. The getting Started instructions require you to copy "simple.war" where as the actual WAR filename is "myfaces-example-simple-1.1.8.war". Anyway, we are going to deploy this sample on GlassFish v2, v3 Prelude, and v3 trunk and what needs to be done to use the MyFaces implementation bundled within the WAR.
  1. Deploy using Mojarra on GlassFish v2
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v2 using "asadmin deploy myfaces-example-simple-1.1.8.war" and it shows the following message:

      [#|2008-12-05T11:00:43.710-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=22;_ThreadName=Thread-43;|
      deployed with moduleid = myfaces-example-simple-1.1.8|#]

      [#|2008-12-05T11:00:44.296-0800|INFO|sun-appserver9.1|javax.enterprise.resource.webcontainer.jsf.config|_ThreadID=21;
      _ThreadName=httpWorkerThread-4848-1;/myfaces-example-simple-1.1.8;|Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03) for context '/myfaces-example-simple-1.1.8'|#]

      The bold text indicates that Mojarra 1.2 bundled with GlassFish v2 is used as the JSF runtime, the exact version is shown in the bold text. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf" and looks like:



      The following error message is shown as you click through the samples:

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      This error message is generated by MyFaces and may be ignored. I think the message should be a WARNING instead of an ERROR.
  2. Deploy using MyFaces on GlassFish v2
    1. Create a directory "simple" and unjar "myfaces-example-simple-1.1.8.war" in there.
    2. Add "WEB-INF/sun-web.xml" and specify the contents as:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useMyFaces" value="true"/>
      </sun-web-app>

      The key point to notice is the property name "useMyFaces". The name is slightly mis-leading because the switch essentially tells GlassFish runtime to use the bundled Java Server Faces runtime and is not restricted to MyFaces only. This is fixed in GlassFish v3 and is discussed later.
    3. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v2.war \*".
    4. Deploy the generated WAR on GlassFish v2 as "asadmin deploy myfaces-simple-v2.war". It shows the following message:

      . . .

      [#|2008-12-05T11:11:25.615-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=24;_ThreadName=Thread-257;|
      deployed with moduleid = myfaces-simple-v2|#]

      [#|2008-12-05T11:11:26.266-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,266 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading standard config org/apache/myfaces/resource/standard-faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.290-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,290 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.309-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,308 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml
      |#]

      [#|2008-12-05T11:11:26.337-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,337 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml
      |#]

      [#|2008-12-05T11:11:26.349-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,349 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-api-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-impl-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar
      |#]

      . . .

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.
      |#]

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/' initialized.
      |#]

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahaw 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v2" is very similar as shown below:

  3. Deploy using Mojarra on GlassFish v3 Prelude - This is very similar experience as with GlassFish v2.
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v3 shows the following message:

      Dec 5, 2008 11:27:17 AM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra (1.2_10-b01-FCS) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 11:27:18 AM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-example-simple-1.1.8 at /myfaces-example-simple-1.1.8
      Dec 5, 2008 11:27:18 AM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-example-simple-1.1.8 done is 3470 ms

      The bold text clearly indicates that Mojarra 1.2 bundled, exact version shown in the bold text, with GlassFish v3 is used as the JSF runtime. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf". Viewing the sample in browser shows:

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      and may be ignored. None of the messages that indicate classloading, as shown for GlassFish v2 above, are displayed. I suspect these are standard messages displayed by MyFaces without taking into consideration that an alternate JSF runtime can be used to run these samples.
  4. Deploy using MyFaces on GlassFish v3 Prelude - There is no way to override JSF implementation with GlassFish v3 Prelude. So even though deploying "myfaces-simple-v2.war" will work fine but viewing the web page at "http://localhost:8080/myfaces-simple-v2/" will show the following exception:



    Basically, a web application cannot use MyFaces implementation on GlassFish v3 Prelude. However Mojarra provides a fully-compliant and feature-rich JSF implementation and is already baked in GlassFish v3 Prelude.
  5. Deploy using Mojarra on GlassFish v3 Trunk
    1. Pick your GlassFish v3 Build Flavor, this blog uses the trunk.
    2. Deploy the original sample as "asadmin deploy myfaces-example-simple-1.1.8.war" and the following log messages are shown:

      Dec 5, 2008 12:35:17 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 12:35:18 PM org.apache.catalina.core.ApplicationContext log
      SEVERE: WebModule[/myfaces-example-simple-1.1.8]PWC1275: Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
      java.lang.NoClassDefFoundError: com/sun/facelets/tag/jsf/ComponentHandler
              at java.lang.ClassLoader.defineClass1(Native Method)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
              at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
              at org.glassfish.web.loader.WebappClassLoader.findClass(WebappClassLoader.java:974)

      This happens because the application has dependencies on internal classes of Facelets 1.1.x. That makes the application non-compatible with Mojarra 2.x which comes bundled with Facelets 2.0.
    3. Lets instruct the application to disable the Facelets 2.0 baked in Mojarra by adding the following application wide context parameter in "web.xml":

      <context-param>
             <param-name>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</param-name>
             <param-value>true</param-value>
       </context-param>

      Now the Facelets 1.1.x classes bundled with the application are used. With this change, the application gets deployed correctly and shows the following log message:

      Dec 5, 2008 2:50:21 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-simple-v3'
      Dec 5, 2008 2:50:21 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3 at /myfaces-simple-v3
      Dec 5, 2008 2:50:21 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3 done is 1513 ms

      The important thing to note here is that Mojarra 2.0.0 implementation (as indicated by the bold text) is used as JSF runtime. This is the newest and the greatest runtime that implements JSF 2.0 specification and baked in GlassFish v3 trunk. The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3/" looks like:

  6. Deploy using MyFaces on GlassFish v3 Trunk
    1. Download the latest GlassFish v3 Nightly.
    2. Lets deploy the WAR file previously created as "asadmin deploy myfaces-simple-v2.war". The main page of the application is accessible at "http://localhost:8080/myfaces-simple-v2".
    3. The "useMyFaces" property, as specified in "sun-web.xml", is expected to work for any bundled JSF implementation. The recommended way to deploy such a web application in GlassFish v3 is to use the property "useBundledJsf". The updated "sun-web.xml" is shown below:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useBundledJsf" value="true"/>
      </sun-web-app>
    4. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v3-usebundled.war \*".
    5. Deploy the generated WAR on GlassFish v3 as "asadmin deploy myfaces-simple-v3-usebundled.war". It shows the following message:

      . . .

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,786 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,806 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,828 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-api-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-impl-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar

      . . .

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,763 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/' initialized.

      Dec 5, 2008 3:19:55 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3-usebundled at /myfaces-simple-v3-usebundled
      Dec 5, 2008 3:19:55 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3-usebundled done is 1994 ms

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahawk 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3-usebundled" is very similar as shown below:



Here is a brief summary of how MyFaces/Tomahawk sample is deployed using Mojarra and MyFaces on GlassFish:

JSF Implementations
Mojarra MyFaces
GlassFish v2 Default "useMyFaces" property in "sun-web.xml"
GlassFish v3 Prelude Default Not supported
GlassFish v3 Trunk Disable Facelets 2.0 in "web.xml" "useMyFaces" OR "useBundledJsf" property in "sun-web.xml"
Disable Facelets 2.0 in "web.xml" (only for Facelets 1.1.x dependencies)

The steps described above for MyFaces can be used with alternate JSF implementations as well. Which JSF implementation do you use ?

Just like Tomahawk components, Trinidad and Tobago libraries should work with Mojarra as well. Have you tried them ?

Technorati: glassfish javaserverfaces mojarra apache myfaces tomahawk
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today