Why struts application throws java.lang.ClassNotFoundException?

Solution Verified - Updated -

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 5.x
    • 6.x
  • Apache Struts
    • 1.x

Issue

  • Why I'm getting java.lang.LinkageError even though application contains struts-el.jar in /WEB-INF/lib folder?
WARN  [org.jboss.modules] (MSC service thread 1-4) Failed to define class org.apache.strutsel.taglib.tiles.ELPutListTag in Module "deployment.example.war:main" from Service Module Loader: java.lang.LinkageError: Failed to link org/apache/strutsel/taglib/tiles/ELPutListTag (Module "deployment.example.war:main" from Service Module Loader)
    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)
...
Caused by: java.lang.ClassNotFoundException: org.apache.struts.tiles.taglib.PutListTag from [Module "deployment.example.war:main" from Service Module Loader]
...
  • Why struts application is throwing ClassNotFoundException with following stack trace?
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/MyApp]] (HDScanner) Servlet action threw unload() exception
javax.servlet.ServletException: Servlet.destroy() for servlet action threw exception
    at org.apache.catalina.core.StandardWrapper.unload(StandardWrapper.java:1269)
...
...
Caused by: java.lang.NoClassDefFoundError: org/apache/struts/config/ModuleConfig
    at org.apache.struts.action.ActionServlet.destroyModules(ActionServlet.java:497)
...
...
Caused by: java.lang.ClassNotFoundException: org.apache.struts.config.ModuleConfig from BaseClassLoader@456f580{vfsfile:/opt/AAA/MyApp.war/}
  • Why struts application deployment is failing with java.lang.ClassNotFoundException?
Caused by: java.lang.RuntimeException: JBAS018757: Error getting reflective information for class org.apache.struts.action.ActionServlet with ClassLoader ModuleClassLoader for Module "deployment.my.ear.my.war:main" from Service Module Loader
    at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:72) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ee.metadata.MethodAnnotationAggregator.runtimeAnnotationInformation(MethodAnnotationAggregator.java:58)
    at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.handleAnnotations(InterceptorAnnotationProcessor.java:107)
    at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.processComponentConfig(InterceptorAnnotationProcessor.java:92)
    at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.deploy(InterceptorAnnotationProcessor.java:77)
    at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:120) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    ... 5 more
Caused by: java.lang.NoClassDefFoundError: Lorg/apache/commons/collections/FastHashMap;
    at java.lang.Class.getDeclaredFields0(Native Method) [rt.jar:1.6.0_33]
    at java.lang.Class.privateGetDeclaredFields(Class.java:2291) [rt.jar:1.6.0_33]
    at java.lang.Class.getDeclaredFields(Class.java:1743) [rt.jar:1.6.0_33]
    at org.jboss.as.server.deployment.reflect.ClassReflectionIndex.<init>(ClassReflectionIndex.java:57) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:68) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    ... 10 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.FastHashMap from [Module "deployment.my.ear.my.war:main" from Service Module Loader]
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:197) [jboss-modules.jar:1.3.0.Final-redhat-2]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:443) [jboss-modules.jar:1.3.0.Final-redhat-2]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:431) [jboss-modules.jar:1.3.0.Final-redhat-2]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:398) [jboss-modules.jar:1.3.0.Final-redhat-2]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:373) [jboss-modules.jar:1.3.0.Final-redhat-2]
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:118) [jboss-modules.jar:1.3.0.Final-redhat-2]
    ... 15 more
  • I got following error when I run my application:
