2 Replies Latest reply on Feb 27, 2017 2:07 PM by ksiczek

    Problem with accessing Spring NamespaceHandler inside EAR file due to class loading issue.

    ksiczek

      Hi,

       

      it is my first post here so please be lenient if possible

       

      We migrate from EAP 6.1 to EAP 6.4 and have a strange issue regarding Spring startup. Our EAR structure is as follows

      dev_production.ear
      ├── atg_admin.war
      ├── atg_bootstrap_ejb.jar
      ├── atg_bootstrap.war
      ├── atglib
      ├── atg-rest-web-1.0.war
      ├── generic.war
      ├── Integration.war
      ├── META-INF
      ├── PhoenixStore.war
      ├── siebel.war
      ├── Static.war
      └── VideoIdent-rs.war
      

       

      where Integration.war has defined Spring context (and some CXF stuff) but all jar artifacts are placed in atglib and atg_bootstrap_ejb.jar refers to them at MANIFEST.MF Class-Path entry. The problem we have is that during start we get

      09:19:26,378 ERROR  [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 117) Context initialization failed: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]
      Offending resource: class path resource [META-INF/app-context.xml]
      

       

      We checked and it seems that during context start there is no META-INF/spring.handlers available to classloader but handler org.springframework.context.config.ContextNamespaceHandler is accessible so we can access it using

      getResourceLoader().getClassLoader().getResources("org/springframework/context/config/ContextNamespaceHandler.class")
      

       

      I did several configurations in jboss-deployment-structure.xml but nothing works for me:

       

      <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" >
      <deployment>
      <dependencies>
      <system export="true">
      <paths>
      <path name="sun/net/util"/>
      <path name="sun/net/www"/>
      <path name="com/sun/crypto/provider"/>
      <path name="sun/awt"/>
      <path name="sun/rmi/server"/>
      </paths>
      </system>
      </dependencies>
      </deployment>
      <sub-deployment name="atg_bootstrap_ejb.jar">
          <exports>
              <include path="META-INF/*"/>
              <include path="META-INF/cxf/*"/>
          </exports>
      </sub-deployment>
      <sub-deployment name="Integration.war">
          <!-- <resources>
              <resource-root path="../atglib/_Integration.Integration_slib_sspring-context-4.1.1.RELEASE.jar">
                  <filter>
                      <include path="META-INF/*"/>
                      <include path="META-INF/cxf/*"/>
                  </filter>
              </resource-root>
          </resources> -->
          <dependencies>
              <module name="deployment.dev_production.ear.atg_bootstrap_ejb.jar" slot="main" meta-inf="import">
                  <!-- <exports>
                      <include path="META-INF/*"/>
                  </exports> -->
              </module>
          </dependencies>
      </sub-deployment>
      </jboss-deployment-structure>
      

       

      and the only solution by now was to put spring-context to Integration.war/WEB-INF/lib. We did not have that problems using jBoss EAP 6.1.

       

      It might be an unusual setup in terms of using Spring in JEE application but it is something I inherited and I do not want to change too much (e.g. Spring version or ear dependency to moduled one) without a good reason and I do not want to let jBoss beat me so do you have any idea how to configure it properly? Also I'm wondering what exactly has changed that jBoss has problems with such configuration.

       

      P.S. I attached server logs and configuration XML.

        • 1. Re: Problem with accessing Spring NamespaceHandler inside EAR file due to class loading issue.
          andey

          Hi,

           

          Verify that you have defined Spring as a module as per below:

           

          The following are steps to create a Spring module:

          1.Download the desired version of Spring. For this example Spring 3.x/4.x, here I'm using spring 3.x

          2.Create the directory: $JBOSS_HOME/modules/org/springframework/spring/main.

          3.Copy the Spring libraries you downloaded to that directory.

          4.Create module.xml with the following contents under that directory. Make sure these correspond to the libraries' names:

           

          ~~~

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

          <module xmlns="urn:jboss:module:1.1" name="org.springframework.spring">

            <resources>

              <resource-root path="org.springframework.aop-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.asm-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.aspects-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.beans-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.context-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.context.support-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.core-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.expression-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.instrument-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.instrument.tomcat-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.jdbc-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.jms-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.orm-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.oxm-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.test-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.transaction-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.web-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.web.portlet-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.web.servlet-3.1.1.RELEASE.jar"/>

              <resource-root path="org.springframework.web.struts-3.1.1.RELEASE.jar"/>

            </resources>

            <dependencies>

              <module name="org.apache.commons.logging"/>

              <module name="javax.api" export="true"/>

              <module name="org.jboss.vfs"/>

            </dependencies>

          </module>

          ~~~

           

          Here is an absolute minimal module.xml (the different Spring version is irrelevant):

          ~~~

          <?xml version="1.0"?>

          <module xmlns="urn:jboss:module:1.1" name="org.springframework.spring">

            <resources>

              <resource-root path="spring-aop-3.2.3.RELEASE.jar"/>

              <resource-root path="spring-beans-3.2.3.RELEASE.jar"/>

              <resource-root path="spring-context-3.2.3.RELEASE.jar"/>

              <resource-root path="spring-core-3.2.3.RELEASE.jar"/>

              <resource-root path="spring-expression-3.2.3.RELEASE.jar"/>

            </resources>

            <dependencies>

              <module name="javax.api"/>

              <module name="org.apache.commons.logging"/>

            </dependencies>

          </module>

          ~~~

           

          5.Put the following jboss-deployment-structure.xml in your application archive (WEB-INF/jboss-deployment-structure.xml for WAR or META-INF/jboss-deployment-structure.xml for EAR or EJB-jar) to use the above module:

           

          If you're using JBoss EAP 6.1.x and greater, then use below:

           

          ~~~

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

          <jboss-deployment-structure>

            <deployment>

              <dependencies>

                <module name="org.springframework.spring" export="true" meta-inf="export"/>

              </dependencies>

            </deployment>

          </jboss-deployment-structure>

          ~~~

           

          If JBoss EAP 6.0.x, then use below

           

          ~~~

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

          <jboss-deployment-structure>  

            <deployment>

              <dependencies>

                <module name="org.springframework.spring" export="true">

                  <imports>

                    <include path="META-INF**"/>

                    <include path="org**"/>

                  </imports>

                  <exports>

                    <include path="META-INF**"/>

                    <include path="org**"/>

                  </exports>

                </module>

              </dependencies>

            </deployment>

          </jboss-deployment-structure>

          ~~~

           

          Note: The meta-inf on the module in the jboss-deployment-structure.xml was added in JBoss EAP 6.1.0, which allows the files in the META-INF of a resource to be visible. Since this was not available in JBoss EAP 6.0.x, the section allows you to get access to the META-INF directory which is not visible by default.

           

          Note: The Spring Framework module should not include resources such as servlet-api.jar, xml-apis.jar, jta-api.jar, and other APIs. These APIs are implemented by either the JDK or JBoss and trying to use a different version of the API will lead to classloading issues and other problems.

           

          Note: The Spring module should include all of its non Java / JavaEE dependencies. The Spring module can depend on javax.api / javaee.api provided by JBoss and any public JBoss module, but for other dependencies Spring has such as aopalliance, they would need to be included as resources in the module or in another custom module.

          • 2. Re: Problem with accessing Spring NamespaceHandler inside EAR file due to class loading issue.
            ksiczek

            andey thanks for your help. I consider moving to modular dependencies but accoring to that post only Spring 2.5 and 3.x are supported on JBoss EAP 6 as a module. Currently we use 4.1.1 so we would need a downgrade and this is another risk. Moreover I do not get why the same ear works on on EAP 6.1 but does not work on EAP 6.4 without any additional configration and how I can access a META-INF resource that is located in EJB module from WAR classloader?