This time I would like to guide you through migration of Seam Booking example which is Enterprise application - EAR.

 

Seam EAR migration is a little complicated in comparing to Seam JPA example. But what we have learnt from JPA example migration, we can use also in this EAR migration.

 

Basic overview of migration steps:

  1. Initialization of JSF 1.2 instead of default JSF 2,

  2. Bundling older hibernate jars than what are provided in JBoss AS7 by default,

  3. Changes in JNDI bindings  due new Java EE 6 JNDI portable syntax. (Note: there is a little mistake in that tutorial - see JAVAEETUTORIAL-44

 

First 2 steps we've done already in JPA example migration, but third step is new one because of using EJBs in EAR.

 

So let's start:

 

  1. Add new file jboss-deployment-structure.xml with the following content into jboss-seam-booking.ear/META-INF/:

    <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
      <deployment>
            <dependencies>
              <module name="org.apache.log4j" export="true"/>
              <module name="org.dom4j" export="true"/>
              <module name="org.apache.commons.logging" export="true"/>
              <module name="org.apache.commons.collections" export="true"/>
              <module name="javax.faces.api" slot="1.2" export="true"/>
              <module name="com.sun.jsf-impl" slot="1.2" export="true"/>
            </dependencies>
      </deployment>
      <sub-deployment name="booking-web.war"> 
          <exclusions>
              <module name="javax.faces.api" slot="main"/>
              <module name="com.sun.jsf-impl" slot="main"/>
            </exclusions>
            <dependencies>
              <module name="javax.faces.api" slot="1.2"/>
              <module name="com.sun.jsf-impl" slot="1.2"/>
            </dependencies>
      </sub-deployment> 
     </jboss-deployment-structure>
    

     

  2. Next remove/comment hibernate property for cache provider class in jboss-seam-booking.jar/META-INF/persistence.xml:

    <!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/> -->
    

     

  3. Add the following dependencies from seam distribution (seam/lib directory) into jboss-seam-booking.ear/lib directory, which are in JBoss AS 5/6 in different versions:

    slf4j-api.jar 
    slf4j-log4j12.jar 
    hibernate-core.jar 
    hibernate-entitymanager.jar 
    hibernate-validator.jar 
    hibernate-annotations.jar 
    hibernate-commons-annotations.jar

     

  4. Next we need to change JNDI lookup strings in jboss-seam-booking.war/WEB--INF/components.xml. Because of new JNDI portable rules, AS7 now binds EJBs with JNDI portable rules like for instance:

java:global/seam-booking/booking-ejb/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching
java:app/booking-ejb/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching
java:module/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching
java:global/seam-booking/booking-ejb/HotelSearchingAction
java:app/booking-ejb/HotelSearchingAction
java:module/HotelSearchingAction

and for Seam framework EJBs like for instance:

java:global/seam-booking/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations
java:app/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations
java:module/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations
java:global/seam-booking/jboss-seam/EjbSynchronizations
java:app/jboss-seam/EjbSynchronizations
java:module/EjbSynchronizations

Notice difference between java:app/jboss-seam/EjbSynchronizations and java:app/booking-ejb/HotelSearchingAction.

We can't use the single jndiPattern like we did before in JBoss AS 5/6. So there are a few solutions to do it, I chose adding jndi-name for every EJB into WEB-INF/components.xml:

<component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
<component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
<component class="org.jboss.seam.example.booking.AuthenticatorAction" jndi-name="java:app/booking-ejb/AuthenticatorAction" />
<component class="org.jboss.seam.example.booking.BookingListAction"  jndi-name="java:app/booking-ejb/BookingListAction" />
<component class="org.jboss.seam.example.booking.RegisterAction" jndi-name="java:app/booking-ejb/RegisterAction" />
<component class="org.jboss.seam.example.booking.HotelSearchingAction" jndi-name="java:app/booking-ejb/HotelSearchingAction" />
<component class="org.jboss.seam.example.booking.HotelBookingAction" jndi-name="java:app/booking-ejb/HotelBookingAction" />
<component class="org.jboss.seam.example.booking.ChangePasswordAction" jndi-name="java:app/booking-ejb/ChangePasswordAction" />

You can alternatively add @JNDIName(value="") annotation with JNDI path. Example of changed SLSB is below, look at @JndiName annotation, detailed description is at Seam2 reference documentation:

@Stateless
@Name("authenticator")
@JndiName(value="java:app/booking-ejb/AuthenticatorAction")
public class AuthenticatorAction 
    implements Authenticator
{
...
}

 

That is all in Booking example modifications.

 

Unfortunatelly the example how is done will deploy with error in JSF initialization.

 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/seam-booking]] (MSC service thread 1-1) Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener: com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! org.jboss.seam.jsf.SeamApplicationFactory
        at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:215) [jsf-impl-1.2_13.jar:1.2_13-b01-FCS]
        at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:196) [jsf-impl-1.2_13.jar:1.2_13-b01-FCS]
        at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3368) [jbossweb-7.0.0.CR4.jar:7.0.0.Final]
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3821) [jbossweb-7.0.0.CR4.jar:7.0.0.Final]
        at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:70) [jboss-as-web-7.0.0.Final.jar:7.0.0.Final]
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1765)
        at org.jboss.msc.service.ServiceControllerImpl$ClearTCCLTask.run(ServiceControllerImpl.java:2291)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_26]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_26]
        at java.lang.Thread.run(Thread.java:662) [:1.6.0_26]
Caused by: java.lang.InstantiationException: org.jboss.seam.jsf.SeamApplicationFactory
        at java.lang.Class.newInstance0(Class.java:340) [:1.6.0_26]
        at java.lang.Class.newInstance(Class.java:308) [:1.6.0_26]
        at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:537) [jsf-api-1.2_13.jar:1.2_13-b01-FCS]
        at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:405) [jsf-api-1.2_13.jar:1.2_13-b01-FCS]
        at javax.faces.FactoryFinder.access$400(FactoryFinder.java:135) [jsf-api-1.2_13.jar:1.2_13-b01-FCS]
        at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:717) [jsf-api-1.2_13.jar:1.2_13-b01-FCS]
        at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239) [jsf-api-1.2_13.jar:1.2_13-b01-FCS]
        at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:186) [jsf-impl-1.2_13.jar:1.2_13-b01-FCS]
        at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:131) [jsf-impl-1.2_13.jar:1.2_13-b01-FCS]
        at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:205) [jsf-impl-1.2_13.jar:1.2_13-b01-FCS]

 

This is a bug in AS 7 Final. But I don't write this blog if there is not a way how to work around it ;-).

I discussed the issue with AS 7 developers and they fixed it in upstream sources.

So we need to download AS7 snapshot or build AS 7 from git sources. The easier is to get working binaries at latest JBoss AS7 snapshot

 

And that is realy all!