Overriding Spring Beans in a Servlet Context

A neat little trick I’ve recently picked up is the ability to override spring bean definitions in a web application, but inside the servlet context. I was always under the impression that only one spring application context was loaded for the entire web application, but in fact it appears that its actually loaded for each DispatcherServlet you have registered in your web.xml. I know, a slight oversight on my part. To be fair, most web apps I’ve worked with have only had one DispatcherServlet declared, so perhaps I can be forgiven for my short sighted ignorance 🙂

I’m definitely no Michealangelo when it comes to anything graphic, but here is a quick diagram illustrating what I’m going on about.

Illustration of how to override a spring bean definition to provide a custom bean for that Dispatcher Servlet application context.

The crux of this example lies in the web.xml.


<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/default-spring-context.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>spring-mvc-default</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring-mvc-default</servlet-name>
<url-pattern>/default/*</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>spring-mvc-custom</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/default-spring-context.xml,classpath:/dispatcher-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring-mvc-custom</servlet-name>
<url-pattern>/custom/*</url-pattern>
</servlet-mapping>

</web-app>

Notice how the spring-mvc-default has its contextConfigLocation init-param value set to nothing, leaving it up to the ContextLoaderListener to load it from the declared ContextParam declared in the beginning, and also how the spring-mvc-custom has it’s contextConfigLocation init-param value of set to the default and the dispatcher specific config file.

I’ve found this quite useful in some of the web apps I’ve been building where I need a specific type of bean to be injected instead of the default one declared. Something to also note here is that in each ServletContext(i.e. each DispatcherServlet definition), they cannot see the customised beans that are being used by any of the others. Each DispatcherServlet loads its own isolated Application Context.

Update: If you’d like top see this in action, albeit a very contrived example then head over to github here,

Advertisements

JSR303 + Spring MVC + Selective Validations

If you’ve ever been using the JSR 303 bean validation in Spring MVC, using the @Valid annotation inside your controllers, you’ve no doubt been frustrated somewhat by the lack of support for selective bean validation. What I mean by this is that in some cases(in reality most cases!) when you validate a bean, you want control over what gets validated and when.

In the past, one of the ways to overcome the @Valid running all of your validations was to either use different model objects or to whip up your own custom version of the @Valid annotation, which isn’t the cleanest way to go about it if you ask me. It’s just to open to errors.

Well thankfully, with Spring 3.1, there is now the introduction of the @Validated annotation which you can use in place of @Valid. We now have the opportunity to specify “groups” to validate. So typically, when you’re applying the bean validation to your model object, it would usually look something like this:

public class UserDTO {

@NotBlank(message = "Username must be supplied.", groups = {Default.class, MinimalUserValidation.class})
@Length(min = 6, message = "Username must be at least 6 characters long.")
private String username;

@NotBlank(message = "Password must be supplied.", groups = {Default.class, MinimalUserValidation.class})
private String password;
private String confirmPassword;

//Rest of class definition ommitted for brevity
}

Notice how on line 3 & 7, we have now specified the groups value, and have provided it with marker interfaces, declaring that these are the validations we’d like to have run when any one of these marker interfaces are mentioned within our @Validated annotation.

So, if we only wanted to run the MinmalUserValidation marked validations, then this is what your controller method would look like:


@RequestMapping(value="/add-user-partial.html", method = RequestMethod.POST)
public String createNewUserWithPartialValidation(@Validated(value = MinimalUserValidation.class) UserDTO userDTO, BindingResult bindingResult, Model model){
// Method body omitted for brevity
}

And thats all there is to it. I have a sample project on Github here if you want to check it out.

As a side note – For the curious amongst us, you’ll soon notice after digging around a bit on the constraint annotation interface (check out the javax.validation.constraints.AssertTrue for an example), you’ll see it includes a <code>payload</code> attribute. After a bit of google goodness, I came across this blog post which provided the answers I was looking for. 🙂

Different Responses with Spring REST

So lately I’ve been delving into Spring REST, and playing around with a few things, and something dawned on me which hadn’t occurred to me until I was actually messing around with a side project I have going on at home. Spring provides you the capability to return content in 2 different fashions:

  1. Either as a representation of the Model Object OR
  2. Either as the actual formatted content in the response body in whatever format(xml, json etc)

It’s important to draw the distinction between information being returned to you directly via the response body, and the model object. An example is probably in order.

Let’s say we have our standard Spring MVC project set up, and we have the controller class HomeController

@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value="/home", method=RequestMethod.GET)
public String home(ModelMap model) {
logger.info("Welcome home!");
model.addAttribute("attribute", "home-gerome");
return "home";
}
}

and the relevant xml for the spring configuration looks like this:

<bean id="xStreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true"/>
<!--<span class="hiddenSpellError" pre=""-->bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"/>
<property name="mediaTypes">
<map>
json" value="#{T(org.springframework.web.servlet.view.json.MappingJacksonJsonView).DEFAULT_CONTENT_TYPE}"/>
<entry key="xml" value="#{T(org.springframework.web.servlet.view.xml.MarshallingView).DEFAULT_CONTENT_TYPE}"/>
</map>

</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg name="marshaller" ref="xStreamMarshaller"/>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true"/>
</bean>

There’s nothing special about this configuration, its pretty standard, and I managed to gleam most of it off of the Spring documentation, and the API docs on the ContentNegotiatingViewResolver

Notice how there’s only a @RequestMapping annotation on the method, nothing else, and the ModelMap parameter being passed in. If you build your HTTP GET request ( I use an add-on called REST Client for Firefox), for the home.json resource, you’ll notice that the response body actually returns like this:

{"attribute":"home-gerome"}

No surprises here that is looks just like the content of the Model, with the key-value pair.

I’d just like to mention that if I made a request for home.html, instead of home.json, I’d actually get the HTML content of the home.jsp page in the response body, and there will be no trace of the ModelMap data here. This is purely down to the ViewResolver chaining where the ContentNegotiatingViewResolver wouldn’t be able to satisfy my request for my .html request, and would then move onto the 2nd ViewResolver I had configured which can. Seeing as though I made the request for home.json, the ContentNegotiatingViewReolver finds a class that can resolve a view for the request, and it uses the MappingJacksonJsonView to resolve the request and format a response, which looks at the ModelMap, to return data back to the calling client. Requests ending in .json, or .xml etc are preferred over the Accept Headers in the request, although this is also configurable in the ContentNegotiatingViewResolver.

Also, you’ll see I’ve added the property ignoreAcceptHeader=true, and I did that because of another “problem” I faced while working with HTTP requests and how Spring uses them to make certain choices, and subsequently learnt that HTTP Headers can be evil… but more on that in another post. So for now, I’ve actually set this property in my project to ignore Accept Headers for now, and just use the extensions on the request to determine how content should be delivered.

Now, having spring deliver content via the @ResponseBody opens up another can of worms. In fact, I was going to try and give you an example here, but after I finished I felt that this post actually ended up being way too massive so I’ll possibly address @ResponseBody use and configuration in an upcoming post. Suffice to say though, that although it is nice to have your objects returned directly via the response body when using the @ResponseBody annotation, doing so doesn’t come without its fair share of additional configuration and hacking about.

In chatting to some others who have used Spring REST, and all the goodness it offers, I’ve come to the conclusion that many are left with the question of when to use @ResponseBody as opposed to just the traditional way before @ResponseBody came onto the scene. From what I’ve seen so far, I’d make the decision based on the following

You have an existing Spring MVC website in place, and you want to make it deliver content in json and xml format.

Well, if this is the case, I’d avoid using @ResponseBody, and I’d just populate the ModelMap object with the content I want to send back to the client. The reason for this being that, I can still then make use of the view resolving that happens for me when I return a string to lookup the .jsp page and render that content back. However if I stick a @ResponseBody tag on my method, I’m effectively responsible for doing all of that myself, i.e. returning the actual content to the response, and I lose all that spring automagic that happened before. So for situations where you want to run your website and your REST requests/responses off of the same MVC controller, then I’d stay away from @ResponseBody.

Another good reason for avoiding the @ResponseBody, is that for GET requests, Spring doesn’t seem to be able to work out (yet) which formatter to correctly pick other than looking at the accept headers. When you use @ResponseBody, as part of the configuration, you’ll setup HTTPConverters responsible for formatting the content, and you’ll configure them to only listen for certain accept headers by populating the supportedMediaTypes property. As I’ve mentioned just previously, I’ve just recently learnt that when relying on browsers coming to your website, accept headers can be evil.. so stay away! 🙂

You don’t have to service browser requests, and will only be serving content to clients to have control the accept header.

If all you need is something that interacts with a representations of your domain objects, then I’d say go for the @ResponseBody annotation. Purely because clients are more than likely in control of setting things like HTTP headers, and when using @ResponseBody with GET requests especially, you have to add the headers property of the @ResponseBody annotation to tell spring which method to effectively call for which type or representation. So your controller would look something like this:

These are my experiences so fat while using @ResponseBody. I’ve only just started realising its benefits, but I think it needs to be said that if you;rethinking about using the @ResponseBody feature, think carefully about where, and how you want to use it, because it can give you more headaches than its worth.