Use #RequestBody to map JSON to a class with #Builder - java

I am using #RequestBody to map JSON body of a POST request to my java class. My POST request was working fine initially, but when I add the #Builder annotation to my java class it started fail. I was wandering how I can use #RequestBody to map JSON to a class with #Builder annotation
My Controller Class
#RequestMapping(value = { "/cards/add" }, method = RequestMethod.POST)
public void addCard(final HttpServletResponse response, #RequestBody Card request) {
...
}
My Model Class
#Data
#Builder
public class Card {
private String Id;
...
}

Try adding these:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class Card {
private String Id;
...
}

Related

How can I make javax validation both of sub class and super class?

I'm using Spring framework,
and I faced the inheritance problem when I write Controller logic.
First of all,
this is my Controller code snippet
#PostMapping("/pay/detail")
public ResponseEntity<PayDetail.Response> getPayDetail(
#Valid PayDetail.Request payDetail
) {
... some code
}
and PayDetail class looks like this
public class PayDetail {
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public static class Request extends CommReqForm {
#NotNull(message = "Not null please")
private String work_type;
}
}
and CommReqForm
#Data
#AllArgsConstructor
#NoArgsConstructor
public class CommReqForm {
#NotEmpty(message = "servicecode not empty")
private String servicecode;
#NotEmpty(message = "reqtype not empty")
private String reqtype;
}
I wish that I can validate both of PayDetail.Request and CommReqForm classes but It makes validation just only PayDetail.Request class.
How can I solve this problem?
#Valid cannot validate super class. I want to make both of sub class and super class validation.

Validate DTO in Get mathod

I want to pass a DTO to Get method:
#GetMapping
public void my_get(MyDto myDto){
}
Above code work's correctly but validations on fields not worked.
#Data
#AllArgsConstructor
#NoArgsConstructor
public class MyDto {
#NotNull
#NotBlank(message = ValidateConstant.NOT_BLANK_MESSAGE)
String id;
String uri;
String type;
String version;
}
I'm also add #Valid annotation but also Get method return 200 in response.
add #Valid annotation
public void my_get(#Valid MyDto myDto){
if that does not help, add #Validated at the class level.

Why #Data and #Builder doesnt work together

I have this simple class
public class ErrorDetails {
private String param = null;
private String moreInfo = null;
private String reason = null;
...
}
After refactoring, I added #Data and #Builder, but all the instantiations doesn't work any more
ErrorDetails errorDetails = new ErrorDetails();
'ErrorDetails(java.lang.String, java.lang.String, java.lang.String)'
is not public in
'com.nordea.openbanking.payments.common.ndf.client.model.error.ErrorDetails'.
Cannot be accessed from outside package
If I removed #Builder, then it will work fine,
Why I cannot use #Data and #Builder together?
Lombok's #Builder must have #AllArgsConstructor in order to work
Adding also #AllArgsConstructor should do
Under the hood it build all fields using constructor with all fields
applying #Builder to a class is as if you added #AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the #Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself.
The full config should be :
#Data
#Builder(toBuilder = true)
#AllArgsConstructor
#NoArgsConstructor
class ErrorDetails {
private String param; // no need to initiate with null
private String moreInfo;
private String reason;
}

Deserialize JSON to polymorphic types Spring boot

I am working on an e-policy project where i need to save different types of policies. For simplicity i am considering only two types "LifeInsurance" and "AutoInsurance". What i want to achieve is if the JSON request to create policy contains "type":"AUTO_INSURANCE" then the request should be mapped to AutoInsurance.class likewise for LifeInsurance but currently in spring boot app the request is getting mapped to parent class Policy eliminating the specific request fields for auto/Life insurance. The domain model i have created is as below.
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#NoArgsConstructor
#Getter
#Setter
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include =
JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({ #Type(value = AutoInsurance.class, name = "AUTO_INSURANCE"),
#Type(value = LifeInsurance.class) })
public class Policy {
#Id
#GeneratedValue
private Long id;
private String policyNumber;
#Enumerated(EnumType.STRING)
private PolicyType policyType;
private String name;
}
My AutoInsurance class is below.
#Entity
#NoArgsConstructor
#Getter
#Setter
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonTypeName(value = "AUTO_INSURANCE")
public class AutoInsurance extends Policy {
#Id
#GeneratedValue
private Long id;
private String vehicleNumber;
private String model;
private String vehicleType;
private String vehicleName;
}
Below is LifeInsurance type child class
#Entity
#NoArgsConstructor
#Getter
#Setter
#JsonTypeName(value = "LIFE_INSURANCE")
public class LifeInsurance extends Policy {
#OneToMany(mappedBy = "policy")
private List<Dependents> dependents;
private String medicalIssues;
private String medication;
private String treatments;
}
To save the policy details, I am sending JSON request from UI with a "type" property indicating the type of insurance in the request.
When i run the below test method, JSON request gets mapped to the correct child class as required.
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper map = new ObjectMapper();
String s = "{\"id\": 1,\"policyNumber\": \"Aut-123\",\"type\": \"AUTO_INSURANCE\",\"policyType\": \"AUTO_INSURANCE\",\"name\": null,\"address\": null,\"contact\": null,\"agentNumber\": null,\"agentName\": null,\"issuedOn\": null,\"startDate\": null,\"endDate\": null,\"vehicleNumber\": \"HR\",\"model\": null,\"vehicleType\": \"SUV\",\"vehicleName\": null}";
Policy p = map.readValue(s, Policy.class);
System.out.println(p.getClass());
//SpringApplication.run(EPolicyApplication.class, args);
}
But when i run the same in Spring boot in a RESTController postmapping, I am getting a PArent class object instead of the child class object.
#RestController
#RequestMapping("/policy")
public class PolicyController {
#PostMapping
public void savePolicy(Policy policy) {
System.out.println(policy.getClass());
}
}
I can get the JSON as string, autowire objectmapper and parse manually but i want to understand if its a known issue and if anyone else has faced the same with Spring boot. I have searched for solutions on this but i got was solution to deserializing to polymorphic classes but nothing related to issue with Spring boot.
In your method you haven't annotated the Policy method argument with #RequestBody. Which leads to Spring creating just an instance of Policy instead of using Jackson to convert the request body.
#PostMapping
public void savePolicy(#RequestBody Policy policy) {
System.out.println(policy.getClass());
}
Adding the #RequestBody will make that Spring uses Jackson to deserialize the request body and with that your annotations/configuration will be effective.

How to automatically return JSON response from REST controller

I am creating a simple Rest web-service(using Spring-boot) and want to return JSON data everytime my web-service is invoked.
Here is my controller Class
#Controller
#RequestMapping("/order")
class A {
#RequestMapping(value = "/all", produces = MediaType.APPLICATION_JSON, method = RequestMethod.GET)
#ResponseBody
List getAllEntitites() {
List list = new ArrayList<>();
ARepository.findAll().iterator().forEachRemaining(list::add);
return list;
}
}
The Model That I am returning is something like
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "user")
public class User {
#Id
private int id;
private String userName;
private String mobile;
private String address;
}
When I invoke "localhost:8080/order/all" I am getting response as [{},{}] for 2 objects in list.
I want output something like this
[ {"id":100,"userName":"AA","mobile":"111111111","address":"India"} , ...]
I am puzzled as to what is going wrong here.
Any help appreciated!
Thanks!

Categories