This blog states my personal opinions and are not representative of IBM or the WebSphere branded products.

Thursday, November 3, 2011

MyFaces 2.0 and WebSphere Application Server v7

JavaServer™ Faces (JSF) 2.0 was designed to work with Java EE 5 application servers.  The problem is that annotation processing and injections are not portable as written by the specs.  Each implementation of JSF has proprietary ways of plugging into an application server’s injection engine and most perform their own annotation scanning.  The following article will guide you through setting up MyFaces 2.0 on WebSphere Application Server, using a newly delivered annotation provider (as of fix pack 7.0.0.19) to give you built in injection engine support.

Setting up the MyFaces 2.0 binaries

Go to the MyFaces download page (http://myfaces.apache.org/download.html) and find the MyFaces Core 2.0.x compressed file that you would like to use.   Download and extract the files to a directory.  Look for a lib folder in the root directory.  The lib folder contains the jar files to create a WebSphere Application Server isolated shared library.  To begin, remove the ServletContainerInitializer and the Tomcat LifeCycleProvider that comes with MyFaces 2.0. 

ServletContainerInitializers are new to Servlet 3.0 and are not supported on WebSphere Application Server  Version 7.  Leaving ServletContainerInitializers  in the services folder of MyFaces will not hurt anything, as it will not be loaded.  MyFaces added this initializer to register the FacesServlet if it found a faces-context.xml in an application.  This means that in WebSphere Application Server Version7 you   define the FacesServlet in your web.xml file, as you would for a JSF 1.2 or earlier application. 

The org.apache.myfaces.config.annotation.LifecycleProvider that comes with MyFaces is specific to Tomcat and should be removed.  You will replace it with one that defines a LifecycleProvider and a LifecycleProviderFactory that were delivered in WebSphere Application Server  Version 7.0.0.19. 
Open up the myfaces-impl-2.0.x.jar file and remove the files in the META-INF\services\ directory. 
When you have completed that step, copy all of the JAR files from the lib directory to a common place on your server where you want to store them.  For this article, the JAR files are copied to ${WAS_INSTALL_ROOT}\optionalLibraries\Apache\MyFaces2.0.2.

When you are finished copying the JAR files, you should have a directory that looks similar to Figure 1.0.  Note: The jars that are delivered with different versions of MyFaces 2.x might not be exactly the same. 

Figure 1.0 ${WAS_INSTALL_ROOT}\optionalLibraries\Apache\MyFaces2.0.2 directory contents


Configuring WAS v7 shared libraries

Next, we configure the JAR files as Isolated Shared libraries.  Isolated Shared libraries have their own classloader that is shared between your applications.  These classloaders are always set to ‘PARENT_LAST’, meaning the classes in these libraries come before any parent classloader classes in the classpath.  You can apply these classloaders to different modules of your application and they will override any runtime classes.  In this manner, we can override the JSF implementation that comes with WebSphere Application Server Version 7 for any application web modules that your Isolated Shared library is applied to.  You will no longer need to set the classloader for your application or its web modules to ‘PARENT_LAST’ when using Isolated Shared libraries.   WebSphere Application Server Version 7 also uses the classloaders to determine if the application has its own implementation of JSF configured, and if so, it will not initialize the JSF implementation in the runtime. 

Log in to your WebSphere Application Server Version 7 administrative console and click on the Environment section of the left hand navigation menu.  Next, click on the Shared libraries link.  Choose the scope that you would like to create the Shared Library for in the dropdown menu and then click the New Button.  Be aware if you choose a scope outside of a single physical machine, you will need to make sure the MyFaces JAR files are manually copied to every machine.  Give your Shared Library a Name, such as, MyFaces 2.0,and add all of the JAR files to the Classpath field, making sure to separate each entry with a new line.   You can use WebSphere Application Server variables, such as ${WAS_INSTALL_ROOT}, to give common paths across machines.  There is a WebSphere-MyFaces20-annotation-provider.jar file that also should be added to your Shared Library.  This JAR file contains the new annotation provider classes and the services files to register them with MyFaces 2.0.  NOTE: This JAR file was added as of WebSphere Application Server Version 7.0.0.19.  The JAR file is located in the ‘optionalLibraries/IBM/JSFProviders’ directory of your WebSphere Application Server installation.  Add the following string to the Classpath of your Shared Library:
${WAS_INSTALL_ROOT}/optionalLibraries/IBM/JSFProviders/WebSphere-MyFaces20-annotation-provider.jar 

Click on the check box for ‘Use an isolated class loader for this shared library’.  Click Apply and Save.  Figure 2.0 shows what your panel should look like.
 Figure 2.0 WebSphere Admin Console screen shot for shared library.  

Configuring your application

Now you are ready to configure your application.  First make sure you have the FacesServlet and the MyFaces StartupConfigureListener defined in the web.xml file of your modules.  See Figure 3.0 for an example.  You need the FacesServlet since, as mentioned previously, the ServletContainerInitializers are not supported on Java EE 5 application servers.  You need the StartupConfigureListener because WebSphere Application Server Version 7 does not support loading of listeners from tld files in Shared Libraries.  Once you have your web.xml file configured, install your JSF 2.0 application in WebSphere Application Server Version 7. 

Figure 3.0 Web.xml

Now you are ready to add the Isolated Shared library to your application.  After you install your application, go to the Applications section in the left hand navigation menu and click on the ‘WebSphere enterprise applications' link.  In this panel, click the ‘Shared library references’ link.  You should see a list of your application’s modules in a table.  Check the box next to the web module you want to use JSF 2.0 with and then click the ‘Reference shared libraries’ button at the top of the table.  In the next panel you should see your MyFaces 2.0 shared library listed in the Available field.  Select it and click the right-arrow button to move it to the Selected list.  Click OK and save.  Figures 3.1 and 3.2 show you what the panels should look like when you are finished.  Repeat these steps for every web module that you want to use JSF 2.0 with.  After you configure the shared library with your application, start the application and start making requests.  You should see that your JSF 2.0 annotations are being injected properly.

Figure 3.1 Shared Library Mapping Panel

Figure 3.2 Shared library references Panel

As you can see, it is fairly simple to configure MyFaces 2.0 with WebSphere Application Server Version 7.  To see JSF 2.0 fully integrated into the WebSphere Application Server runtime, take a look at WebSphere Application Server Version 8, which is an IBM full Java EE 6 application server.  Here is a link to the WebSphere Application Server Version 8 InfoCenter samples gallery that includes some JSF 2.0 samples.