Spring REST multiple #RequestBody parameters, possible? - java

I've implemented a Spring RESTful web service. Using Jackson JSON for Object Mapping. I have a method that accepts two parameters.
public Person createPerson(
#RequestBody UserContext userContext,
#RequestBody Person person)
How would the client construct a request where in multiple JSON objects are to be passed in the body?
Is this possible?
-- Sri

I'm pretty sure that won't work. There may be a workaround, but the much easier way would be to introduce a wrapper Object and change your signature:
public class PersonContext{
private UserContext userContext;
private Person person;
// getters and setters
}
public Person createPerson(#RequestBody PersonContext personContext)

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.

Working with custom annotations in the Spring Boot app

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

hibernate DTO with a deviant database

I am building a spring boot application which uses REST services to deliver content to the front-end
But my DTO does not correspond to my database.
Here is a diagram of the database
And my DTO should look something like this
public class GlobeEntity extends BaseEntity {
// for all definition years
private List<Instance> instances;
class Instance {
// CountryInstance.definitionYear
private String definitionYear;
// for all countries
private List<Country> countries;
class Country {
// Country.countryId
String id;
// Country.externalIdentifier
String externalIdentifier;
// CountryInstanceCompatibility.total
String com;
// CountryInstanceUtility.total
String uti;
}
}
}
Is this possible to do with hibernate annotations?
For the DTO, what is turned into JSON when you return that class from a controller depends on your JSON serializer you have configured in Spring. Then you make use of the JSON annotations to have more control over what is returned.
Depending on how you do things, you may just choose to convert between an entity and a DTO, and have a class for each. Although this is a bit annoying because it does add allot of overhead of having more classes and other classes depending on the two, it can be come a real real mess if you use the same class for both DTO and Entity representations when they are very different. For instance if you use a method in your controller, it's not clear wether this is an entity or a DTO. There are many cases when you have a controller you return a response which is not a resource in a database.

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

Categories