37

I'm working on a webapp in Spring using Spring Tool Suite. If I build and deploy the application there using the IDE onto the provided Pivotal tc Server, it works just fine. However, if I do a manual "mvn clean package" build and attempt to deploy it to a standalone Tomcat server (using newest Tomcat 7), it throws the following exception:

2017-08-23 15:24:13 WARN  AnnotationConfigWebApplicationContext:551 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerAdapter' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mvcValidator' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/el/ELManager
2017-08-23 15:24:13 ERROR DispatcherServlet:502 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerAdapter' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mvcValidator' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/el/ELManager

Upon further inspection, it does complain few lines higher above about not loading jars:

sie 23, 2017 3:24:12 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive D:\Apache-Tomcat-7.0\webapps\TestApp-0.0.1-SNAPSHOT.war
sie 23, 2017 3:24:12 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(D:\Apache-Tomcat-7.0\webapps\TestApp-0.0.1-SNAPSHOT\WEB-INF\lib\el-api-2.2.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
sie 23, 2017 3:24:12 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(D:\Apache-Tomcat-7.0\webapps\TestApp-0.0.1-SNAPSHOT\WEB-INF\lib\javax.servlet-api-3.1.0.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
sie 23, 2017 3:24:12 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(D:\Apache-Tomcat-7.0\webapps\TestApp-0.0.1-SNAPSHOT\WEB-INF\lib\tomcat-el-api-8.0.21.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/el/Expression.class
2017-08-23 15:24:13 INFO  ContextLoader:304 - Root WebApplicationContext: initialization started

My pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.exmaple.mvc</groupId>
  <artifactId>TestApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.6</version>
    </dependency>
    <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.17</version>
       <exclusions>
        <exclusion>
            <artifactId>jms</artifactId>
            <groupId>javax.jms</groupId>
        </exclusion>
        <exclusion>
            <artifactId>jmxri</artifactId>
            <groupId>com.sun.jmx</groupId>
        </exclusion>
        <exclusion>
            <artifactId>jmxtools</artifactId>
            <groupId>com.sun.jdmk</groupId>
            </exclusion>
        </exclusions>
    </dependency>
        <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.1.Final</version>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
  </dependencies>

    <build>
        <plugins>
            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        </plugins>
    </build>

</project>

What's the reason for this behavior and how can I solve this?

EDIT More information:

Adding <scope>provided</scope> to javax.servlet-api seems to fix the warning about javax.servlet-api not being loaded at the start. Problem with el-api still remains.

I've checked the tomcat/lib directory and it already contains el-api.jar in it, which is likely why it tells me it's not going to load the one I list in pom.xml. The thing is, adding <scope>provided</scope> doesn't fix it either. Whatever I do, it still complains gives me the same java.lang.NoClassDefFoundError: javax/el/ELManager error.

SOLUTION

In addition to the part in the edit above regarding javax.servlet-api the problem with el-api was that I was running a Tomcat 7 with provided el-api jar in version 2.2. The missing class was introduced in el-api 3.0. Running the same webapp in Tomcat 8 (with el-api 3.0 jar) works properly.

J_S
  • 2,985
  • 3
  • 15
  • 38
  • Does this help? https://stackoverflow.com/questions/15601469/jar-not-loaded-see-servlet-spec-2-3-section-9-7-2-offending-class-javax-serv – GhostCat Aug 23 '17 at 13:49
  • @GhostCat That solved the issue with loading `javax.servlet-api-x.y.z.jar`, that is adding `provided` to the `javax.servlet-api`. I am however still fighting with the `el-api` issue. More info in the comment under the answer below. – J_S Aug 23 '17 at 15:29
  • If anyone want to brute-force patch Tomcat7 this is how I did it, same story as in this topic (v2.2 to v3.x el-api.jar and el-impl.jar) https://stackoverflow.com/a/54305385/185565 – Whome Jan 22 '19 at 10:20

8 Answers8

35

You miss the javax.el-api as dependency. Add:

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>

to your pom.xml

Jens
  • 67,715
  • 15
  • 98
  • 113
  • 2
    I've tried it before. The thing is - I still get this error, plus tomcat tells me just like before that it failed to load `el-api` jar when it starts deploying the app. When I look into the tomcat/lib directory, it already contains `el-api.jar` in it, which is likely why it tells me it's not going to load the one I list in pom.xml. The thing is, adding `provided` doesn't fix it either. Whatever I do, it still complains gives me the same `java.lang.NoClassDefFoundError: javax/el/ELManager` error. – J_S Aug 23 '17 at 15:32
  • @JacekŚlimok Which Version of javax.el-api do you use? – Jens Aug 23 '17 at 15:35
  • As for the provided version in tomcat/lib - jar file name doesn't specify it (it's `el-api.jar`). According to MANIFEST.MF inside it's version 2.2: https://pastebin.com/sHpZKxrF – J_S Aug 23 '17 at 15:42
  • 3
    @JacekŚlimok This class was introduced in Version 3.0. So it is not available in 2.2 – Jens Aug 23 '17 at 15:43
  • 9
    This solves my issue. Running it on Tomcat 8 (current newest versionn 8.5.20) works fine. Its provided el-api is version 3.0. Marked this as an answer. If you wish to, you may add that the issue was really with the fact that I was running Tomcat 7 with older el-api. – J_S Aug 23 '17 at 16:01
  • 11
    I need it running on Tomcat 7. Any way to do this? – Impulse The Fox Mar 15 '18 at 10:37
  • @JacekŚlimok Thanks a lot, you saved my day! I've run my war file successfully only on Tomcat 8 (8.5.31 to be precise). – zkvarz Jun 05 '18 at 18:01
  • What is this? What triggers this error? Why is this not documented anywhere except on this one stackoverflow post? – Krum Dec 04 '18 at 19:30
  • 1
    Actually, this is not the proper solution. When running on Tomcat7, you can add el-api explicitly on classpath, but in this case, you will have a conflicting classes available in both - Tomcat libs and your projects dependencies. Running on Tomcat 8 works fine, but adding the el-api results in what I wrote. This post addresses the question further: https://stackoverflow.com/questions/8487048/java-lang-linkageerror-javax-servlet-jsp-jspapplicationcontext-getexpressionfac – Giorgi Tsiklauri Apr 18 '19 at 09:39
  • Quote from HV migration guide: "An implementation of Expression Language 3.0 (JSR 341) is required now." - https://hibernate.org/validator/documentation/migration-guide/ – Shawyeok Aug 30 '23 at 09:52
14

Hibernate Validator 6.x -> Bean Validation 2.0 (JSR 380) -> EL3.0

Hibernate Validator 5.x -> Bean Validation 1.1 (JSR 349) -> EL2.2

Bean Validation 1.0 (JSR 303) -> (I'm not sure)

so,it also influence others version (tomcat,jdk,jsp,servlet)

such as tomcat7, if you want to use Hibernate Validator, should use Hibernate Validator 5.x, el 2.2 (and servlet 3.0, jsp 2.2 and jdk 6+)

CuriousRookie
  • 141
  • 1
  • 2
14

Downgrade hibernate-validator to version 5 and it will work fine with Tomcat 7. In my case I add next dependency to my pom:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.3.Final</version>
</dependency>

Or you can add newer el-api.jat to tomcat lib folder.

6

Please refer to Hibernate validation "Unable to initialize javax.el.ExpressionFactory" error

use

<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.el</artifactId>
   <version>3.0.1-b08</version>
</dependency>
Nandan kelkar
  • 69
  • 1
  • 1
3

I'm using Tomcat 7.0.9 and couldn't change to any newer one due my company bureaucracy. Importing EL as a dependency didn't solve it either.

At Tomcat's root folder -> lib I replaced old el-api (2.2 version of it) with a new 3.0 (from local .m2\repository\javax\el\javax.el-api\3.0.0). Then, isolating tomcat's dependencies correctly (as shown here) made my WAR be correctly deployed at Tomcat 7.0.9

rado
  • 5,720
  • 5
  • 29
  • 51
  • This was the solution for me. Now I have to explain to our CTO and Chief Architect that Tomcat 7 is not compatible with the app. I should note that I tried deploying the app to Tomcat 9 and this problem was not present, so this may be our opportunity to upgrade – Chris Clark Feb 28 '19 at 14:54
  • Thank you Rado for this awesome answer – Faraz Dec 23 '20 at 18:39
2

Adding my answer for those having Tomcat 7 and trying to apply selected answer.

If adding dependency does not help you and you continue getting

java.lang.NoClassDefFoundError: javax/el/ELManager

that's because Tomcat 7 will not allow you to load a more modern jar with objects from javax.* package. It will print to the log:

jakarta.el-3.0.3.jar - jar not loaded. See Servlet Spec 3.0, section 10.7.2. Offending class: javax/el/Expression.class

The solution will be to either upgrade your Tomcat or downgrade hibernate-validator to the latest 5.x version. Another (less preferred from my POV) option would be to try to replace jars in your tomcat7/lib folder.

Kirill
  • 6,762
  • 4
  • 51
  • 81
1

In my case, Commented out this dependency,

<!-- <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.8.Final</version>
    </dependency> -->

and added

    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.0</version>
        <scope>provided</scope>
    </dependency> 

This solved my issue

Noorus Khan
  • 1,342
  • 3
  • 15
  • 33
0

Try the following:

  • Add javax.eland javax.el-api to the pom.xml as others mention
  • If you have different classloaders - as often the case when using OSGi - you need to temporarily set the context to the one holding the implementation. Wrap your call with:

    ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try {
      Class<?> currentClass = this.getClass(); // or any class that is in a bundle with the dependency 
      Thread.currentThread().setContextClassLoader(currentClass.getClassLoader());
      // execute library call
    } finally {
      Thread.currentThread().setContextClassLoader(originalClassLoader); // back to original context
    }
    
  • Add a service to META-INF/services/

  • Add a property to $java.home/lib/el.properties
  • Use the system property with the factoryId

When the library is instantiating the ExpressionFactory via > ELManager.newInstance(..) > FactoryFinder.find(..) it has several strategies to find an implementation. The call is hardcoded like this:

public static ExpressionFactory newInstance(Properties properties) {
    return (ExpressionFactory) FactoryFinder.find(
        "javax.el.ExpressionFactory", "com.sun.el.ExpressionFactoryImpl", properties);
}

See source of javax.el.FactoryFinder.find(..) for further information

Terran
  • 1,091
  • 18
  • 29