Bhavik Bhavik - 10 days ago 5
Java Question

Unable to find JSP views in Spring MVC with Embedded Jetty 9

I have a Spring MVC, upgrading the Embedded Jetty from Jetty 7 to Jetty 9.3.9 and Java 8. I rewrote the Embedded Jetty 9 class to support JSP for Jetty 9 referring examples here and some helpful questions on SO, however still when I start the App server, I get

Problem accessing /webapp/WEB-INF/views/404.jsp. Reason:

Not Found


My Server Startup class looks like:

public class ServerStart {

private static Server server;

public static void main(String[] args) throws Exception {
try {

ServerStart startup = new ServerStart ();
startup.startServer();

server.start();
server.join();
}

public void startServer(){

HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setSecureScheme("https");
httpConfiguration.setSecurePort(Integer.parseInt(properties.getProperty(
"console.port", "5444")));
httpConfiguration.setOutputBufferSize(64000);
httpConfiguration.setSendServerVersion(false);

//Http Connector
ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(httpConfiguration));
http.setPort(8080);
http.setIdleTimeout(1000 * 60 * 60);


// SSL Context Factory for HTTPS and SPDY
SslContextFactory sslCtxFactory = new SslContextFactory();
sslCtxFactory.setKeyStorePassword(properties
.getProperty("/path/to/password");
sslCtxFactory.setKeyStoreType("JKS");
sslCtxFactory.setKeyStorePath(properties.getProperty("/Path/to/keystore.jks"));

// HTTPS Configuration
HttpConfiguration https_config = new HttpConfiguration(httpConfiguration);
https_config.addCustomizer(new SecureRequestCustomizer());
https_config.setSendServerVersion(false);

// HTTPS connector
ServerConnector https = new ServerConnector(server,
new SslConnectionFactory(sslCtxFactory,"http/1.1"),
new HttpConnectionFactory(https_config));
https.setPort(5444);
https.setIdleTimeout(1000 * 60 * 60);

server.setConnectors(new Connector[] { http, https });

// Set JSP to use Standard JavaC always
System.setProperty("org.apache.jasper.compiler.disablejsr199", "false");

// setup web apps
WebAppContext context = new WebAppContext();
context.setContextPath("/webproject");
context.setAttribute("javax.servlet.context.tempdir", "/temp"));
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault( server );
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration" );

context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/.*taglibs.*\\.jar$");
context.setResourceBase("/webproject");

context.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers());
context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
context.addBean(new ServletContainerInitializersStarter(context), true);
context.setClassLoader(getUrlClassLoader());

context.addServlet(jspServletHolder(), "*.jsp");

server.setHandler(context);

}

/**
* Ensure the jsp engine is initialized correctly
*/
private static List<ContainerInitializer> jspInitializers()
{
JettyJasperInitializer sci = new JettyJasperInitializer();
ContainerInitializer initializer = new ContainerInitializer(sci, null);
List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
initializers.add(initializer);
return initializers;
}

/**
* Create JSP Servlet (must be named "jsp")
*/
private static ServletHolder jspServletHolder()
{
ServletHolder holderJsp = new ServletHolder("jsp", JettyJspServlet.class);
holderJsp.setInitOrder(0);
holderJsp.setInitParameter("logVerbosityLevel", "DEBUG");
holderJsp.setInitParameter("fork", "false");
holderJsp.setInitParameter("xpoweredBy", "false");
holderJsp.setInitParameter("compilerTargetVM", "1.8");
holderJsp.setInitParameter("compilerSourceVM", "1.8");
holderJsp.setInitParameter("keepgenerated", "true");
return holderJsp;
}

/**
* Set Classloader of Context to be sane (needed for JSTL)
* JSP requires a non-System classloader, this simply wraps the
* embedded System classloader in a way that makes it suitable
* for JSP to use
*/
private ClassLoader getUrlClassLoader()
{
ClassLoader jspClassLoader = new URLClassLoader(new URL[0], this.getClass().getClassLoader());
return jspClassLoader;
}
}


My web.xml for webapp:

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>com.tools.contexts.XmlValidatorContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>wsServlet</servlet-name>
<servlet-class>com.tools.servlets.WebSocketServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>wsServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>


Whenever I try to access http://localhost:8080/webapp/index, I get 404 Not found, however, from the info logs I can see, the webapp is hitting My BaseController:

@Controller
public class BaseController{
private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
@RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView login(HttpServletRequest request,
HttpServletResponse response) {

String sessionid = request.getSession().getId();
Map<String, String> model = new HashMap<String, Object>();
logger.info("Requested home page...");
model.put("Welcome Page", "Welcome to home");
return new ModelAndView("index", model);
}


My Project Hierarchy, I have two projects. Jetty-Startup to start the Jetty server to configure the server properties. Other project - webapp where all my web.xml, servlets, Controllers, JSP, JS, CSS etc resides:

jetty-startup
-src/main/java
- ServerStart.java
-Gradle Dependencies
...

webproject
- src/main/java
- Package com.admin.controllers
- BaseController
- Referenced Libraries
...
- src
- main
- webapp
- META-INF
- WEB-INF
- web.xml
- views
..all JSPs Here


Is there some configuration that I'm missing for JSP support? It would be very helpful anyone can figure out what I am missing.

Also, while starting the jetty I'm receiving following error:

17:11:05.067:INFO:/webproject:main: No Spring WebApplicationInitializer types detected on classpath


Not sure if it's related?

Thanks in advance!

Answer

I realized form the Spring Debug logs that I had two servlets (appservlet & wsServlet) essentially mapping to same path in my web.xml

Mapped my wsServlet to different Url-pattern and was able to load the jsp page.