Setting up embedded Jetty 8 and Spring MVC with Maven and NO XML
You can check out the complete source of this simple project from github. If you want to set up with XML configuration, check my earlier post.
Starting a new project, and irritated by xml configuration, I thought I'd try Spring @MVC (annotation configured MVC) with Jetty-8 embedded using the no xml servlet 3.0 configuration approach.
Initializing the Servlet Context
The Servlet 3 spec introduces the ability to configure the servlet context from code, via implementations of ServletContainerInitializer
. You can dynamically configure Servlets and Filters here.
Spring @MVC provides an implementation of ServletContainerInitializer
(SpringServletContainerInitializer
) which tells the container to scan for classes which implement WebApplicationInitializer
, so when using @MVC we need to provide an implementation of WebApplicationInitializer
.
Here's a simple one that gets us up and running with a Spring DispatcherServlet mapped to "/" and JSP processing for *.jsp requests (including those forwarded from Controllers):
public class WebAppInitializer implements WebApplicationInitializer
{
private static final String JSP_SERVLET_NAME = "jsp";
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
@Override
public void onStartup(ServletContext aServletContext)
throws ServletException
{
registerListener(aServletContext);
registerDispatcherServlet(aServletContext);
registerJspServlet(aServletContext);
}
private void registerListener(ServletContext aContext)
{
AnnotationConfigWebApplicationContext _root =
createContext(ApplicationModule.class);
aContext.addListener(new ContextLoaderListener(_root));
}
private void registerDispatcherServlet(ServletContext aContext)
{
AnnotationConfigWebApplicationContext _ctx =
createContext(WebModule.class);
ServletRegistration.Dynamic _dispatcher =
aContext.addServlet(
DISPATCHER_SERVLET_NAME, new DispatcherServlet(_ctx));
_dispatcher.setLoadOnStartup(1);
_dispatcher.addMapping("/");
}
private void registerJspServlet(ServletContext aContext) {
ServletRegistration.Dynamic _dispatcher =
aContext.addServlet(JSP_SERVLET_NAME, new JspServlet());
_dispatcher.setLoadOnStartup(1);
_dispatcher.addMapping("*.jsp");
}
private AnnotationConfigWebApplicationContext createContext(
final Class<?>... aModules)
{
AnnotationConfigWebApplicationContext _ctx =
new AnnotationConfigWebApplicationContext();
_ctx.register(aModules);
return _ctx;
}
}
Notice here that I am registering two "Modules" (a naming convention I've adopted for my Spring @Configuration classes) - ApplicationModule
and WebModule
. I like to configure the various layers of the application separately.
In ApplicationModule
I'll put things like scheduled operations and any dependencies those operations need, while anything that is only needed during web request handling I'll put in WebModule
.
ApplicationModule
for a simple web-app might be unnecessary.
@Configuration
public class ApplicationModule
{
// Declare "application" scope beans here (ie.,
// beans that are not _only_ used by the web context)
}
WebModule
will be used to configure Spring MVC, and for a simple web-app might look like this:
@EnableWebMvc
@Configuration
@ComponentScan(basePackages={"com.sjl"})
public class WebModule extends WebMvcConfigurerAdapter
{
@Override
public void addViewControllers(ViewControllerRegistry aRegistry)
{
aRegistry.addViewController("/").setViewName("index");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry aRegistry)
{
ResourceHandlerRegistration _res =
aRegistry.addResourceHandler("/WEB-INF/view/**/*");
_res.addResourceLocations(
"classpath:/META-INF/webapp/WEB-INF/view/");
}
@Bean
public ViewResolver viewResolver()
{
UrlBasedViewResolver _viewResolver =
new UrlBasedViewResolver();
_viewResolver.setViewClass(JstlView.class);
_viewResolver.setPrefix("WEB-INF/view/");
_viewResolver.setSuffix(".jsp");
return _viewResolver;
}
}
I'm extending Spring's WebMvcConfigurerAdapter which provides a host of conveniences. Note that this WebModule
sets the annotations @EnableWebMvc and @ComponentScan which are equivalent to the xml configuration you're probably familiar with:
<mvc:annotation-driven/>
<context:component-scan base-package="com.sjl" />
The ResourceHandlerRegistration
provides a mapping from requests forwarded to /WEB-INF/view/
onto the classpath location of the actual files. Without this, for example, Jetty won't be able to find your jsp files when Controller
's forward requests to View
's (the ViewResolver
's prefix must be matched by the ResourceHandler
's path-pattern).
What remains is to instantiate Jetty and have it find its configuration from the classpath. I won't list that here as its quite long, and the full working example is in github.
An important thing to point out is that there is a problem with current versions of Jetty (8.1.7) where Jetty won't find your WebApplicationInitializer
classes unless they are either inside a Jar or in the WEB-INF/classes. When running embedded from your IDE neither of these will be true.
This results in log output like "No Spring WebApplicationInitializer types detected on classpath" and is why, in my WebServer class, I set a subclass of AnnotationConfiguration
which overrides the default Jetty behaviour to also search for non-jar'd classes on the classpath (see the codefrom around line 75).
Configuring global exception-handling in Spring MVC
It took a couple of hours to figure this out - the mighty Google and even StackOverflow let me down - in the end I had to actually read Spring's DispatcherServlet code! (I know, right!?)
Here's the problem I was having - I'm using Spring MVC's data-binding tricks to inject objects into my @Controller
's methods like this:
@Controller
@RequestMapping("things/{thing}.html")
class MyController {
public ModelAndView thing(@PathVariable Thing aThing) {
// Thing should be magically mapped from
// the {thing} part of the url
return new ModelAndView(..blah..);
}
}
I have global Formatter
's configured as described in my previous post, and I want my method parameters to be automatically conjured from @PathVariable
's and so on.
So far so good .. until I make a screw-up and parameter binding fails for any reason, at which point Spring's exception-handling kicks in. When that happens, Spring eats the exception and dumps me on the worlds shittiest error page saying:
HTTP ERROR 400
Problem accessing /your/url/whatever.html. Reason:
Bad Request
Wow, thanks Spring!
To blame here are Spring's default set of HandlerExceptionResolver
's, which are specified in DispatcherServlet.properties
in the spring-webmvc jar. In 3.1.2 it says:
org.springframework.web.servlet.HandlerExceptionResolver=
org.springfr..AnnotationMethodHandlerExceptionResolver,
org.springfr..ResponseStatusExceptionResolver,
org.springfr..DefaultHandlerExceptionResolver
(I've shortened the package-names to keep things readable)
Beats me why the default is to eat the exception without even logging it when Spring is normally so chatty about everything it does, but there you go. OK, so we need to configure some custom exception-handling so we can find out what's actually going wrong. There are two ways (that I know of) to do that:
- Use
@ExceptionHandler
annotated methods in our@Controller
's to handle exceptions on a per-controller basis (or across more than one@Controller
if you have a hierarchy and implement the@ExceptionHandler
method high-up in the hierarchy). - Register a
HandlerExceptionResolver
implementation to deal with exceptions globally (ie. across all@Controller
's, regardless of hierarchy).
@ExceptionHandler
These bad-boys are straight-forward to use - just add a method in your @Controller
and annotate it with @ExceptionHandler(SomeException.class)
- something like this:
@Controller
class MyExceptionalController {
@ExceptionHandler(Exception.class)
public void handleExceptions(Exception anExc) {
anExc.printStackTrace(); // do something better than this ;)
}
@RequestMapping("/my/favourite/{thing}")
public void showThing(@PathVariable Thing aThing) {
throw new RuntimeException("boom");
}
}
That exception-handler method will now be triggered for any exceptions that occur while processing this controller - including any exceptions that occur while trying to format the Thing parameter.
There's a bit more to it, for example you can parameterise the annotation with an array of exception-types. Shrug.
Just for completeness its worth mentioning that when formatting/conversion fails the exception presented to the @ExceptionHandler
will be a TypeMismatchException
, possibly wrapping a ConversionFailedException
which in turn would wrap any exception thrown by your Formatter
classes.
Custom HandlerExceptionResolver
This is the better approach, IMHO: Set up a HandlerExceptionResolver to deal with exceptions across all @Controller
's and override with @ExceptionHandler
's if you have specific cases that need special handling.
A deadly simple HandlerExceptionResolver
might look like this:
package com.sjl.web;
import org.springframework.core.*;
import org.springframework.web.servlet.*
public class LoggingHandlerExceptionResolver
implements HandlerExceptionResolver, Ordered {
public int getOrder() {
return Integer.MIN_VALUE; // we're first in line, yay!
}
public ModelAndView resolveException(
HttpServletRequest aReq, HttpServletResponse aRes,
Object aHandler, Exception anExc
) {
anExc.printStackTrace(); // again, you can do better than this ;)
return null; // trigger other HandlerExceptionResolver's
}
}
Two things worth pointing out here:
- We are implementing
Ordered
and returningInteger.MIN_VALUE
- this puts us at the front of the queue for resolving exceptions (and ahead of the default). If we don't implementOrdered
we won't see the exception before one of the default handlers grabs and handles it. The default handlers appear to be registered with orders ofInteger.MAX_VALUE
, so any int below that will do. - We are returning
null
from theresolveException
method - doing this means that the other handlers in the chain get a chance to deal with the exception. Alternatively we can return aModelAndView
if we want to (and if we know how to deal with this particular kind of exception), which will prevent handlers further down the chain from seeing the exception.
There are some classes in Spring's HandlerExceptionResolver
hierarchy that you might want to look at sub-classing - AbstractHandlerMethodExceptionResolver
and SimpleMappingExceptionResolver
are good ones to check first.
Of course we need to make Spring's DispatcherServlet
aware of our custom HandlerExceptionResolver
. The only configuration we need is:
<bean class="com.sjl.web.LoggingHandlerExceptionResolver"/>
No really, that's it.
There's an unusually high level of magic surrounding the DispatcherServlet
, so although you must define your resolver as a bean in your spring config you do not need to inject it into any other spring beans. The DispatcherServlet
will search for beans implementing the interface and automagically use them.
Configuring global data-binding formatters in Spring MVC
Here's a very quick how-to for configuring Spring-MVC (Spring 3.1.x) to use a global set of formatters for converting (data-binding) web-request and form parameters for use in Controllers, rather than having to have an @InitBinder
annotated method in all your @Controller
's.
In your spring-web configuration:
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- just to show that we can wire other beans into our registrar -->
<bean id="serviceA" class="com.sjl.myproject.ServiceA"/>
<bean id="serviceB" class="com.sjl.myproject.ServiceB"/>
<!-- Binding -->
<bean
id="customFormatterRegistrar"
class="com.sjl.myproject.web.config.CustomFormatterRegistrar">
<constructor-arg ref="serviceA"/>
<constructor-arg ref="serviceB"/>
</bean>
<bean
id="conversionService"
class="
org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<ref local="customFormatterRegistrar"/>
</set>
</property>
</bean>
Be sure to add the "conversion-service" attribute (pointing at your conversionService bean) to the <mvc:annotation-driven> element, otherwise it won't work!
The CustomFormatterRegistrar class:
package com.sjl.myproject.web.config;
import org.springframework.format.*;
import com.sjl.myproject.*;
public class CustomFormatterRegistrar implements FormatterRegistrar {
private ServiceA serviceA;
private ServiceB serviceB;
// construct the registrar with other spring-beans as constructor args
public CustomFormatterRegistrar(
ServiceA aServiceA,
ServiceB aServiceB) {
serviceA = aServiceA;
serviceB = aServiceB;
}
@Override
public void registerFormatters(FormatterRegistry aRegistry) {
aRegistry.addFormatter(new SomeTypeFormatter(serviceA));
aRegistry.addFormatter(new OtherTypeFormatter(serviceB))
}
}
An example formatter:
package com.sjl.myproject.web.config;
import java.text.*;
import java.util.*;
import org.springframework.format.Formatter;
import com.sjl.myproject.*;
public class SomeTypeFormatter implements Formatter<SomeType> {
private ServiceA serviceA;
public SomeTypeFormatter(ServiceA aServiceA) {
serviceA = aServiceA;
}
@Override
public String print(SomeType aSomeType, Locale aLocale) {
return aSomeType..; // produce some string-based identifier
}
@Override
public SomeType parse(String aText, Locale aLocale) throws ParseException {
return serviceA.lookupByNameOrIdOrSomething(aText);
}
}
And a Controller that benefits from it:
package com.sjl.myproject.web.controllers;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
import com.sjl.myproject.*;
@Controller
public class SomeController {
public static final String URL = "path/with/{param1}/and/{param2}";
@RequestMapping(SomeController.URL)
public String blah(
@PathVariable SomeType param1,
@PathVariable OtherType param2) {
// .. do stuff with our typed params
return "view-name";
}
}
Comment on this post
Spring config for parameterised, non-static factory methods
I recently discovered a nice way of using beans defined in your spring config as factories in the definition of other beans.
Its great, for example, when you want a factory that has non-static factory methods, or that relies on a bunch of other dependencies, or you want to instrument beans via some service which is itself a bean (this is what I was doing when I made this discovery). Here's how it looks..
A factory class whose factory-method is non-static and requires parameters:
package com.sjl;
class Factory {
private DependencyA depA;
public Factory(DependencyA aDepA) {
depA = aDepA;
}
public ResultType newInstance(DependencyB aDepB) {
ResultType _result = ..; // use the deps to cook up result
return _result;
}
}
.. and a Spring XML config:
<bean id="depA" class="com.sjl.DependencyA"/>
<bean id="depB" class="com.sjl.DependencyB"/>
<bean id="factory" class="com.sjl.Factory">
<constructor-arg ref="depA"/>
</bean>
<bean id="result" class="com.sjl.ResultType"
factory-bean="factory" factory-method="newInstance">
<constructor-arg ref="depB"/>
</bean>
So what we have here is an instance of Factory
, created with a dependency (depA), on which we invoke a non-static method with arguments to create our ResultType
.
The bit that surprised me was the use of <constructor-arg>
elements to define the parameters to pass to the factory method.
Instrumentation
If you followed any of my recent posts you'll know that I've been playing with dynamic proxies to create services that automagically decorate objects with instrumented versions.
As an example, in this post I showed an InstumentationService
which adds timing around method invocations.
I wanted to instrument several (about 8 actually) of my beans via a service that adds health monitoring, where the healthiness of a service is measured as a ratio of successful method invocations to unsuccessful ones (that throw exceptions).
The interface for instrumenting objects for health-monitoring looks like this:
interface HealthServiceInstrumenter {
public <T> T instrument(T aT);
}
So what I needed from Spring is:
- to create the instance of my
HealthServiceInstrumenter
, - to create the instances of various different
T
to pass through theHealthServiceInstrumenter
, and - the tricky part - to get spring to create the instrumented bean of type
T
by passing the original bean through the instrumenter.
Here's what the spring wiring looks like for that:
<bean id="health-instrumenter" class="com.sjl.HealthInstrumentationService"/>
<bean id="uninstrumented-bean-A" class="com.sjl.BeanA"
autowire-candidate="false"/>
<bean id="bean-A" class="com.sjl.BeanA"
factory-bean="health-instrumenter"
factory-method="instrument">
<constructor-arg ref="uninstrumented-bean-A"/>
</bean>
<bean id="uninstrumented-bean-B" class="com.sjl.BeanB"
autowire-candidate="false"/>
<bean id="bean-B" class="com.sjl.BeanB"
factory-bean="health-instrumenter"
factory-method="instrument">
<constructor-arg ref="uninstrumented-bean-B"/>
</bean>
Comment on this post
Implicit Future's, aka Promises
java.lang.concurrent.Future<T>
is an example of an explicit future, where client code is well aware that the object it is handling is not a direct reference to the value of interest, and must invoke a method to obtain the value (Future.get()
in the case of java.lang.concurrent.Future
).
That's all very well, but if you have collaborators that expect to deal with the value T
you have limited options:
You could invoke get()
on your future, wait for it to be realised, then pass the realised value to the collaborators. This defeats the purpose of Future's, since what you really want is to do as much other work as possible before future.get()
is called.
Alternatively, you could modify the collaborators to know that they are dealing with a Future. But you don't really want to do that either - its an implementation detail that they should not be concerned with.
What you really want is to pass around implicit futures that hide the fact that the object is anything other than a pojo.
You can create implicit futures by wrapping an explicit future<T>
in an implementation of interface T
and delegating all of the methods to future.get().xxx()
. Here's what that might look like:
// the type expected by client code
interface ExpensiveToCompute {
public BigDecimal getValue1() throws Exception;
public BigInteger getValue2() throws Exception;
}
interface Computer {
public ExpensiveToCompute compute() throws Exception;
}
class SynchronousComputer {
public ExpensiveToCompute compute() throws Exception {
// ..
}
}
// the implicit future, delegating to an explicit future
class ImplicitFutureExpensiveToCompute implements ExpensiveToCompute {
private Future<ExpensiveToCompute> delegate;
public ImplicitFutureExpensiveToCompute(
Future<ExpensiveToCompute> aDelegate) {
delegate = aDelegate;
}
public BigDecimal getValue1() throws Exception {
delegate.get().getValue1();
}
public BigInteger getValue2() throws Exception {
delegate.get().getValue2();
}
}
// the async version that returns implicit futures
class AsynchronousComputer implements Computer {
private ExecutorService executor = ..;
private SynchronousComputer sync = ..;
public ExpensiveToCompute compute() throws Exception {
return new ImplicitFutureExpensiveToCompute(
executor.submit(new Callable<ExpensiveToCompute>() {
public ExpensiveToCompute call() {
return sync.compute();
}
}));
}
}
Pretty straight-forward, although there's quite a bit of boiler-plate, and i've passed the buck on exception handling.
This example is very simple, but things can get more involved if, for example, you want to use Future's overloaded get(long timeout, TimeUnit units)
and handle timeouts appropriately (say, by returning a default value).
What if, instead of all this, you could pass your current synchronous implementation through some machinery that converted appropriately annotated methods to run asynchronously and return implicit futures, without the chore of having to create those classes yourself?
It might look like this:
// the type expected by client code
interface ExpensiveToCompute {
public BigDecimal getValue1() throws Exception;
public BigInteger getValue2() throws Exception;
}
interface Computer {
@ComputationallyExpensive
public ExpensiveToCompute compute() throws Exception;
}
// the synchronous implementation - exact same as before
class SynchronousComputer implements Computer{
public ExpensiveToCompute compute() throws Exception {
// ..
}
}
// the async version, returning implicit futures
class AsynchronousComputer implements Computer {
private Computer async;
public AsynchronousComputer(
AsyncificationService anAsyncifier, Computer aDelegate) {
async = anAsyncifier.makeAsync(aDelegate);
}
public ExpensiveToCompute doSomething() {
return async.doSomething();
}
}
This time we didn't need to create the implicit future implementation, cutting a whole lot of boiler-plate, and the async implementation got a fair bit simpler too. We marked the expensive method with an annotation so that the AsyncificationService
knew to work its magic on that method.
There's a lot more useful stuff we can do when we have the machinery for converting synchronous methods to asynchronous methods that return implicit futures. For example we can transparently handle exceptions and return default values, or we can impose timeouts and return default values if we don't get a result in time, etc., etc.
If you want to see how we might implement such machinery, or want to try using it, fork the code for Implicit-Futures from github.
Comment on this post