tomcat7-maven-plugin tomcat7:run java.lang.LinkageError previously initiated loading for a different type with name

11,874

Solution 1

Biju Kunjummen answered the question in his comment to my original post. Thank you Biju Kunjummen! Please vote up his comment.

My answer to my own question is only providing a bit more detail.

The servlet-api dependency in the pom.xml needed the "provided" scope. This is because Tomcat already provides (requires and uses itself) the servlet-api dependency. Maven's dependency scoping rules are defined here:

http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope

The corrected servlet-api dependency xml:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

Why did the previous xml work when I deployed my war to a local tomcat instance, as opposed to running it "in process" (i.e., with the tomcat7:run goal)? I don't have an exact answer for this. The maven in process server runner is clearly loading up dependencies in a different way than the local tomcat instance.

My takeaway from this is that even though I may need a dependency to compile some code, I need to keep in mind that, if I'm deploying that code into some kind of container, I need to use maven's provided scope to make sure the dependencies don't collide.

Solution 2

for me it worked like.

         <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

simply adding the scope in the dependency

Share:
11,874
Hawkeye Parker
Author by

Hawkeye Parker

Web software programmer in SF Bay Area. Have done more backend than UI. More: C#, .NET, SQL; less: Java, JavaScript, Python. Big fan of high quality code ala Robert C. Martin's "Agile Principles, Patterns, and Practices in C#" and "Clean Code." Interested in psychological/sociological aspects of programming . . . how to get a team of developers working together and producing clean code. Love Agile. Interested in Lean.

Updated on June 26, 2022

Comments

  • Hawkeye Parker
    Hawkeye Parker almost 2 years

    Windows Server 2008 R2, 64 Apache Maven 2.2.1 Java version: 1.6.0_26 JAVA_HOME: C:\Program Files\Java\jdk1.6.0_26 Tomcat 7.0 Compiling project with Java 1.6

    I am trying to use tomcat7-maven-plugin to run a tomcat dev server using the tomcat7:run goal. When I try to hit the index.jsp for the server, I receive:

    HTTP Status 500 - java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
    
    type Exception report
    
    message java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
    
    description The server encountered an internal error (java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest") that prevented it from fulfilling this request.
    
    exception
    
    javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
        org.apache.jasper.servlet.JspServlet.service(JspServlet.java:343)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    root cause
    
    java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
        java.lang.Class.getDeclaredMethods0(Native Method)
        java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
        java.lang.Class.getDeclaredMethods(Class.java:1791)
        org.apache.catalina.util.Introspection.getDeclaredMethods(Introspection.java:108)
        org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:172)
        org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:369)
        org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
        org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    

    I have successfully used tomcat7:deploy to deploy the same code to a local tomcat Windows service instance. When I access the local instance of the server, no errors.

    My code depends on javax.servlet.http.HttpServlet via this maven dependency:

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

    Given the error I'm getting, I'm pretty sure there's a class loading conflict for this dependency. What I can't figure out is the how/why/where of the conflict; i.e., where are the jars which are conflicting, and how/why is this happening when I try to run with tomcat7:run, but not when I run "standalone" using my local tomcat instance.

    pom:

    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.moring.gloak</groupId>
        <artifactId>gloak-registration</artifactId>
        <packaging>war</packaging>
        <version>1.0.0-SNAPSHOT</version>
        <name>gloak-registration Maven Webapp</name>
    
        <build>
            <finalName>gloak-registration</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.0-SNAPSHOT</version>
                    <configuration>
                        <server>local_tomcat</server>
                        <url>http://localhost:9280/manager/text</url>
                        <update>true</update>
                        <port>9280</port>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.5.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <repositories>
            <repository>
                <id>people.apache.snapshots</id>
                <url>http://repository.apache.org/content/groups/snapshots-group/</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
            </dependency>
        </dependencies>
    </project>
    

    project web.xml

    <!DOCTYPE web-app PUBLIC
            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
            "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
        <display-name>Archetype Created Web Application</display-name>
    
        <servlet>
            <servlet-name>registrationServlet</servlet-name>
            <servlet-class>com.moring.gloak.web.register.RegistrationServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>registrationServlet</servlet-name>
            <url-pattern>/register</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    tomcat web.xml webapp declaration from maven target dir:

    <web-app 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://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    

    actual servlet code:

    package com.moring.gloak.web.register;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    public final class RegistrationServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.getRequestDispatcher("index.jsp").forward(request, response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            Map<String, String> messages = new HashMap<String, String>();
            request.setAttribute("messages", messages);
    
            // Get and validate name.
            String serviceName = request.getParameter("serviceName");
            if (serviceName == null || serviceName.trim().isEmpty()) {
                messages.put("name", "Please enter service name");
            } else if (!serviceName.matches("\\p{Alnum}+")) {
                messages.put("name", "Please enter alphanumeric characters only");
            }
    
            if (messages.isEmpty()) {
                messages.put("success", String.format("Service name is %s", serviceName));
            }
    
            request.getRequestDispatcher("index.jsp").forward(request, response);
        }
    }