Auto detection Jackson for Spring - java

I am working on a project that uses Spring framework and Jackson. However, I was not able to find a place, where it is being plugged. I looked at many examples on the web and most of them use bean of class org.springframework.http.converter.json.MappingJacksonHttpMessageConverter to allow deserialization of #ResponseBody.
So, I was not able to find any references to MappingJacksonHttpMessageConverter.
My question: Will spring framework automatically use Jackson if it will find it on its classpath to convert JSON into #ResponseBody object?
What are other ways how Jackson can be enabled?

If you wire up your spring project using #EnableWebMvc or via XML by using the tag <mvc:annotation-driven /> you enable a bunch of features. You can read the detailed list of features in the original Spring docs.
One of the features that are enabled is the support for #RequestBody method parameters and #ResponseBody method return values. This is done via the HttpMessageConverter component and the feature is enabled for methods that are annotated with #RequestMapping or #ExceptionHandler.
The following lists the converters that are registered by default:
ByteArrayHttpMessageConverter converts byte arrays.
StringHttpMessageConverter converts strings.
ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.
SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.
FormHttpMessageConverter converts form data to/from a MultiValueMap.
Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present on the classpath.
MappingJackson2HttpMessageConverter (or MappingJacksonHttpMessageConverter) converts to/from JSON — added if Jackson 2 (or Jackson) is present on the classpath.
AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.
RssChannelHttpMessageConverter converts RSS feeds — added if Rome is present on the classpath.
So, if you have a web enabled project with Jackson available on the classpath, Spring will automatically convert return values from a controller-method that is annotated with #ResponseBody (if the client caller accepts JSON that is which means that the accept header typically must be set to application/json).
If you wish to override the HttpMessageConverters you can implement the following:
#Configuration
#EnableWebMvc
public class YourConfiguration extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
// Do your magic, override your stuff
}
}
For a good introduction on how to customize e.g. the Jackson converter you can read this article from DZone about Customizing HttpMessageConverters with Spring Boot and Spring MVC.

Related

What's the difference between Converter and HandlerMethodArgumentResolver?

In Spring MVC, I can use PropertyEditor(Converter) or WebArgumentResolver(HandlerMethodArgumentResolver) to make customized command and form-backing objects. I'm puzzled which one should I use and what's the difference between them? Thanks a lot!
p.s. I know Converter and HandlerMethodArgumentResolver is recommended now. I've read the posts below:
Spring MVC type conversion : PropertyEditor or Converter?
Upgrading to spring-3.1 seems to break my CustomWebArgumentResolver
A converter simply converts between two different types. An HttpMessageConverter converts a request message having a defined media type to an instance of a defined class. Converters are usually called by argument resolvers.
An argument resolver provides a value for an argument. E.g. there is a resolver that creates the value based an a request parameter (#RequestParam) or one that converts the request body (#RequestBody). Both use converters.
But the value doesn't have to be related to the request. You could create a resolver that returns the current time, something like
public void foo(#CurrentTime Date) {

Respond to html, json and xml with Spring MVC content negotiation

All examples that I have found around internet were about to use content negotiation with json, xml etc. Is there any chance to have only one method producing all kind of contents, like:
#RequestMapping(produces={"text/html","application/json"})
public List<Product> list() {
return productDAO.list();
}
I tried to use the ContentNegotiationManager, but nothing worked for me.
One method can return responses of different content types. Some you can get with default settings, some you have to additionally configure. Take for example a following method, quite similar to yours,
#RequestMapping(value="/response", method=RequestMethod.GET, produces={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public #ResponseBody Foo multipleTypes() {
return new Foo();
}
this method is capable of returning both XML and JSON, even more Spring MVC will automatically configure the converters if you have JAXB2 and Jackson libs on the classpath.
When reasoning whether it will return an XML or JSON its where content negotiation comes to play. If the request is suffixed with a path e.g. /response.json or /response.xml the response will be set based on it. The resolution can be based on a parameter as well, so /response?format=xml. Finally, if the request has an Accept header set to XML or JSON a response will be converted to the respective type. This constitutes a PPA strategy (Path, Parameter, Accept).
In other words, if you provide a proper converter implementations and configure them properly (some are available out of the box), you can get a single method that returns different representations, that you can control based on the PPA strategy.
Content Negotiation Using Spring MVC is a great post on Spring's Blog site with working examples.

Generating json using spring-mvc

I tried to generate a json response earlier using spring-mvc (annotation) . After so may failure i find out some check point :
I need to add <mvc:annotation-driven/> in my servelet mapper. although i don't know the reason.
Then I need to add #ResponseBody annotation which should bound the return value as http response as the documentation says.
And I also need add some jacson dependency.
Did i missed something?
Now i have bunch of questions
why we have to add that in my servelet xml and how this whole process is working?
As json response is most commonly used when why spring need jackson dependency to generate json?
some days ago i was doing Struts2 generating json response there was much simple.
Is there any way to do it more easily in spring-mvc .?
At first you should understand that <mvc:annotation-driven/> annotation used for many cases not only for generating json response in Spring. This annotation allow to use different annotations in Spring mvc classes like:#NumberFormat #DateFormat #Controller #Valid and of course #ResponseBody.
To generate json response you just need #ResponseBody annotation in your controller or servlet and import libraries for processing JSON.
Recently java has oun set of APIs for processing JSON as part of Java EE 7 JSR 353 actually it has clean Oracle tutorial. Also you can use third party libraries like Jackson. To process (parse, generate, transform, and query) JSON text it's necessarily to have one of this libs.
You can learn about most popular third party libraries and their performance in this article
Here you can see simple example.
If you are using jacson you can do something like:
Your Model
public class Shop {
String name;
String staffName[];
}
Your Controller
#Controller
#RequestMapping("/shop/list")
public class JSONController {
#RequestMapping(value="{name}", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON(#PathVariable String name) {
Shop shop = new Shop();
shop.setName(name);
shop.setStaffName(new String[]{"mkyong1", "mkyong2"});
return shop;
}
}
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.example.mypackage" />
<mvc:annotation-driven />
Basically, you need check if:
Your Jackson library is existed in the project classpath
The mvc:annotation-driven is enabled
Return method annotated with #ResponseBody

