2

I want to deploy multiple grails applications on Jboss. Because they all use same grails version (2.1.1) I want to exclude common jars from war file and provide them via Jboss module. For starters, I'm trying with one application, but can't get it to work.

What I tried

  1. Set defaultDependenciesProvided true in BuildConfig.groovy (before inherits("global"))
  2. Created module folders: modules/commons/grails/main and put all the common jars in
  3. Created module.xml
  4. Added Dependencies: commons.grails to MANIFEST.MF file inside war
  5. Tried to deploy the app

What happend

10:16:12,800 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) JBAS015876: Starting deployment of "sofmk13-web-0.1.war"

10:16:23,095 WARN  [org.jboss.modules] (MSC service thread 1-4) Failed to define class org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag in Module "commons.grails:main" from local module loader @4ec57293 (roots: C:\development\tools\jboss-as-7.1.2.Final\modules,C:\development\repository\jboss): java.lang.LinkageError: Failed to link org/codehaus/groovy/grails/web/taglib/jsp/JspInvokeGrailsTagLibTag (Module "commons.grails:main" from local module loader @4ec57293 (roots: C:\development\tools\jboss-as-7.1.2.Final\modules,C:\development\repository\jboss))
    at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:396)
    at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:243)
    at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:73)
    at org.jboss.modules.Module.loadModuleClass(Module.java:527)
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:182)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
    at java.lang.ClassLoader.defineClass1(Native Method) [rt.jar:1.7.0_17]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791) [rt.jar:1.7.0_17]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) [rt.jar:1.7.0_17]
    at org.jboss.modules.ModuleClassLoader.doDefineOrLoadClass(ModuleClassLoader.java:327)
    at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:391)
    at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:243)
    at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:73)
    at org.jboss.modules.Module.loadModuleClass(Module.java:527)
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:182)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
    at java.lang.Class.forName0(Native Method) [rt.jar:1.7.0_17]
    at java.lang.Class.forName(Class.java:266) [rt.jar:1.7.0_17]
    at org.jboss.as.server.deployment.reflect.DeploymentClassIndex.classIndex(DeploymentClassIndex.java:54)
    at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:81) [jboss-as-ee-7.1.2.Final.jar:7.1.2.Final]
    at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:116)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_17]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_17]
    at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_17]
Caused by: java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/DynamicAttributes
    at java.lang.ClassLoader.defineClass1(Native Method) [rt.jar:1.7.0_17]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791) [rt.jar:1.7.0_17]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) [rt.jar:1.7.0_17]
    at org.jboss.modules.ModuleClassLoader.doDefineOrLoadClass(ModuleClassLoader.java:327)
    at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:391)
    ... 31 more
Caused by: java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.DynamicAttributes from [Module "commons.grails:main" from local module loader @4ec57293 (roots: C:\development\tools\jboss-as-7.1.2.Final\modules,C:\development\repository\jboss)]
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
    ... 36 more

There is a lot of similar warnings for different classes.

Can somebody point me to what to try next? I can't decipher what exactly is wrong from the error message.

Thanks!

4

2 回答 2

2

After some trial and error I finally managed to exclude some of the jars and provide them as modules. The hardest part was to get all the jar dependencies right. A brief overview follows. We start with description of how to prepare war archive to use the modules. Then we describe how modules are added to jboss.

Prepare WAR archive (assuming the modules are already provided)

  1. create jboss-deployment-structure.xml file inside /web-app/WEB-INF folder. Here we specify which modules application uses and set appropriate versions (with slot parameter). Note that these modules provide all the jars we'll excluded from the war in the next step.

    <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
        <deployment>
            <dependencies>
                <module name="commons.restGrailsJars" slot="2.1.1"/>
                <module name="org.springframework" slot="3.1.2.RELEASE"/>
            </dependencies>
       </deployment>
    </jboss-deployment-structure>
    
  2. add code to exclude shared jars from war file. We use grails.war.resources configuration option inside BuildConfig.groovy. It lets us do some extra processing before war is created, so we can delete shared jars from the archive (they are listed in the list). Append following lines to the file:

    grails.war.resources = { resourceDir ->
    
    File libDir = new File(resourceDir, 'WEB-INF/lib')
    
    ['aopalliance',
    'asm',
    'aspectjrt',
    'aspectjweaver',
    'cglib',
    'commons-beanutils',
    'commons-codec',
    'commons-collections',
    'commons-dbcp',
    'commons-el',
    'commons-fileupload',
    'commons-io',
    'oro',
    'sitemesh',
    'slf4j',
    'spring-aop',
    'spring-asm',
    'spring-beans',
    'spring-core',
    'spring-expression',
    'xpp3_min',
    'h2',
    'servlet-api']
            .each { jarNameStart ->
                        libDir.eachFile { file ->
                            if (file.name.startsWith(jarNameStart)) {
                                file.delete()
                                 println "deleted jar $file"
                            }
                        }
             }
    
     } 
    

Adding Jboss modules

