Undertow is another alternative for using an embedded container with Spring Boot. You can find general information in the Spring Boot reference guide chapter Use Undertow instead of Tomcat. While I was working on updating the Spring Boot documentation regarding the JSP support for Tomcat, I noticed the following line in the reference guide for Spring Boot
1.3.3
:"Undertow does not support JSPs."
Being a good citizen, I dug a little deeper and discovered the Undertow JSP sample application by Chris Grieger. It turns out that Undertow has indeed JSP support by using jastow, which is a Jasper fork for Undertow. The key was to adapt the Undertow JSP sample application for Spring Boot. Doing so was actually fairly straightforward. The actual Undertow configuration uses Spring Boot`s
EmbeddedServletContainerCustomizer
:final UndertowDeploymentInfoCustomizer customizer = new UndertowDeploymentInfoCustomizer() { @Override public void customize(DeploymentInfo deploymentInfo) { deploymentInfo.setClassLoader(JspDemoApplication.class.getClassLoader()) .setContextPath("/") .setDeploymentName("servletContext.war") .setResourceManager(new DefaultResourceLoader(JspDemoApplication.class)) .addServlet(JspServletBuilder.createServlet("Default Jsp Servlet", "*.jsp")); final HashMap<String, TagLibraryInfo> tagLibraryInfo = TldLocator.createTldInfos(); JspServletBuilder.setupDeployment(deploymentInfo, new HashMap<String, JspPropertyGroup>(), tagLibraryInfo, new HackInstanceManager()); } };
The full source is available in the
JspDemoApplication
class. The main issue is more or less the retrieval and configuration of the used Taglibraries. The Undertow JSP sample provides the TldLocator class, which does the heavy lifting. For our example, I am adapting that class so that it works in the context of Spring Boot. In Spring Boot we are dealing with über-Jars, meaning the resulting executable jar file will contain other jar files representing its dependencies.Spring provides some nifty helpers to retrieve the needed Tag Library Descriptors (TLD) files. In
TldLocator#createTldInfos
I use a ResourcePatternResolver
, specifically a PathMatchingResourcePatternResolver
with a location pattern of classpath*:**/*.tld
.final URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader); final Resource[] resources; final String locationPattern = "classpath*:**/*.tld"; try { resources = resolver.getResources(locationPattern); } catch (IOException e) { throw new IllegalStateException(String.format("Error while retrieving resources" + "for location pattern '%s'.", locationPattern, e)); }
Don’t forget the asterix right after classpath . The classpath*: allows you to retrieve multiple class path resources with the same name. It will also retrieve resources across multiple jar files. This is an extremely useful feature. For more information please see the relevant JavaDocs for PathMatchingResourcePatternResolver. |
Once we have the TLD resources, they will be parsed and ultimately used to create a collection of
org.apache.jasper.deploy.TagLibraryInfo
. With those at hand, we create a JSP deployment for Undertow using the DeploymentInfo and the TagLibraryInfo
collection.final HashMap<String, TagLibraryInfo> tagLibraryInfo = TldLocator.createTldInfos(); JspServletBuilder.setupDeployment(deploymentInfo, new HashMap<String, JspPropertyGroup>(), tagLibraryInfo, new HackInstanceManager());
And that’s it. Simply build and run the application and you should have a working JSP-based application.
$ mvn clean package $ java -jar jsp-demo-undertow/target/jsp-demo-undertow-1.0.0-BUILD-SNAPSHOT.jar
In your console you should start seeing how the application starts up.
Once started, open your browser and go to the following Url http://localhost:8080/.
You can find the full source-code for this sample at https://github.com/ghillert/spring-boot-jsp-demo
2 comments:
I am the original author of the spring-boot-undertow-starter and author of the string "Undertow does not support JSPs."
At that time I have not managed to support them. Glad to here that you pushed harder or maybe Jastow became a little bit more convenient.
Have you considered a PR to spring-boot project?
@Ivan - Thanks for your comment! That would be the idea eventually. Just need to get around it. As a first step, I want to collect the state of what is possible (originally I only cared about Tomcat but it seems there is some general interest in JSP support via Boot) Next, I plan to update the Boot documentation. A followup ultimately would be to think about what can be "integrated" back into Boot proper to make the user experience better.
Post a Comment