Red Hat

Weblogic 10, Seam, and EJB3

Posted by Jay Balunas    |       |    Tagged as Seam

The latest release of Seam 2.0.2.SP1 includes a completely updated reference guide chapter for deploying Seam on BEA's Weblogic . The primary focus was on working around several issues with Weblogic and EJB3 support.

We will explain and demonstrate how to get the Seam jee5/booking example installed and running on Weblogic 10.0.MP1. This example demonstrates the use of Seam in a Java EE 5 environment using EJB3 with transaction and persistence context management handled by Weblogic.

What you need

First step we need to install Weblogic 10.0.MP1, and create a domain in Development Mode. You can use either the Sun JDK or the JRockit JDK it does not matter to this example.

For this example we'll refer to the seam distribution directory as $SEAM_DIST, BEA home as $BEA_HOME, and the domain home as $DOMAIN_HOME.

The Weblogic varargs issue

For several release of Weblogic you could not deploy an EJB that used variable arguments in its methods. Weblogic's internal EJB compiler confuses variable arguments as if it was a transient modifier. Seam uses variable arguments in one of its internal EJB's TimerServiceDispatcher, so when deployed this produces an error like this:

java.io.IOException: Compiler failed executable.exec: /jboss/apps/bea/wlserver_10.0/user_projects/domains/seam_examples/servers/AdminServer/cache/EJBCompilerCache/5yo5dk9ti3yo/org/jboss/seam/async/
TimerServiceDispatcher_qzt5w2_LocalTimerServiceDispatcherImpl.java:194: modifier transient not allowed here
  public transient javax.ejb.Timer scheduleAsynchronousEvent(java.lang.String arg0,java.lang.Object[] arg1)

To work around this issue there are 2 options:

Option 1) Apply the CR327275 patch, but...

BEA has released a patch that addresses the variable arguments issue. It is named CR327275 and can be requested from BEA through their support organization.

Unfortunately an additional issue that this patch either causes, or exposes has been reported and verified by BEA (CR363182). This issue has to do with certain EJB methods incorrectly left out of Weblogic's generated internal stub classes. Some users have reported that this does not effect them - see this 2.0.2.GA release comment for details.

Option 2) Don't deploy TimerServiceDispatcher EJB

Starting with Seam 2.0.2.CR2 a special Weblogic specific jar has been packaged that does not contain the TimerServiceDispatcher . This is the only Seam EJB that uses variable arguments.

$SEAM_DIST/lib/interop/jboss-seam-wls-compatible.jar

To use this jar simply rename jboss-seam-wls-compatible.jar to jboss-seam.jar and replace the original in your applications EAR file.

We will be using this approach for the jee5/booking example here.

Weblogic's JSF support

Weblogic requires its own JSF 1.2 libraries be deployed when using an EAR based application. I suspect this has to do with classloader visibility while processing EARs and deploying EJBs.

Out of the box Weblogic does not come with its JSF libraries deployed, an like other parts of Weblogic it almost worked as expected.

  1. Start the Server and launch the Weblogic administration console.
  2. Deploy $BEA_HOME/wlserver_10.0/common/deployable-libraries/jsf-1.2.war
  3. Make sure Install this deployment as a library is selected
  4. On the Settings for jsf(1.2,1.2.3.1) page set the Deployment Order to 99 so that it is deployed before autodeployed applications.
  5. Don't forget to activate your changes

Later you will see how to get your application to reference this shared library.

That should be it but you will get errors like the one below when deploying your application.

User defined listener com.sun.faces.config.ConfigureListener failed: java.lang.NullPointerException

Again this is most likely due to classloader visibility issues.. To work around this you need to have the jsf-api.jar from inside the jsf-1.2.war in the $DOMAIN_HOME/lib directory. While you are there you might as well copy in the $SEAM_DIST/lib/hsqldb.jar for the next section. You will need to stop and start your server for these to take effect.

Setting up the example data source

Configuring the seam-jee5-ds is pretty straight forward, and we can do it all through the admin console.

  1. If you have not already, you will need to copy the $SEAM_DIST/lib/hsqldb.jar into the $DOMAIN_HOME/lib directory and restart the server.
  2. Launch the admin console and navigate to $DOMAIN_NAME -> Services -> JDBC -> Data Sources
  3. Create a new data source with the values below.
  • Name = seam-jee5-ds
  • JNDI Name = seam-jee5-ds
  • Set database type to other
  • Database name = hsqldb
  • Host Name = 127.0.0.1
  • Port = 9001
  • Username = sa
  • Driver class = org.hsqldb.jdbc.Driver
  • URL = jdbc:hsqldb:.

Then just choose your domain for the data source and activate your changes.

The example/jee5/booking example

