We are using Jersey, Jackson and Spring service (#service) annotation to expose some REST based Web-Services. Request and response data are exchanged in JSON Format.
Below is the Service Request Object content:
public class ServiceRequest{
private RequestHeader requestHeader;
private List<BaseEntity> requestData;
}
All specific entities will extend from BaseEntity class. For example :
public class User extends BaseEntity{
private String userName;
}
For all service operation we accept only ServiceRequest Object by passing list of request data objects. Now when we try to call these operation from REST Client, these are failing with
userName is not found as part of BaseEntity.
This is because while converting, Jersey/Jackson tries to autodetect the incoming field names with the specified object's property.
I want to know is there any way, I can handle this in an intelligent way. We do not have an option to change the signature of the Service. Really appreciate your help on this.
The below link has the answer for my question. Thank you for the support.
Polymorphism in jackson annotations: #JsonTypeInfo usage
Did you tried to use generics? You can declare concrete class type at Resource's to inform Jackson to map to specific type
Related
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.
In advance, I'm not speaking of Content Negotiation. Let's assume I've a simple JPA entity, by the way it is convertible with a related DTO it doesn't matter.
#Entity
public class User {
...
private String email;
private String password;
...
}
I've a RESTful controller with two different routes, a secured one and a public one.
#RestController
public class UserController {
...
#GetMapping("/public")
private User publicRoute() {
return service.getLatestUser();
}
#Secured("...")
#GetMapping("/private")
private User privateRoute() {
return service.getLatestUser();
}
}
For both routes the same entity is returned, but in the first case a public representation, let's say for a user profile, without sensitive stuff like E-Mail and Password should be returned. However in the second case a private representation, let's say for the owner itself, is required.
Is there any elegant way for doing this? I tried it on JSON level with #JsonIgnore but it doesn't worked for me. Also I tried to use Response-Objects, but it results in a lot of boilerplate code! Any suggestions?
See Also:
Recommended by Ananthapadmanabhan there already exists some questions/resources about this topic:
Spring REST webservice serializing to multiple JSON formats
How do I serialize using two different getters based on JsonView in RestController?
You could have different DTO objects being returned from the two endpoints instead of returning the same Entity class, that way you can have control over which attributes should be there in the response.
Read here about the advantages of using a DTO .
Another approach that you could make is to have custom serializers and deserializers for your endpoint.
You could read here for more details.
And here
Ignore dto fields while sending back to controller.
you can write you own method if your object is not final
private User ignoreEmailAndPass(User user){User usr=new User();usr.setName();//send only required fields.}
from Question:
In the database table you can have two roles
Say like User and Owner
3.In the service,check if it is user or owner and get the required details then have the
two DTOs,for each of their information that you want to send,set the info and return.
Or have a Common DTO, conataining all the information and when want to send user info just ignore the other info{Subset} else all.
Tell me what do you think of this solution?
How to change dependency in already deployed application. So when application starts it send notification through email, but at some moment we should be able to change to send notification through sms.
How to do that in Spring Boot?
thats a work for a strategy pattern, it does not have anything to do with spring itself
You should have 2 strategies one for email and one for sms, in each strategy you will autowired the needed bean.
check this link for strategy implementation
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
You can define a property in a Singleton bean? let's call it notificationMethod and assign by default EMAIL. (the property could be enum or string or int no matter).
You need a controller method to change the property.
#Autowired
private MyNotificationMethodHolderService service;
#RequestMapping(value = "/changeNotificationMethod")
#ResponseBody
public String change(#RequestParam("methodName") String methodName) {
service.setNotificationMethod (methodName);
}
Your notification service checks the property and sends notification according to the value (Strategy pattern according to comments).
If you need to change method you invoke
<HOST>:<PORT>/context/changeNotificationMethod?methodName=SMS
I'm building a straight forward AJAX / JSON web service with Spring. The common data flow is:
some DTO from browser
v
Spring #Controller method
v
Spring #Service method
I'm looking for the most easy way to handle data validation.
I know the #Valid annotation which works pretty well inside #Controller methods.
Why does #Valid not work within #Service methods?
I mean: A service method can be used by any other service and controller. So wouldn't it make much more sense to validate at #Service level?
Let's take this simple example:
MyDTO.java:
public class MyDTO {
#NotNull
public String required
#Min(18)
public int age;
}
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO) {
// persist myDTO
// and return created domain object
}
MyController.java:
#Autowired
MyService myService;
#Autowired // some simple bean mapper like Dozer or Orika
Mapper mapper; // for converting domain objects to DTO
#RequestMapping(...)
public MyDomainObjectDTO doSomething(#RequestBody MyDTO myDTO) {
mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class);
}
Is it common practice that the service method receives the DTO?
If yes: What's the best practice to validate that DTO inside the service method?
If no: Should maybe the controller manipulate the Domain object and just let the service save that object? (this seems pretty useless to me)
In my opinion the service should be responsible for only data consistency.
How do you solve this?
My answer? Both.
The service must check its own contract for validity.
The controller is part of the UI. It should validate and bind for a better user experience, but the service should not rely on it.
The service cannot know how it's being called. What if you wrap it as a REST service?
The service also knows about business logic violations in a way that no UI can. It needs to validate to make sure that the use case is fulfilled appropriately.
Double bag it; do both.
See my other answer: Check preconditions in Controller or Service layer
If you really want to do validation like error handling in your Service layer similar to Spring MVC you can use javax.validation and AspectJ (to advice the methods to validate) which is what I do because I like making reflection do the work and declarative programming (annotations).
Spring MVC doesn't need to do AspectJ/AOP to do the error handling because the methods are being called through reflection (url routing/dispatching).
Finally for you MVC code you should know that #Valid is sort of unofficially deprecated. Instead consider #Validated which will leverage more of the javax.validation features.
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