Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AbstractAnnotationConfigDispatcherServletInitializer with Jetty

I'm using Jetty 9.1.0.RC2 and Spring 4. Have a AbstractAnnotationConfigDispatcherServletInitializer and trying to kick start the initialization with:

Server server = new Server();

WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setConfigurations(new Configuration[] { new AnnotationConfiguration() });
webAppContext.setParentLoaderPriority(true);

webAppContext.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/target/classes/.*");

server.setHandler(webAppContext);
server.start();
server.join();

But failing to detect:

No Spring WebApplicationInitializer types detected on classpath
like image 625
Matthew Campbell Avatar asked Mar 05 '14 16:03

Matthew Campbell


1 Answers

This is a common problem. Many more people are facing this issue. Sometimes it is causing error or sometimes it gives just as info. For info, there is no problem(just like warning). For error, there are many types of reason for occuring this error. I am trying to give you some sort of solutions.


  1. Sometimes spring library and jdk version mismatch causes this error. Classes are built in lower version of jdk and trying to run in upper version may cause the error. Then we need to change using Eclipse from Preferences\Java\Compiler We have to set "compiler compliance level: 1.7" and "Generated .class files compatibility: 1.6", "Source compatibility: 1.6".
  2. Some of people get that log4j wasn't configured to capture error output which was throwing configuration errors in the background.
  3. If you are using maven, then WEB-INF directory must be inside your webapp. Structure will be src/main/webapp/WEB-INF It also solves this issue.
  4. If "Project -> Build Automatically" is not selected. You can force the "m2e-wtp folder and contents" generation by doing;

    "(right-click on your project) -> Maven -> Update Project..."

Note: make sure the "Clean Projects" option is un-selected. Otherwise the contents of target/classes will be deleted and you're back to square one.

  1. Add WebROOT file directory to the default directory, then this problem will be solved.

    properties->MyEclipse->Deployment Assembly->Add

Resource Link:

  1. No Spring WebApplicationInitializer types detected on classpath
  2. INFO: No Spring WebApplicationInitializer types detected on classpath
  3. only one error: No Spring WebApplicationInitializer types detected on classpath

For tomcat,

  1. if maven has tomcat7 plugin but the JRE environment was 1.6. Then this problem occurs. Then you need to downgrade tomcat7 to tomcat6 or upgrade jdk and jre version to 1.7.
  2. Sometimes it is need to stop your tomcat. Then clean the project, clean the server and run again your project. Sometimes caches make this issue. After following this way, it may solve.

For JBOSS,

@Sotirios Delimanolis given a very nice answer. That is given below:

In a typical servlet application, you would have a web.xml descriptor file to declare your serlvets, filters, listeners, context params, security configuration, etc. for your application. Since servlet 3.0 you can do most of that programmatically.

Servlet 3.0 offers the interface ServletContainerInitializer, which you can implement. Your servlet container will look for your implementation of that class in META-INF/services/javax.servlet.ServletContainerInitializer file, instantiate it, and call its onStartup() method.

Spring has built WebApplicationInitializer on top of that interface, as an adapter/helper.

You need either the web.xml descriptor or a class that implements WebApplicationInitializer to setup and run your application.

Resource Link:

  1. Jboss No Spring WebApplicationInitializer types detected on classpath

A brief detail answer is given below with Jetty:

Spring WebApplicationInitializer - how it works and what may go wrong

Startup of servlet contexts without web.xml

Servlets of release 3 can be configured programatically, without any web.xml. With Spring and its Java-configuration you create a configuration class that implements org.springframework.web.WebApplicationInitializer. Spring will automatically find all classes that implement this interface and start the according servlet contexts. More excatly its not Spring that searches for those classes, its the servlet container (e.g. jetty or tomcat ). The class org.springframework.web.SpringServletContainerInitializer is annotated with @javax.servlet.annotation.HandlesTypes(WebApplicationInitializer.class) and implements javax.servlet.ServletContainerInitializer According to the Servlet 3 specification the container will call org.springframework.web.SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext) on every class in the classpath implementing that interface, suppling a set of classes as defined in HandlesTypes

Startup order, if there is more than one context

If there is more than one class that implements WebApplicationInitializer, the order in which they are started can be controlled with the annotation org.springframework.core.Ordered .

Things that may go wrong

Different Spring versions in the classpath

If you have different versions of WebApplicationInitializer in the classpath, the servlet container may scan for the classes implementing WebApplicationInitializer of version 'A' while your configuration classes implement WebApplicationInitializer of version 'B'. And than your configuration classes will not be found and the sercletontexts will not be started.

Unexpected WebApplicationInitializers in the classpath

Do not package any WebApplicationInitializers into jars or wars that you later may have in the classpath of other web applications. They may get found and started when you do not expect it. This happend to me when I packed WebApplicationInitializers with Maven into test-jars, which were reused by other tests.

To many classes in the classpath

The servlet container has to scan the classpath, and the more classes, the longer it takes. At least Jetty has a build in timeout, so you may get an

javax.websocket.DeploymentException thrown by
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer

The solution is to tell jetty which jars to scan. This will make the startup much faster and avoids the timeout. In Maven you can do it like this :

pom.xml

<plugin>
     <groupId> org.eclipse.jetty</groupId >
     <artifactId> jetty-maven-plugin</artifactId >
     <configuration>
     <webAppConfig>
         <contextPath> /${project.artifactId}</contextPath >
         <webInfIncludeJarPattern> busines-letter-*.</webInfIncludeJarPattern >
     </webAppConfig>

Spring logging

When you have logging configured you should find one of the following entries in your log :

If Spring finds no WebApplicationInitializer at all, you will see in the log :

No Spring WebApplicationInitializer types detected on classpath

If Spring finds at least one WebApplicationInitializer you will see :

Spring WebApplicationInitializers detected on classpath: " + initializers
like image 188
SkyWalker Avatar answered Nov 15 '22 12:11

SkyWalker