Adding modules is pretty easy if we know what dependencies are needed by each jar library. Here is an example of adding modules for Spring version 3.2.3.RELEASE.

  1. Spring framework jars reside inside modules/org/springframework folder.
  2. Create new folder named 3.2.3.RELEASE and copy all the jars that can be shared*.
  3. Put module.xml beside the jars. It looks something like this: (notice changed slot value which corresponds to release version and folder name)

    <module xmlns="urn:jboss:module:1.1" name="org.springframework" slot="3.2.3.RELEASE">
      <resources>
          <resource-root path="spring-asm-3.2.3.RELEASE.jar"/>
          <resource-root path="spring-core-3.2.3.RELEASE.jar"/>
          <resource-root path="spring-aop-3.2.3.RELEASE.jar"/>
          <resource-root path="spring-beans-3.2.3.RELEASE.jar"/>
          <resource-root path="spring-expression-3.2.3.RELEASE.jar"/>        
      </resources>
    
       <dependencies>
        <module name="aopalliance.aopalliance" export="true"/>
        <module name="cglib.cglib" export="true"/>
        <module name="org.aspectj.aspectjweaver" export="true"/>
        <module name="org.apache.commons.logging" export="true"/>
        <module name="org.apache.commons.pool" export="true"/>
        <module name="javax.servlet.api"/>
        <module name="javax.faces.api" slot="1.2" />
        <module name="com.sun.jsf-impl" slot="1.2" />
        <module name="org.jboss.vfs"/>
        <module name="javax.persistence.api"/>
        <module name="javax.xml.bind.api"/>
        <module name="javax.api"/>
        <module name="javax.jms.api"/>
        <module name="javax.annotation.api"/>
        </dependencies>
    </module>
    

If some modules are missing, application won't deploy (or it will, but strange things, like email validation failures will happen).

You have to do similar thing for all the libraries you want to exclude from war archive. I managed to exclude all the jars listed in 'Prepare WAR archive' section (2.).

于 2013-06-06T19:16:37.400 回答
1

There are several root resources you are including that are already modules so you should add a dependency rather than including the JAR. You also should probably avoid adding jcl-over-slf4j-1.6.2.jar. There is already an slf4j bridge provided.

The error seems to indicate you need a dependency on javax.servlet.jsp.api.

I didn't go over it in great detail, but I'm thinking your module.xml should look more like the following.

<module xmlns="urn:jboss:module:1.1" name="commons.grails">
    <resources>
        <resource-root path="aopalliance-1.0.jar"/>
        <resource-root path="asm-3.1.jar"/>
        <resource-root path="aspectjrt-1.6.10.jar"/>
        <resource-root path="aspectjweaver-1.6.10.jar"/>
        <resource-root path="cglib-2.2.jar"/>
        <resource-root path="commons-codec-1.5.jar"/>
        <resource-root path="commons-dbcp-1.4.jar"/>
        <resource-root path="commons-el-1.0.jar"/>
        <resource-root path="commons-fileupload-1.2.2.jar"/>
        <resource-root path="commons-validator-1.3.1.jar"/>
        <resource-root path="concurrentlinkedhashmap-lru-1.2_jdk5.jar"/>
        <resource-root path="ehcache-core-2.4.6.jar"/>
        <resource-root path="grails-bootstrap-2.1.1.jar"/>
        <resource-root path="grails-core-2.1.1.jar"/>
        <resource-root path="grails-crud-2.1.1.jar"/>
        <resource-root path="grails-datastore-core-1.1.0.RELEASE.jar"/>
        <resource-root path="grails-datastore-gorm-1.1.0.RELEASE.jar"/>
        <resource-root path="grails-datastore-simple-1.1.0.RELEASE.jar"/>
        <resource-root path="grails-hibernate-2.1.1.jar"/>
        <resource-root path="grails-logging-2.1.1.jar"/>
        <resource-root path="grails-plugin-codecs-2.1.1.jar"/>
        <resource-root path="grails-plugin-controllers-2.1.1.jar"/>
        <resource-root path="grails-plugin-converters-2.1.1.jar"/>
        <resource-root path="grails-plugin-datasource-2.1.1.jar"/>
        <resource-root path="grails-plugin-domain-class-2.1.1.jar"/>
        <resource-root path="grails-plugin-filters-2.1.1.jar"/>
        <resource-root path="grails-plugin-gsp-2.1.1.jar"/>
        <resource-root path="grails-plugin-i18n-2.1.1.jar"/>
        <resource-root path="grails-plugin-log4j-2.1.1.jar"/>
        <resource-root path="grails-plugin-mimetypes-2.1.1.jar"/>
        <resource-root path="grails-plugin-scaffolding-2.1.1.jar"/>
        <resource-root path="grails-plugin-services-2.1.1.jar"/>
        <resource-root path="grails-plugin-servlets-2.1.1.jar"/>
        <resource-root path="grails-plugin-url-mappings-2.1.1.jar"/>
        <resource-root path="grails-plugin-validation-2.1.1.jar"/>
        <resource-root path="grails-resources-2.1.1.jar"/>
        <resource-root path="grails-spring-2.1.1.jar"/>
        <resource-root path="grails-web-2.1.1.jar"/>
        <resource-root path="groovy-all-1.8.8.jar"/>
        <resource-root path="icu4j-51_1.jar"/>
        <resource-root path="oro-2.0.8.jar"/>
        <resource-root path="postgresql-9.2-1002.jdbc4.jar"/>
        <resource-root path="sitemesh-2.4.jar"/>
        <resource-root path="spring-aop-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-asm-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-aspects-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-beans-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-context-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-context-support-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-core-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-expression-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-jdbc-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-jms-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-orm-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-tx-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-web-3.1.2.RELEASE.jar"/>
        <resource-root path="spring-webmvc-3.1.2.RELEASE.jar"/>
        <resource-root path="xpp3_min-1.1.4c.jar"/>
    </resources>


    <dependencies>
        <module name="javax.servlet.jsp.api" export="true"/>
        <module name="javax.servlet.jstl.api" export="true"/>
        <module name="com.h2database.h2"/>
        <module name="org.apache.commons.beanutils"/>
        <module name="org.apache.commons.collections"/>
        <module name="org.apache.commons.lang"/>
        <module name="org.apache.commons.io"/>
        <module name="org.apache.commons.pool"/>
        <module name="org.apache.log4j"/>
        <module name="org.slf4j"/>
    </dependencies>
</module>

I've removed some of the dependencies not needed and added module dependencies where appropriate.

于 2013-05-06T16:16:07.957 回答