Spring 4 brings several improvements for MVC applications. In this post I will focus on restful web services and try these improvements by taking a project implemented with Spring 3.2 and upgrading it to Spring 4. The following points sum up the content of this post:
The source code of the following projects can be found at github:
Original project (spring 3.2)
Migration to Spring 4
2 The Spring 3.2 RESTful sample
The starting project is implemented with Spring 3.2 (pom.xml) . It consists in a Spring MVC application that access a database to retrieve data about TV series. Let's have a look at its REST API to see it clearer:
This class is responsible of retrieving the data from a mongoDB database:
This controller will handle requests and interact with the service in order to retrieve series data:
These integration tests will test our controller within a mock Spring MVC environment. In this way, we will be able to also test the mappings of our handler methods. For this purpose, the MockMvc class becomes very useful. If you want to learn how to write tests of Spring MVC controllers I highly recommend the Spring MVC Test Tutorial series by Petri Kainulainen.
I'm showing some of the tests implemented. Check SeriesIntegrationTesting for complete implementation.
The application contains some functional testing by using the RestTemplate class. You need the webapp deployed in order to test this.
That's all, the web application is tested and running. Now is time to migrate to Spring 4.
3 Migrating to Spring 4
Check this page to read information about migrating from earlier versions of the Spring framework
3.1 Changing maven dependencies
This section explains which dependencies should be modified. You can take a look at the complete pom.xml here.
The first step is to change Spring dependencies version from 3.2.3.RELEASE to 4.0.0.RELEASE:
The next step is to update to Servlet 3.0 specification. This step is important since some of the Spring features are based on Servlet 3.0 and won't be available. In fact, trying to execute SeriesIntegrationTesting will result in a ClassNotFoundException due to this reason, which is also explained here.
3.2 Updating of Spring namespace
Don't forget to change the namespace of your spring configuration files:
Review the information page linked in section 2 since there are some changes regarding mvc namespace.
3.3 Deprecation of jackson libraries
If you check SeriesFunctionalTesting (setup method) again you will notice that the Jackson converter is now deprecated. If you try to run the test it will throw a NoSuchMethodError due to method change in Jackson libraries:
In Spring 4, support to Jackson 1.x has been deprecated in favor of Jackson v2. Let's change the old dependency:
Finally, if you are explicitly registering message converters you will need to change the deprecated class for the new version:
3.4 Migration complete
The migration is done. Now you can run the application and execute its tests. The next section will review some of the improvements I mentioned at the beginning of this post.
4 Spring 4 Web improvements
4.1 @ResponseBody and @RestController
If your REST API serves content in JSON or XML format, some of the API methods (annotated with @RequestMapping) will have its return type annotated with @ResponseBody. With this annotation present, the return type will be included into the response body. In Spring 4 we can simplify this in two ways:
Annotate the controller with @ResponseBody
This annotation can now be added on type level. In this way, the annotation is inherited and we are not forced to put this annotation in every method.
Annotate the controller with @RestController
This annotation simplifies the controller even more. If we check this annotation we will see that it is itself annotated with @Controller and @ResponseBody:
Including this annotation won't affect methods annotated with @ResponseEntity. The handler adapter looks up into a list of return value handlers in order to resolve who is capable of handling the response. The handler responsible of handling the ResponseEntity return type is asked before the ResponseBody type, so it will be used if ResponseEntity annotation is present at the method.
4.2 Asynchronous calls
Using the utility class RestTemplate for calling a RESTful service will block the thread until it receives a response. Spring 4 includes AsyncRestTemplate in order to execute asynchronous calls. Now you can make the call, continue doing other calculations and retrieve the response later.
Asynchronous calls with callback
Although the previous example makes an asynchronous call, the thread will block if we try to retrieve the response with futureEntity.get() if the response hasn't already been sent.
AsyncRestTemplate returns ListenableFuture, which extends Future and allows us to register a callback. The following example makes an asynchronous call and keeps going with its own tasks. When the service returns a response, it will be handled by the callback:
We took a Spring 3.2.x web application and migrated it to the new release of Spring 4.0.0. We also reviewed some of the improvements that can be applied to a Spring 4 web application.
I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.
Labels: Jackson, mongoDB, MVC, REST, Spring, Test