I am relatively new to Spring MVC, and have a working knowledge of Embedded Jetty. We have an existing Spring MVC webapp which I can compile into a war and drop into Tomcat, and it works fine. However I now want to run it in Embedded Jetty instead of having to drop it into Tomcat.
I have followed this tutorial which I found helpful (with a few small changes):
http://kielczewski.eu/2013/11/using-embedded-jetty-spring-mvc/
And everything seems to be 'almost' ok, except the mappings for my jsps don't seem to work.
Here is my main class:
public class EmbeddedJetty {
private static final int DEFAULT_PORT = 8080;
private static final String CONTEXT_PATH = "/";
private static final String CONFIG_LOCATION = "/WEB-INF/spring-servlet.xml";
private static final String MAPPING_URL = "/*";
public static void main(String[] args) throws Exception {
new EmbeddedJetty().startJetty(getPortFromArgs(args));
}
private static int getPortFromArgs(String[] args) {
if (args.length > 0) {
try {
return Integer.valueOf(args[0]);
} catch (NumberFormatException ignore) {
}
}
return DEFAULT_PORT;
}
private void startJetty(int port) throws Exception {
Server server = new Server(port);
WebApplicationContext context = getContext();
ServletContextHandler servletContextHandler = getServletContextHandler(context);
server.setHandler(servletContextHandler);
server.start();
server.join();
ResourceHandlerRegistry rhr = new ResourceHandlerRegistry(context, servletContextHandler.getServletContext());
rhr.addResourceHandler("images/**").addResourceLocations("images/");
rhr.addResourceHandler("jsp/**").addResourceLocations("jsp/");
rhr.addResourceHandler("css/**").addResourceLocations("css/");
}
private static ServletContextHandler getServletContextHandler(WebApplicationContext context) throws IOException {
ServletContextHandler contextHandler = new ServletContextHandler();
contextHandler.setErrorHandler(null);
contextHandler.setContextPath(CONTEXT_PATH);
DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
ServletHolder servletHolder = new ServletHolder(dispatcherServlet);
contextHandler.addServlet(servletHolder, MAPPING_URL);
contextHandler.addEventListener(new ContextLoaderListener(context));
contextHandler.setResourceBase(new ClassPathResource("webapp").getURI().toString());
return contextHandler;
}
private static WebApplicationContext getContext() {
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocation(CONFIG_LOCATION);
return context;
}
}
This is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- Welcome file -->
<display-name>USER Administration</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- This is the servlet that will route to the correct Controller based on annotations -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--Map non-resource URLs to the DispatcherServlet -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Allow access to the resources -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
</web-app>
This is my spring-servlet.xml (relevant parts - I think):
<!-- This is the base package(s) for where spring should scan for @Component, @Service, @Controller, etc -->
<context:component-scan base-package="com.my.user.admin" />
<!-- A resolver for the returned ModelAndView objects and other strings, this tells it to append .jsp and look in the /WEB-INF/jsp/ for it -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
<!-- loads in property files for use in this config -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:Frameworks/hibernate.properties</value>
<value>classpath:Frameworks/activemq.properties</value>
</list>
</property>
</bean>
<!-- Hibernate 3 session factory used for session management -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:${hibernate.config.location}" />
</bean>
I then build it with the maven shade plugin, and run it with the following command:
java -classpath c:\dev\customclasspath;target\user-admin.jar com.admin.main.EmbeddedJetty
It starts up, and all looks fine in the logs, and I see lots of lines where it is loading my Java classes onto URLs:
Mapped URL path [/modifyUser] onto handler 'menuController
Mapped URL path [/modifyUser.*] onto handler 'menuControll
Mapped URL path [/modifyUser/] onto handler 'menuControlle
Mapped URL path [/addUser] onto handler 'menuController'
Mapped URL path [/addUser.*] onto handler 'menuController'
Mapped URL path [/addUser/] onto handler 'menuController'
But when I try to load up my app at "localhost:8080", I get a 'Not Found -- Powered by Jetty' page, and in the logs I see the following message:
No mapping found for HTTP request with URI [/] in DispatcherServlet with name 'org.springframework.web.servlet.DispatcherServlet-6910fe28'
What am I doing wrong? In my jar file, I can see the file /webapp/index.jsp, so I thought it might be that, but if I do "localhost:8080/webapp/" that doesn't work either. I have no idea what to change now, any help would be appreciated!
EDIT1
I believe the issue is because it is not actually loading my web.xml file (where I define the servlet-mappings) because I am creating the Jetty Context as the spring context, and not a 'WebAppContext'. However, I need the spring-servlet.xml file because it contains all my Controllers. How do I load both?