REST, Spring with annotations, Jackson and handling of generic classes

I am trying to use Spring with Jackson to implement REST service using JSON as data interchange format. Now I have hit a road block with handling of generic classes in Jackson/Java. I am reading JacksonDataBinding page but I do not understand how I could use the information to help me with the issue when using Spring annotations. Given a basic response class like this, how do I make it work properly with Jackson and Spring together?
public class BasicResponseDto<ResponseDataType> {
private ResponseDataType data;
// ...
}

Spring MVC - Force a controller to produce MappingJacksonJsonView(s)

Here we have a basic webapp using JSP which needs to provide a few JSON based REST service URLs.
These urls will all reside under /services and be generated by a MyRestServicesController.
The examples I see for settings up JSON based views all use ContentNegotiatingViewResolver. But it seems like overkill to me as this resolver seems meant for situations where the same URL might produce different output.
I just want my one RestServicesController to always produce MappingJacksonJsonView(s).
Is there a cleaner, more straight forward way to simply direct the controller to do this?
Is there a cleaner, more straight forward way to simply direct the controller to do this?
Yes there is. You can have a look at this sample I posted in Spring forums. In short the way I prefer to do it is through the following.
ApplicationContext:
<!-- json view, capable of converting any POJO to json format -->
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
Controller
#RequestMapping("/service")
public ModelAndView getResultAsJson() {
Object jsonObj = // the java object which we want to convert to json
return new ModelAndView("jsonView", "result", jsonObj);
}
EDIT 2013: In these modern days, #skaffman's approach would be a nice alternative.
If all you need to do is output JSON, then the view layer itself is redundant. You can use the #ResponseBody annotation to instruct Spring to serialize your model directly, using Jackson. It requires less configuration than the MappingJacksonJsonView approach, and the code is less cluttered.
As long as you are using mvc:annotation-driven and Jackson is on the classpath then all you should need to do is use #ResponseBody on on your methods and the return type will be converted to JSON per Spring's standard HTTP Message Conversion functionality.
Also check out this video at around 37:00: Mastering Spring MVC.

Categories