Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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);
    }
}
like image 510
Hawkeye Parker Avatar asked Jun 21 '12 19:06

Hawkeye Parker


2 Answers

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.

like image 153
Hawkeye Parker Avatar answered Nov 11 '22 17:11

Hawkeye Parker


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

like image 45
Pratik Gaurav Avatar answered Nov 11 '22 18:11

Pratik Gaurav