[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