18

I am attempting to move a xml-based Spring MVC app to a Java Configuration based app. There appears to be a mismatch with the various java.servlet classes available in maven. For instance, some provide the addServlet() method and some do not.

Here is my config class:

public class MyWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) throws ServletException {

        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();
        rootContext.register(JpaSandboxConf.class);

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/myapp/*");
    }
}

Which seems rather uncontroversial. In order to get the

container.addServlet()

method, I included this in my pom:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-servlet-api</artifactId>
    <version>7.0.30</version>
</dependency>

I tried this, but the ServletContext class from the entry below DID NOT WORK (in that it didnot provide the addServlet() method):

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>com.springsource.javax.servlet</artifactId>
    <version>2.5.0</version>
    <scope>provided</scope>
</dependency>

When I attempt to run this using

mvn clean tomcat7:run

I unhappily obtain

SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/]]
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
    at java.util.concurrent.FutureTask.get(FutureTask.java:111)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1130)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:782)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1568)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1558)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    ... 7 more
Caused by: java.lang.ClassCastException: org.springframework.web.SpringServletContainerInitializer cannot be cast to javax.servlet.ServletContainerInitializer
    at org.apache.catalina.startup.ContextConfig.getServletContainerInitializer(ContextConfig.java:1543)
    at org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.java:1464)
    at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1190)
    at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:825)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:300)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 7 more

I see that one class is coming from Spring framework and the other from javax.servlet, but once again, the method does not exist from the Spring provided class (which is frustrating, because this example exists within the Spring 3.2 documentation itself.

I am using Spring 3.2. I am NOT using Eclipse (all the examples are Eclipse based, I'm in IntelliJ). This is a maven project

I DO appreciate your help.

Lucky
  • 16,787
  • 19
  • 117
  • 151
Brian Dolan
  • 3,086
  • 2
  • 24
  • 35
  • possible duplicate of [ServletDispatcher cannot be cast to Javax.servlet.Servlet exception in my spring project](http://stackoverflow.com/questions/11704069/servletdispatcher-cannot-be-cast-to-javax-servlet-servlet-exception-in-my-spring) – Rugal Mar 18 '14 at 14:38

6 Answers6

23

A better servlet 3.0 api dependency entry in pom is available here - https://github.com/SpringSource/greenhouse/tree/servlet3, you should also mark the scope as provided, otherwise the jar will be included in your final war which will interfere with the jar provided by the container which is what seems to be happening in your case.

Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
13

I had a similar problem without Spring, where mvn tomcat7:run did not work, despite the servlet deploying to OpenShift just fine. As per Biju Kunjummen's answer, the problem for me was which servlet-api I was compiling against.

Broken:

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

Fixed:

<dependency>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>servlet-api</artifactId>
    <version>3.0.20100224</version>
    <scope>provided</scope>
</dependency>

Not terribly sure why, but it works now.

KevinL
  • 1,238
  • 11
  • 28
2

I was facing the same problem wis gradle tomcat plugin. I updated the tomcat version to 8 and it worked.

plugins {
    id "com.bmuschko.tomcat" version "2.2.2"
    id "java"
    id "eclipse"
    id "idea"
    id "war"
}


dependencies {
    providedCompile ('javax.servlet:javax.servlet-api:3.1.0')
    providedCompile ('javax.servlet.jsp:jsp-api:2.2')
    compile ('org.springframework:spring-webmvc:4.2.1.RELEASE')

    def tomcatVersion = '8.0.27'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"

}
abhi shukla
  • 1,119
  • 1
  • 10
  • 19
2

I used providedCompile 'javax.servlet:javax.servlet-api:3.1.0' to solve the issue

jogo
  • 12,469
  • 11
  • 37
  • 42
Saurabh
  • 7,525
  • 4
  • 45
  • 46
1

I am facing the same error when using Tomcat in Eclipse.

I solve this by going to Servers tab > double click the Tomcat and uncheck the "Serve modules without publishing"

Mrye
  • 699
  • 3
  • 10
  • 31
0

I alse get this problem, I use their method to handle it, but failed. my tomcat version i used are 7 and 8.0 , i got get this problem too. when i use tomcat 8.5, there is no problem. my project run successfully.

varuscn
  • 131
  • 2
  • 2