Now Weblogic is all set up we need to make some adjustments to the jee5/booking example. These are mainly configuration file and build script changes.

Configuration File changes

Paths are assumed from the $SEAM_DIST/examples/jee5/booking directory

resources/META-INF/persistence.xml

  • Comment out glassfish properties
  • Set <jta-data-source>seam-jee5-ds</jta-data-source>
  • Add the following properties:
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WeblogicTransactionManagerLookup"/>

resources/WEB-INF/web.xml

  • Because the JSF jars are not going to be packaged in the WAR we need to add:
<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

resources/META-INF/weblogic-application.xml

You must create this file:

<?xml version="1.0" encoding="ISO-8859-1"?>

<weblogic-application>
    <library-ref>
        <library-name>jsf</library-name>
        <specification-version>1.2</specification-version>
        <implementation-version>1.2</implementation-version>
        <exact-match>false</exact-match>
    </library-ref>
    <prefer-application-packages>
        <package-name>antlr.*</package-name>
    </prefer-application-packages>
</weblogic-application>

This allows the EAR to reference the JSF libraries installed above, and also manages a dependency conflict with antlr.

resources/WEB-INF/weblogic.xml

You must create this file:

<?xml version="1.0" encoding="UTF-8"?>

<weblogic-web-app> 
<library-ref>
    <library-name>jsf</library-name>
    <specification-version>1.2</specification-version>
    <implementation-version>1.2</implementation-version>
    <exact-match>false</exact-match>
  </library-ref>
</weblogic-web-app>

This allows the WAR to reference the JSF libraries installed above and yes, it is needed in both places ;-)

resources/META-INF/ejb-jar.xml

Update the <assembly-descriptor> to look like the following:

<assembly-descriptor>
   <interceptor-binding> 
      <ejb-name>AuthenticatorAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>BookingListAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>RegisterAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>ChangePasswordAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>HotelBookingAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>HotelSearchingAction</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
   <interceptor-binding> 
      <ejb-name>EjbSynchronizations</ejb-name>
      <interceptor-class >org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
   </interceptor-binding>
</assembly-descriptor>

The changes to this file were the real challenge with Weblogic (to be polite about it). Unlike the other application servers tested Weblogic is only using a single instance of the sessionBeanInterceptor for all session beans if <ejb-name>*</ejb-name> is used. By defining a separate interceptor for each bean we force Weblogic to create a distinct instance for each session bean.

Note: There was a deployment descriptor that should have changed this behavior, but it did not have any effect.

Dependencies and getting them packaged

There are just a couple of changes needed the build file so that the new files above are packaged, and some extra jars are included.

build.xml

  • Add the bits below:
<!-- jars to go in the war's lib -->
<fileset id="war.lib.extras" dir="${seam.dir}"> 
   <include name="lib/richfaces-api.jar" />
</fileset>

<!-- Resources to go in the ear -->
<fileset id="ear.resources" dir="${resources.dir}">
   <include name="META-INF/application.xml" />
   <include name="META-INF/weblogic-application.xml" />
   <include name="META-INF/*-service.xml" />
   <include name="META-INF/*-xmbean.xml" />
   <include name="treecache.xml" />
   <include name="*.jpdl.xml" />
   <exclude name=".gpd.*" />
   <include name="*.cfg.xml" />
   <include name="*.xsd" />
</fileset>
  • Search for ear.lib.extras fileset and add these:
<include name="examples/wiki/lib/jboss-archive-browsing.jar" />
<include name="lib/concurrent.jar" />

$SEAM_DIST/lib/interop/jboss-seam-wls-compatible.jar

The last item to deal with is to replace the jboss-seam.jar with the jboss-seam-wls-compatible.jar. There are really two options.

  • Backup the original $SEAM_DIST/lib/jboss-seam.jar and rename and replace with jboss-seam-wls-compatible.jar
  • Modify the jboss-seam-jee5.ear after the build and replace the jar there.

Deploying and viewing your application

Now all we have to do build the application and deploy it.

If you chose the first option for handling the jboss-seam-wls-compatible.jar then all we need to do is execute:

$SEAM_DIST/examples/jee5/booking/ant

Then because we created our Weblogic domain in development mode we deploy it to the autodeploy directory.

cp $SEAM_DIST/examples/jee5/booking/dist/jboss-seam-jee5.ear $DOMAIN_HOME/autodeploy

Now point your browser at http://localhost:7001/seam-jee5/

If you see classdef or classloader issues during deployment or redeployment try removing the EAR from the autodeploy directory, restarting the server, and redeploying. Weblogic sometimes has classloader issues when applications are redeployed.

Would you like to know more?

See the reference guide chapter: Seam on BEA's Weblogic with details on this example and other Seam applications on Weblogic.

back to top