[jboss-dev] Classloader changes from AS 4.2.2 to AS 4.2.3 affecting launch of Tool built Seam apps

Jaikiran Pai jpai at redhat.com
Tue Apr 28 08:24:36 EDT 2009


This issue (the WARN message that SeamPhaseListener spits out and 
ultimately the application isn't accessible), has come up frequently in 
user forums but has ended up without any clean solutions. I just tried 
out the application attached to the JBIDE-4166 JIRA and here's what 
causes this issue:

Exploded deployment:
--------------------
4.2.2 - The deployment framework:
--------------------

1) During deploy, it picks up the EAR/xxx-ejb.jar. Looks at its 
Manifest.mf and finds jboss-seam listed. So creates a tmp out of this 
and puts it in the tmp folder and adds it to classpath of the app. Let's 
call this temped file as tmpAjboss-seam.jar.
2) Later on during deploy, it picks up EAR/jboss-seam.jar (since its 
listed as a module in application.xml) and creates a temp jar out of 
this and adds to classpath of the app. Let's call this temped file as 
tmpBjboss-seam.jar.
3) Ultimately, we now have 2 (duplicated) temp versions of the same 
jboss-seam jar file.
4) Later on during the servlet context initialization of the seam 
application, the com.sun.faces.config.ConfigListener.contextInitialized 
(from jsf-impl.jar available in the AS) gets all 
META-INF/faces-config.xml resources in the application's classpath. This 
URL list now contains tmpAjboss-seam.jar and tmpBjboss-seam.jar (the 
duplicated temp versions of jboss-seam.jar).  
5) Then the xmls corresponding to these URLs are parsed corresponding 
LifecycleBean(s) are created out of these.
6) The phase listeners (ex: SeamPhaseListener) are then added to a list 
maintained in com.sun.faces.config.beans.LifecycleBean. However, before 
adding the LifecycleBean does a check for phase listeners already 
registered with the given name. If present, then it *ignores* the next 
phase listener with the same name:

public void addPhaseListener(String phaseListener) {
    if (!(this.phaseListeners.contains(phaseListener))) {
     ...// some logic
      this.phaseListeners.add(phaseListener);
    }
  }

Ultimately, each of these phaseListeners are instantiated and invoked. 
Because of this logic involved in the LifecycleBean, the 
SeamPhaseListener is registered only once, even though 2 (duplicate 
temp) jars with faces-config.xml contained this listener.

In 4.2.3 - The jsf-impl.jar version is different and the classes have 
been refactored. But the logic involved is the same till step#4 above. 
In the later steps, the call goes to 
com.sun.faces.config.processor.LifecycleProcessor. Here there is no 
check for existing phaseListeners with the same name. As a result, the 
SeamPhaseListener is instantiated twice which leads to it complaining:

15:40:49,386 WARN  [SeamPhaseListener] There should only be one Seam 
phase listener per application

Ultimately this leads to an exception while accessing the application 
(which i believe is related to the incorrect phase listener coming into 
picture).

So it's the jsf-impl which has changed that leads to this error. 
However, the real questions are:

1) Should (EJB) *deployments* be listed in the MANIFEST.MF files of 
other deployments. In this example the jboss-seam.jar which is a EJB 
deployment (marked as a "module" in application.xml) is listed in 
MANIFEST.MF of an xxx-ejb.jar deployment.
2) Is the duplicate temp files for the same jar file (jboss-seam.jar) 
intentional? It's created once during the MANIFEST.MF parsing of 
xxx-ejb.jar deployment and once during deploying jboss-seam.jar 
deployment (which is listed as a module in application.xml).

--------------------
Archived deployment :
--------------------
When the application is deployed as an archive, the deployment framework 
creates a exploded temp of the EAR in the tmp folder. It however does 
*not* create temps for the sub-deployments or the libraries within the 
ear. So there is only one jboss-seam.jar in 
tmp/sometmpName.ear-contents. Because of this the logic explained above, 
registers the SeamPhaseListener only once and hence no issues.

Max Rydahl Andersen wrote:
> Anyone got an idea why exploded deployment 
> <https://jira.jboss.org/jira/browse/JBIDE-4166> differs from a zipped 
> deployment ?
Because of the logic involved in the deployment framework (see above)
> Why does it matter which letters we use in the deployment, i.e. 
> fseam.ear behaves different that seam.ear ?
Though the JIRA mentions this, i don't see a reason why the name should 
matter. I did not see any other explanation in the JIRA as to how this 
fixed the issue.  Is there some app which shows this behaviour?

> Why does it work if all jars are in a /lib folder (JEE 5 style), but 
> not when using Manifest.mf (J2EE 1.4 style) ?
Because of the duplicate temp jars that are created during deployment 
process, when Manifest.mf is involved (see above explanation).


regards,
-Jaikiran



More information about the jboss-development mailing list