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:
# Initialization of JSF 1.2 instead of default JSF 2,
# Bundling older hibernate jars than what are provided in JBoss AS7 by default,
# Changes in JNDI bindings due new [Java EE 6 JNDI portable syntax|http://download.oracle.com/javaee/6/tutorial/doc/gipjf.html#girgn]. (Note: there is a little mistake in that tutorial - see [JAVAEETUTORIAL-44|http://java.net/jira/browse/JAVAEETUTORIAL-44]
First 2 steps we've done already in [JPA example migration|http://community.jboss.org/blogs/marek-novotny/2011/07/15/seam-2-jpa-example-on-jboss-as7], but third step is new one because of using EJBs in EAR.
So let's start:
# Add new file jboss-deployment-structure.xml with the following content into _jboss-seam-booking.ear/META-INF/_:{code:xml}
<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>
{code}
# Next remove/comment hibernate property for cache provider class in jboss-seam-booking.jar/META-INF/persistence.xml:{code:xml}
<!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/> -->
{code}
# 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:{noformat}slf4j-api.jar
slf4j-log4j12.jar
hibernate-core.jar
hibernate-entitymanager.jar
hibernate-validator.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar{noformat}
# 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:
{noformat}
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
{noformat} and for Seam framework EJBs like for instance:
{noformat}
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
{noformat}
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:
{code: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" />
{code}
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:
{code:java}
@Stateless
@Name("authenticator")
@JndiName(value="java:app/booking-ejb/AuthenticatorAction")
public class AuthenticatorAction
implements Authenticator
{
...
}
{code}
That is all in Booking example modifications.
Unfortunatelly the example how is done will deploy with error in JSF initialization.
{noformat}
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]
{noformat}
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|http://hudson.jboss.org/jenkins/view/JBoss AS/job/JBoss-AS-7.0.x/lastSuccessfulBuild/artifact/build/target/jboss-7.0.x.zip]
And that is realy all!