Working with custom annotations in the Spring Boot app - java

I got the response body from the HttpServletResponse with ContentCachingResponseWrapper used.
Now, I introduced custom annotations for the entities fields in my app and I need response body returned without the fields that I have annotated.
I do not want to affect my application behavior.
For example:
#Entity
public class User implements Serializable{
....
#Column
private String firstname;
#MyCustomAnnotation
#Column
private String lastname;
...
The real response body for the client should look like:
{"firstname":"John", "lastname":"Smith"}
And response body that I need for my later work is:
{"firstname":"John", "lastname":"MyCustomAnnotation"}
or
{"firstname":"John"}
or similar.
I was wondering if it is possible to do such a thing? Can I get one version of the response(filtered) and send client real version of the response?
I would like to avoid changing of the application code (methods in the controllers, model etc.), if it's possible. I would like to do all my work in the class where I am dealing with the HttpServletResponse.

What you probably need are json views, or if you simply want to ignore a field in your response - then #JsonIgnore

Related

Converting Request body to DTO with different fields structure in Spring Web app

Spring Web works perfectly in scenarios when rest controller takes a custom object, entity or dto, as parameter of handler method. You just need to annotate it with #RequestBody annotation. But how can I handle cases when the object has different field names or structure? I.e. for request json like
{"name":"FirstName", "address" : { "city" : "Rome" }}
to 'flattened' structure like
class Person { private String name; private String city; }
Is it possible to create a custom converter like HttpConverter, but for specific controller handler method only?
I think the easies way is to make a DTO matching the structure of the incomming json so Spring can map the json to this DTO. Then you can map this DTO to your Person class in your controller.
If your mapping is simple it is easiest to just write the mapping yourself. If not you can use a mapping tool like https://github.com/mapstruct/mapstruct or http://modelmapper.org/.
Please let me know if this is usefull.

Hiding sensitive information in response

I am currently working in a project where I have a User model and am using a REST API to fetch a list of users. (I have more entities.)
User has a password field. I do not want to include the password field in the result. So I excluded it in the DTO. But when I want to create a User, I want to include the password in the request. So Spring MVC gets the User entity (not the DTO).
I don't think it is good to do so.... For example, I have Event model which is connected to user with a many-to-many relationship. I don't want that in the request. I want only the user. So what do you suggest me to do? Have another kind-of DTO?
Use #JsonIgnore with Access.WRITE_ONLY for getter methods only.
Example
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
If you are using Jackson to serialize your response objects, you can annotate the property in question with #JsonIgnore and it will not be included in the response.
public User {
private String email;
#JsonIgnore
private String password
...getters and setters
}
It might also be a good idea to create separate response objects that only include the fields you want in case you add sensitive fields down the road and forget to hide them. Likewise, you would also have separate request objects for creating users that would include a password field. Business entities, like a User, are probably best to use only internally, so you can control what information goes public.
To avoid using #JsonIgnore, you can use json-view library.
For example, in your controller you can do something like this:
At first, declare this in your controller variable:
private JsonResult json = JsonResult.instance();
And then use this method:
#RequestMapping("/get/{id}")
public void getUserById(#PathVariable(value = "id") long id) {
User user = usersService.findOne(id);
json.use(JsonView.with(user)
.onClass(User.class, Match.match()
.exclude("password").exclude("yetAnothertopSecretField")));
}
It returns JSON without excluded fields.
The JsonView and JsonResult classes are imported from the json-view library.
I'm tried this JsonProperty.Access.WRITE_ONLY and it's working with me.
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
Make the field 'password' as null while sending the response and Jackson will not show that in response. Don't remove it completely from the model class.

Restrict JSON attributes for #RequestBody

This may be a simple task, but I couldn't find a way to do it. Basically, I need to disallow some parameters at the time of using #RequestBody annotation in my controller.
Here is my model:
#Data
public class MyModel {
private int id;
private String name;
}
What I want to do is at the time of response, I want both of the properties to be serialized to JSON, but at the time of create or update, I prefer not to receive id as part of #RequestBody deserialization.
Right now, if I pass id in the JSON body, Spring initializes a MyModel object with its id set to the passed value.
Reason? The ID cannot be generated until the model is created, so the app shouldn't allow the ID to be set. On update, the ID needs to be passed in the URL itself e.g. (PUT /mymodels/43). This helps following the REST principles appropriately.
So, is there any way to achieve this functionality?
Update 1:
Right now, I am stuck with using a request wrapper. I created a new class MyModelRequestWrapper with only name as its property, and have used it with the #RequestBody annotation.
How you do this depends on what version of Jackson you are using. It's basically possible by a combination of the annotations #JsonIgnore and #JsonProperty on relevant fields/getters/setters.
Have a look at the answers here: Only using #JsonIgnore during serialization, but not deserialization

How to send inherited Object with JSON in Spring Controller?

I work with Hibernate and everything is fine except this case. If I have class and inherited classes , when I send Object like that with JSON in Spring Controller , always I get error 400 BadRequest.
All fields are circulated well and everything is stored well if I send an object that is not a subclass.
This is exmp.:
#Entity
#javax.persistence.Table(name="person")
#Inheritance(strategy=InheritanceType.JOINED)
public class Person{
#Id
#GeneratedValue
#Column(name="id_person")
protected int id_person;
.....
#Entity
#javax.persistence.Table(name="client")
#PrimaryKeyJoinColumn(name="id_person")
public class Client extends Person{
#Column(name="address")
protected String address;
....
#Entity
#javax.persistence.Table(name="individual")
#PrimaryKeyJoinColumn(name="id_person")
public class Individual extends Client {
#Column(name="personal_number")
protected String personalNumber;
.....
My method inController:
#RequestMapping(value="/individualPerson", method=RequestMethod.POST)
public ResponseEntity<List<Individual>> posttest(HttpServletRequest request, HttpServletResponse response, #RequestBody Individual indiv)
Do I need some additional annotations or settings when I send inherited objects?
Also, Hibernate is automatically created all the tables with a primary key that is annotated in these classes.
If you use JSON format, Jackson library by default doesn't need any special annotations. Spring supports it out of the box, so generally you don't need to specify anything else than:
#RequestMapping(value="/individualPerson", method=RequestMethod.POST, produces="application/json")
Other option is to rely on HTTP content negotiation, which is supported by Spring and don't specify any format in produces attribute
You would make two changes if you have Jackson library in your path:
Mark #ResponseBody annotation on the method or on the return type.
Add produces property set to org.springframework.http.MediaType.APPLICATION_JSON on #RequestMapping

Dropwizard returns 400 on valid GET

I'm developing a Dropwizard app and am facing a strange bug on a GET request after I have included mongojack.
I have a simple GET query with the ID as a path parameter. It worked before I included mongojack and added two annotations to my entity:
public class Bill {
#javax.persistence.Id #org.mongojack.ObjectId
private String id;
#javax.persistence.Id #org.mongojack.ObjectId
public String getId() { return id; }
//...
}
What puzzles me most is that the request is actually accepted. When I debug, I can step into the method. The entity is loaded from MongoDB into memory and looks fine. So I suspect that this might actually be serialization issue, but currently I'm stuck. Any ideas?
Update
Seems to be a known mongojack issue: https://github.com/devbliss/mongojack/issues/26. Later I want to use custom DTOs without ObjectIds for my GETs anyway, so this shouldn't be relevant anymore. What I still don't understand is why Dropwizard maps this to a 400 response...
What I still don't understand is why Dropwizard maps this to a 400 response
Dropwizard, via Jackson, generates JSON using all the getters (or #JsonProperty annotated fields/methods) as you know. If any exception occurs on getters (or setters on deserialization) dropwizard automatically returns 400 Bad Request.
I guess that makes sense since it expects simple POJO DTOs with dumb getters and setters.

Categories