tomcat7-maven-plugin tomcat7:run java.lang.LinkageError previously initiated loading for a different type with name
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:
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
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, 2022Comments
-
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); } }