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

Max Rydahl Andersen max.andersen at redhat.com
Thu Apr 30 06:31:22 EDT 2009


In case you are not on the jboss as dev list here is an explanation AND 
workaround for the weird classloader and seam errors
we have had when we package with *standard* manifest.mf.

Basically JBoss will create multiple temp .jar's for one unique jar in 
an deployment if they are not deployed in sequence.
Resulting in the applications seeing multiple URL's even though there 
only are one.

/max

-------- Original Message --------
From: 	Jaikiran Pai <jpai at redhat.com>
Subject: 	Re: [jboss-dev] Classloader changes from AS 4.2.2 to AS 4.2.3 
affecting launch of Tool built Seam apps
To: 	Max Rydahl Andersen <max.andersen at redhat.com>
CC: 	JBoss.org development list <jboss-development at lists.jboss.org>



Max Rydahl Andersen wrote:
>>  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.
>
>  We list these in manifest.mf since that is the only way Eclipse can
>  know what is on the classpath; application.xml afaik does not
>  attribute to the classpath - at least I never seen an IDE does that
>  (they might be wrong ;)
>  In any case, listing it in manifest.mf and in application.xml should
>  not hurt anything since they should just resolve to the *same* jar.
I agree, adding it to the MANIFEST.MF should not be breaking the 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).
>  This is *the* bug I believe ? This will keep causing problems...
Someone who knows better about JBoss-4.x deployers would probably know
how to fix this.
>
>  Any suggestion for a workaround that still allow me to use *standard*
>  manifest.mf classpath entries ?
Luckily yes :) I looked at what the MainDeployer[1] does. The important
piece of code is :

private void parseManifestLibraries(DeploymentInfo sdi)
{
...//blah blah blah
if (classPath != null)
      {
         StringTokenizer st = new StringTokenizer(classPath);
         log.debug("resolveLibraries: "+classPath);

         while (st.hasMoreTokens())
         {
...//blah blah blah

        // Only deploy this if it is not already being deployed
               if ( deploymentMap.containsKey(lib) == false )
               {
                  /* Test that the only deployer for this is the
JARDeployer.
                   Any other type of deployment cannot be initiated through
                   a manifest reference.
                  */
                  DeploymentInfo mfRef = new DeploymentInfo(lib, null,
getServer());
                  makeLocalCopy(mfRef);
                  URL[] localURL = {mfRef.localUrl};
                  mfRef.localCl = new java.net.URLClassLoader(localURL);
                  findDeployer(mfRef);
                  SubDeployer deployer = mfRef.deployer;
                  if(deployer != null&&  (deployer instanceof
JARDeployer) == false)
                  {
                     // Its a non-jar deployment that must be deployed
seperately
                     log.warn("Found non-jar deployer for " + tk + ": "
+ deployer);
                  }

                  // add the library
                  sdi.addLibraryJar(lib);
               }
            }

So, if the classpath entry contains a reference to a jar which is
*already being deployed*, then it will *not* create a (duplicate) temp
copy while parsing the manifest entry. The (single) temp copy will be
created when the deployment jar (marked as module in application.xml) is
being processed for deployment.

So the *workaround* is to ensure that deployments which are referenced
in Classpath attribute of other deployments are deployed first. For ex:
in the application attached to the JIRA, the xxx-ejb.jar refers to
jboss-seam.jar (EJB deployment) in the MANIFEST.MF. So the trick is to
ensure that jboss-seam is picked up for deployment before xxx-ejb.jar is
picked for deployment (and the subsequent MANIFEST.MF processing). This
can be done by specifying the correct order of modules in the
application.xml and *also* specifying the module-order as "strict" in
jboss-app.xml (by default the module-order is "implicit" which follows
filename based deployment ordering [2]). So here's what i did:

application.xml:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd"
    version="5">

    <display-name>xxx-ear</display-name>

    <!-- JBIDE-4166 Workaround - Make sure we deploy this first, since
this is referenced in xxx-ejb.jar-->
     <module>
        <ejb>jboss-seam.jar</ejb>
    </module>

    <module>
        <ejb>xxx-ejb.jar</ejb>
    </module>
    <module>
        <web>
            <web-uri>xxx.war</web-uri>
            <context-root>/xxx</context-root>
        </web>
    </module>
</application>

jboss-app.xml:

<?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>
   <!-- JBIDE-4166 : We need strict ordering to follow the order mentioned
    in application.xml -->
   <module-order>strict</module-order>

   <loader-repository>
      seam.jboss.org:loader=xxx-ear.ear
   </loader-repository>
</jboss-app>

So all that JBoss Tools needs to do is add a intelligent ordering of the
modules in the application.xml and mark the application for strict
module ordering in the jboss-app.xml.

[1]
http://anonsvn.jboss.org/repos/jbossas/tags/JBoss_4_2_3_GA/system/src/main/org/jboss/deployment/MainDeployer.java
[2] This also explains why the deployment behaves differently when the
name of the deployment is changed.
>
>>  --------------------
>>  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.
>  Why the difference in behavior ? Legacy ? Intentional ?
Not sure. Someone who has more experience on the 4.x deployers might know.
>>>  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?
>  The problem is that it only shows up sometimes - I have seen it
>  several times with capital letters (another bug) and even went so far
>  to add a warning in the ui that using capital letters as the first
>  character were not recommended.
>  I'll try and see if I can find a way to reproduce the situation with
>  different lett
When i read the JIRA, i thought the user was noting that changing the
name of the EAR fixed the issue. That's why i commented that naming of
the files should not matter (atleast for this specific issue). However
after what i explained above, related to implicit ordering of
deployments *within* an EAR, i think the user was talking about renaming
the deployments *within* the EAR. That makes sense now and it definitely
affects (= is expected) the deployment ordering.

-Jaikiran




More information about the seam-dev mailing list