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);
}
}
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With