18:33:30,245 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/sample].[action]] (http-localhost/127.0.0.1:8080-2) JBWEB000236: Servlet.service() for servlet action threw exception: java.lang.ClassNotFoundException: antlr.TokenStream from [Module "deployment.sample.ear:main" from Service Module Loader]
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:196) [jboss-modules.jar:1.2.0.Final-redhat-1]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:444) [jboss-modules.jar:1.2.0.Final-redhat-1]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:432) [jboss-modules.jar:1.2.0.Final-redhat-1]
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:374) [jboss-modules.jar:1.2.0.Final-redhat-1]
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:119) [jboss-modules.jar:1.2.0.Final-redhat-1]
    at java.lang.Class.getDeclaredMethods0(Native Method) [rt.jar:1.7.0_51]
    at java.lang.Class.privateGetDeclaredMethods(Unknown Source) [rt.jar:1.7.0_51]
    at java.lang.Class.getMethod0(Unknown Source) [rt.jar:1.7.0_51]
    at java.lang.Class.getMethod(Unknown Source) [rt.jar:1.7.0_51]
    at org.apache.commons.validator.ValidatorAction.loadValidationMethod(ValidatorAction.java:600) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.commons.validator.ValidatorAction.executeValidationMethod(ValidatorAction.java:532) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.commons.validator.Field.validateForRule(Field.java:796) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.commons.validator.Field.validate(Field.java:876) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.commons.validator.Form.validate(Form.java:288) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.commons.validator.Validator.validate(Validator.java:351) [commons-validator-1.3.1.jar:1.3.1]
    at org.apache.struts.validator.ValidatorForm.validate(ValidatorForm.java:116) [struts-core-1.3.8.jar:1.3.8]

Resolution

Package the correct version of the Apache Struts jars and required dependencies as specified by the Apache Struts documentation and do not mix older version jars in the application.

  • Use and package appropriate version of struts.jar in the application. The jar file should be present inside the application's /WEB-INF/lib/ folder.
  • If application uses taglib component, put compatible struts-el.jar in the application.
  • Struts jar depends on some other APIs, for example: commons-beanutils.jar, commons-collections.jar, commons-digester.jar, commons-logging.jar, commons-validator.jar,
    jakarta-oro.jar, struts-legacy.jar, antlr.jar etc. Make sure application have all required dependent jars.
  • EAP 6 have some of struts dependent jars inside $JBOSS_HOME/modules/system/layers/base/org/apache/commons module. To avoid the version conflict, verify compatibility of existing jars in EAP with application. Depending on this compatibility, add either dependency or exclusion logic in jboss-deployment-structure.xml. For example,
<jboss-deployment-structure>
    <!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
    <exclusions>
        <module name="org.apache.commons.beanutils" />
        <module name="org.apache.commons.collections" />
        <module name="org.apache.commons.logging" />
    </exclusions>
</jboss-deployment-structure>

Root Cause

For Taglib related error

  • "org.apache.strutsel.taglib.tiles.ELPutListTag" in "example.war/WEB-INF/lib/struts-el-1.3.5.jar" is looking for "org.apache.struts.tiles.taglib.PutListTag".
  • "example.war/WEB-INF/lib/struts.jar" manifest shows it is version 1.1. "example.war/WEB-INF/lib/struts-el.1.3.5.jar" manifest shows it is version 1.3.5.
  • Struts 1.1 contains: "org.apache.struts.taglib.tiles.PutListTag" where Struts-el 1.3.5 expects: "org.apache.struts.tiles.taglib.PutListTag".
  • Struts was restructured from 1.2.x to 1.3.x and the package name changed for tiles. Thus mixing struts-el-1.3.5 with struts 1.2.x causes the ClassNotFoundException.
  • Struts 1.1.x & 1.2.x has "org.apache.struts.taglib.tiles.PutListTag".
  • Struts 1.3.x has "org.apache.struts.tiles.taglib.PutListTag".

Diagnostic Steps

  • Run jar -tf on the jars packaged or tattletale on the application and check the full class names & packages and confirm the class is missing.
  • Check the manifest of the packaged jars to see what version of Apache Struts is being used.
  • Check the Apache Struts source to see that the packages changed.
  • Check the Apache Struts documentation to see if the jars packaged are compatible (struts / struts-el).

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments