Why do we need jackson databind? - spring

I am new in Spring MVC. My question is, why do we need jackson databind? Because We can receive the Request Params by #ModelAttribute and requests through http PUT or POST by #RequestBody. I can't find a reason why we need jackson databind to convert json/xml to POJO or vice versa.
Thanks.

Why do we need jackson databind?
Because representing structured data is much easier using XML (or JSON) than using simple name-value pairs.
Because it is more convenient to send and receive JSON from the client side when you are doing AJAX.
Because once you have to deal with sending and receiving JSON or XML in the server side Java app, it is more convenient to deal with structured data as POJOs.
None of the above points mean you have to use a binding. There are other ways of dealing with each of the above. But many Java developers think that data bindings the better way to go: more efficient in terms of developer time, and more reliable. Especially if you are implementing services with a complex APIs. That's why they are popular.
And as other answers/comments point out, if you are using #RequestBody, then that is using a binding library under the hood to give you the POJOs. In the case of Spring, it is Jackson that is being used.

By default, when an endpoint expects a JSON document as input and a given controller method argument is annotated with #RequestBody, Spring will use Jackson databind features to map the incoming JSON document to a Java object. You don't need to use the Jackson's ObjectMapper directly, as Spring does it for you.
For example purposes, consider the following HTTP request to create a comment:
POST /comments HTTP/1.1
Host: example.org
Content-Type: application/json
{
"content": "Lorem ipsum"
}
And the following class which represents a comment:
#Data
public class Comment {
private String content;
}
A #RestController to handle such request would be like:
#RestController
#RequestMapping("/comments")
public class CommentController {
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Foo> createComment(#RequestBody Comment comment) {
// By default, Spring will rely on Jackson databind to map the incoming
// JSON document to the comment argument annotated with #RequestBody
...
}
}
If you are interested in the Spring component that maps the incoming JSON document to a Java object, have a look at the MappingJackson2HttpMessageConverter class:
Implementation of HttpMessageConverter that can read and write JSON using Jackson 2.x's ObjectMapper.
This converter can be used to bind to typed beans, or untyped HashMap instances.
By default, this converter supports application/json and application/*+json with UTF-8 character set. [...]
If you are creating a HTTP API and exposing resources that can be manipulated with JSON representations, it's unlikely you'll use #ModelAtribute. Such annotation is particularly useful when you are dealing with web views.

When you get some request in some data types like json/xml, the Spring MVC platform will try to deserialize this request attributes in some model object of your project.
But the platform itself don't provide a des-serialize implementation out of the box. So it will try to use some des-serializer provider in the classpath like jackson, jersey, gson, etc.
As you said - is possible to use #ModelAttribute - but this annotation is a better option to a request from a form view in the front-end. In cases rest json/xml requests, the #ModelAttribute won't be able to convert correctly the received data to a business class of your program.

Related

Bean Validation for POST requisition in JAX-RS with Jersey implementation

I'm using the Jersey implementation for JAX-RS, and I was looking for an example where I can use the Bean Validation in POST requisitions. I have this operation, for example:
#POST
#Path("document/annotations/save")
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Map<String, Object> saveAnnotation(
#FormParam("user") String userStr,
#FormParam("documentId") String documentId,
#FormParam("documentPage") Integer documentPage,
#FormParam("annotationContent") String annotationContent,
#FormParam("annotationId") Long annotationId,
#FormParam("isMobile") Boolean isMobile) { // the code... }
I wanna use validations constraints (#NotNull, #Pattern, etc) for each method param. I saw this doc where they're using the Seam Framework to do that.
Currently, I'm trying to use the javax.validation implementation to validate my requests, but it doesn't working.
Is there a way to use the JSR-303 specification with JAX-RS?
Tnks.
This is currently not possible using Jersey; one possible alternative is to write a customer resource filter and bind to the #NotNull, etc. annotations.
It would be simpler if it was encapsulated in a resource class because you could then bind to a #Valid annotation on your method and validate the bean in one shot.
Because JSR-303 is designed to deal with beans and not a collection of parameters then it ends up being very verbose when you try to bend it to your will.
IMHO it's better not to keep validation inside your class anyway and to either use the pipes and filters pattern, i.e. ContainerRequestFilter, or to use something like AspectJ as #Willy suggested.
It's possible. See docs for latest Jersey
https://jersey.java.net/documentation/latest/bean-validation.html#d0e9380
https://jersey.java.net/documentation/latest/bean-validation.html

Spring MVC Rest: How to implement partial response in Json and XML?

I need to the ignore the serialization (JSon/Jackson and XML/XStream) of some attributes from my object response based on user input/or Spring security roles (like you don't have permission to see the content of this field, but all others are ok etc). How is the best approach to do this in Spring MVC Rest?
Other approach is show only the attributes that are relevant for the api user, like described here http://googlecode.blogspot.com.br/2010/03/making-apis-faster-introducing-partial.html
If you are using Jackson, here are some possible options to modify the Json serialization:
Use the #JsonIgnore annotation - However, this is static filtering, and will not allow you to implement rule-based filtering as you appear to need
Use #JsonFilter - This will allow you to implement an interface in which you can provide your serialization filtering logic. You may find this to be too heavyweight of a solution.
The way I often solve this is to return a Map from my Controller methods instead of the underlying object. You can write processing code that puts the relevant fields from the object into the Map, therefore giving you complete control over what is serialized. You could include a method on the Object to do the conversion. The method could look something like this:
// RequestObj is whatever 'input' object that indicates what should be filtered
public Map<String,Object> convertToMapForRequest(RequestObj request){
// Build return map based on 'this' and request
}

Jersey - data validation before sending entity object to REST api

I use Jersey framework to communicate (marshalling and unmarshalling object and xml) with REST api. I send data (object has lot attributes) this way:
.
.
ClientResponse response = webResource.type("application/xml").post(ClientResponse.class, object);
.
I would like to ask how can I validate some object attributes (for example private String code in Object should be in format of two numbers etc.)
aYou mean in the service that receives the object? How have you tried? It comes in as an object, or whatever you want it to come in as. We frequently take in Map<String,Object> and then do validation on that map (if we need to decide what subtype to create from the post for example). If you have Jersey unmarshall your request into the POJO for you, you can then do whatever validation you want and return a Response object with the validation error information to your client if the object doesn't pass.
So in other words, the validation is up to you. There are a few validation frameworks out there that you could try to help, such as javax.validation but IMHO it's usually easier to just test each property you need to validate yourself using conditionals, regexps, whatever.
In my opinion the validation comes with a webframework like struts, wicked, jfc... to name some. There the user inputs his data in a form to create the object he wants to post to a service. The webframeworks already got components to validate this data. When there was a positive validation you make the post call to your service.

Parsing a POJO to JSON using JAX-RS and not using any speific implemnation code

I was looking at internals of jersey, on how it converts a simple POJO to Json. Jersey has an interface Providers, which will provide list of contextResolvers given the class and mediaType. once we get the contextResolver, we can get the Context and Marshaller from it, which can used to get the json string, like show below.
lets assume we want to serialize the Pojo "obj". the code will look like follows
Providers ps = ...
ContextResolver<JAXBContext> resolver = ps.getContextResolver(obj.getClass(), MediaType.APPLICATION_JSON_TYPE);
JAXBContext ctx = resolver.getContext(obj.getClass());
ctx.createMarshaller().marshal(obj, writer);
By above way we can convery any POJO which has a valid context resolver to json. but the question is how do we get the handler for Providers.
PS: i have not compiled this code, but from what i can see from source this is what jersey does. On why i am doing all this stuff, so that we can convert a object to JSON directly with JAX-RS apis. instead of using any implementation code.
In a JAX-RS resource clas, use the #Context annotation to tell Jersey to inject the producers:
#Context Producers producers;
So your question is : "how to find providers" ?
You have to write code to find classes in the classpath which are Annotated with #Provider.

Handling JSON and form data request with Spring MVC

I'm working on simple Spring-MVC application and I love new Spring REST features. I'd like to use the same method to process regular form and JSON data. It seems to be a little tricky, however. For example, method
public #ResponseBody String process(#RequestBody Bean bean);
will work for JSON request (Content-type: application/json), and
public #ResponseBody String process(Bean bean);
will match request with Content-type: application/x-www-form-urlencoded.
These methods are obviously will have almost the same content, so I'd prefer to avoid such duplication. With Jersey it's possible with #Consumes annotations, but I can't figure out how to do it with Spring.
First, the above declaration won't compile, because you are having duplicate signature.
Btw, #Consumes wouldn't help, I think, because it only designates what content type the method can handle.
In spring you can specify the content-type with
#RequestMapping(headers="Content-Type=application/json")
Just add #RestController annotation for the controller class.

Resources