7 Replies Latest reply on Sep 25, 2012 11:21 AM by zbedell

    Access EAR classpath from MBean in JBoss Module?

    zbedell

      I've defined an MBean whose classes are in a JBoss module (stored at $JBOSS_HOME/modules/ucs/jb4compat/main).  My configuration/standalone.xml lists this module as in global-modules under the ee subsystem. I have an EAR deployment (standalone/deployments/MyEar.ear) which has META-INF/jboss-service.xml that references the MBean in the module.  My EAR starts to deploy, the module class is found, and the start() method of the MBean is called.  All of the attributes listed in the mbean element in jboss-service.xml are called, and my properties are set as expected.  So far so good...

       

      The problem arises in that one of the attributes set via jboss-service.xml::server/mbean/attribute is intended to be the name of an attribute on the classpath.  Under JBoss 4.2.3 (from which I'm migrating), the MBean calls Thread.currentThread().getContextClassLoader().getResource([attributeValue]) which yields a URL to the classpath resource which would usually get something out of EAR/META-INF.  Under JBoss 7.1.1, the TCCL appears to be the JBoss Module (ucs.jb4compat) classloader rather than the EAR's classloader, so I have no access to classpath elements within the ear.

       

      Is there a way within the MBean's start() method that I can get a handle on the classloader of the EAR which contains the jboss-service.xml that spawned the MBean in the first place?  Any help would be appreciated.

       

      Best regards,

      Zac Bedell

        • 1. Re: Access EAR classpath from MBean in JBoss Module?
          sfcoy

          There is nothing in the Java EE specs that says that the root content of an EAR file should be accessible to deployed applications. The fact that it works for you in JBoss 4.x is an implementation accident and I would not expect it to work on any other vendor implementation either.

           

          You need to move your META-INF/jboss-service.xml file into a jar contained in the EAR/lib directory.

          • 2. Re: Access EAR classpath from MBean in JBoss Module?
            zbedell

            The location of the jboss-service.xml doesn't appear to make a difference.  Step-debugging through the MBean's start() method, it looks like the TCCL is set in such a way that I don't have a chance of getting at my deployment's resources.  Specifically:

             

            public void start() throws Exception {

              // ...

              final ClassLoader loader = Thread.currentThread().getContextClassLoader();

              URL loginConfig = loader.getResource(...);

              // ...

            }

             

            Inspecting loader at this point gives:

              ModuleClassLoader for Module "ucs.jb4compat:main" from local module loader @23e8f4e1 (roots: /opt/software/sag/sag_dev/modules)

            IE the TCCL is the module's ClassLoader, not that of the EAR deployment.  To the best of my knowledge, I don't have any EAR classes available at that point from which I could grab an appropriate ClassLoader.

             

            Looking up the stack a bit, I see:

            // org.jboss.as.service.AbstractService:

            protected void invokeLifecycleMethod(final Method method) throws InvocationTargetException, IllegalAccessException {

                    if (method != null) {

                        final ClassLoader old = SecurityActions.setThreadContextClassLoader(mBeanInstance.getClass().getClassLoader());

                        try {

                            method.invoke(mBeanInstance);

                        } finally {

                            SecurityActions.resetThreadContextClassLoader(old);

                        }

                    }

                }

             

            Which appears to stash the TCCL at that point and explicictly set it to the MBean's ClassLoader.  The stashed TCCL (old) at that point is "ModuleClassLoader for Module "org.jboss.as.sar:main" from local module loader @23e8f4e1 (roots: /opt/software/sag/sag_dev/modules)".

             

            I've tried repackaging my resource (login-config.xml) inside the ear as ear//lib/config.sar//META-INF/login-config.xml as well as ear//lib/config.sar//login-config.xml, but none of the ClassLoader's I have available within the MBean's start() method are anything related to my EAR or its contents.

             

            On a side note, I realize root-of EAR isn't expected to be in Classpath per EE spec, but I thought that contents of EAR/META-INF should be.  So in this case EAR/META-INF/login-config.xml would be equally accessible as EAR/lib/config.jar//META-INF/login-config.xml, assuming I had a ClassLoader with a view of the EAR.  Is that incorrect?  Granted the distinction is moot unless I can find an appropriate ClassLoader to pull from.

             

            Just by way of structure, here's what I'm working with at the moment:

             

            The EAR:

            /Work/ExactlyWatt/java/dist/server/deployments $ unzip -l ExactlyWatt.ear

            Archive:  ExactlyWatt.ear

              Length     Date   Time    Name

            --------    ----   ----    ----

                    0  09-25-12 09:33   META-INF/

                  106  09-25-12 09:33   META-INF/MANIFEST.MF

                    0  09-25-12 09:33   lib/

            11378038  09-25-12 09:33   ExactlyWatt.war

                55168  09-25-12 09:33   ExactlyWatt_ejb.jar

            ...

                  866  09-25-12 09:33   lib/config.jar (See below)

            ...

                40161  09-25-12 09:33   lib/ydoclet-runtime.jar

                  568  09-25-12 09:32   META-INF/application.xml

                 1137  09-21-12 15:12   META-INF/exactlywatt-ds.xml

                 1050  09-24-12 15:26   META-INF/jboss-service.xml

             

            config.jar within EAR/lib:

            /Work/ExactlyWatt/java/dist/server/deployments/ear $ unzip -l lib/config.jar

            Archive:  lib/config.jar

               Length     Date   Time    Name

              --------    ----   ----    ----

                     0  09-25-12 09:33   META-INF/

                   106  09-25-12 09:33   META-INF/MANIFEST.MF

                   936  06-23-11 13:22   META-INF/login-config.xml

              --------                   -------

                  1042                   3 files

             

            EAR/META-INF/jboss-service.xml:

            /Work/ExactlyWatt/java/dist/server/deployments/ear $ cat META-INF/jboss-service.xml

            <?xml version="1.0" encoding="UTF-8"?>

            <server xmlns="urn:jboss:service:7.0"

              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

              xsi:schemaLocation="urn:jboss:service:7.0 http://ucmsload.courtnet.org/dtds/jb7/jboss-service_7_0.xsd">

              <!-- Note this MBean deploys & works properly.  It's accessing files on-disk in standalone/configuration rather than trying to pull from classloader.  -->

              <mbean code="ucs.jb4compat.SystemPropertiesService" name="jboss.util:type=Service,name=SystemProperties-ExactlyWatt">

                <attribute name="URLList">configuration/exactlywatt.properties</attribute>

              </mbean>

             

              <mbean code="ucs.jb4compat.DynamicLoginConfig" name="sample-app:service=DynamicLoginConfig,domain=ExactlyWatt">

                <!-- With or without "META-INF/" here makes no difference. -->

                <attribute name="AuthConfig">META-INF/login-config.xml</attribute>

                <depends>jboss.util:type=Service,name=SystemProperties-ExactlyWatt</depends>

              </mbean>

            </server>

             

             

            /Work/ExactlyWatt/java/dist/server/deployments/ear $ cat META-INF/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://ucmsload.courtnet.org/dtds/javaee/application_6.xsd"

              version="6">

              <description>ExactlyWatt Jar Index</description>

              <display-name>ExactlyWatt</display-name>

              <module><ejb>ExactlyWatt_ejb.jar</ejb></module>

              <module>

                  <web>

                     <web-uri>ExactlyWatt.war</web-uri>

                     <context-root>/ExactlyWatt</context-root>

                   </web>

              </module>

            </application>

             

            Note this particular attempt has jboss-service.xml directly in EAR//META-INF without a SAR file to wrap it.  If I change things to put jboss-service.xml inside EAR//config.sar//META-INF and add EAR//META-INF/jboss-app.xml with a <module><service>config.sar</service></module> and application.xml with <module><java>config.sar</java></module>, it makes no difference on any of this.  I still get the module's ClassLoader for TCCL in the MBean's start() method and have no access to the EAR deployment's contents.

            • 3. Re: Access EAR classpath from MBean in JBoss Module?
              dmlloyd

              You are correct - yout SAR should be the TCCL, not the mbean instance, even if the mbean instance resides in a module or an external JAR.  This is definitely a bug.

              • 4. Re: Access EAR classpath from MBean in JBoss Module?
                sfcoy

                {quote}So in this case EAR/META-INF/login-config.xml would be equally accessible as EAR/lib/config.jar//META-INF/login-config.xml, assuming I had a ClassLoader with a view of the EAR.  Is that incorrect?{quote}

                 

                Yes, that is incorrect.

                1 of 1 people found this helpful
                • 5. Re: Access EAR classpath from MBean in JBoss Module?
                  zbedell

                  I have a minimal test project that reproduces this in two classes & a few XML's.  About 3KB total tarballed w/ an Ant script to build it & configured a JBoss instance.  Shall I file a JIRA ticket?

                  • 6. Re: Access EAR classpath from MBean in JBoss Module?
                    dmlloyd

                    Please do - though since you found the actual code that causes the problem, the reproducer will be a formality only

                    • 7. Re: Access EAR classpath from MBean in JBoss Module?
                      zbedell