Recently I started a proof of concept for a new project that will run on JBoss 5.1. The reason for picking JBoss 5.1 instead of the mature 4.2 series was due to its full support for JavaEE 1.5 (4.2 supports only EJB3 spec, no servlet injection, etc) as well as its longer support (4.2 will start an EOL cycle soon).
As soon as I decided to use JBoss 5.x the classloading nightmare started. First of all, Seam uses a kinda strange hack for detecting its components (its scanner class makes use of java.io.File which in turn does not work on newer VFS system released on JBoss 5.x).
Recommendation on Seam forums is to include no Seam file at you EAR/WAR and let Seam deployer do the trick but thiss comes with much obvious limitations:
- You’ll need a separate packaging for your application on JBoss (this is probably the worst limitation)
- Seam (and its dependencies) upgrades will involve patching Application Server files
But although recommended you can still deploy a regular Seam application without Seam Deployer. I’ll try to provide a step-by-step guide on how to circumvent this limitation:
First step: remove seam.deployer from $JBOSS_HOME/server/default/deployers (an alternative and less intrusive solution that I just found after writting this post is described over here)
Second step: add all Seam dependencies (jboss-seam-ui.jar, jboss-seam.jar, etc) inside EAR (I sincerely suggest under a lib folder).
Third step: place a jboss-app.xml with the following content on you EAR/META-INF folder
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-app
PUBLIC "-//JBoss//DTD J2EE Application 4.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd">
<jboss-app>
<loader-repository>
myapp.ear=MyAppEar
</loader-repository>
</jboss-app>
Fourth step: place a jboss-classloading.xml also on EAR/META-INF folder with the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<classloading xmlns="urn:jboss:classloading:1.0"
name="myapp.ear"
domain="MyAppEar">
</classloading>
Fifth step: place jboss-seam-int-jbossas.jar from seam.deployer/lib-int into your EAR/lib folder. (this jar contains org.jboss.seam.integration.jbossas.vfs.VFSScanner)
Sixth step: place another jboss-classloading.xml on WAR/WEB-INF folder with the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<classloading xmlns="urn:jboss:classloading:1.0"
name="mywebapp.war"
domain="MyWebAppWar">
</classloading>
Seventh step: Place a jboss-web.xml under WAR/WEB-INF with the following contents:
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
mywebapp.war:loader=MyWebApp
<loader-repository-config>java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
Eighth step: place a seam-deployment.properties anywhere in the classpath (anywhere but before seam jar) with the following contents:
org.jboss.seam.deployment.scanners=org.jboss.seam.integration.jbossas.vfs.VFSScanner
Ninth step: Add all Seam dependencies on MANIFEST.MF file under WAR/META-INF and remember to include jboss-seam-int-jbossas.jar on the classpath.
That’s all you need to avoid having a separate packaging for a Seam enterprise application running on JBoss 5.x (sincerely I guess that you risk having to remove the seam-deployment.properties only). This also makes it easier to replace the JSF implementation on your application.