I'm working with java project using spring REST.
My problem that i could not extract data from request body (which is json) after receive it as enitiy.
for example:
JSON Request Body
{
"firstname": "Rayan",
"lastname": "Cold",
"company_id": 23
}
My Controller maaped method is:
#PostMapping("/employee")
public Employee createEmployee(#RequestBody Employee employee) {
// Here i need to extract the company id from request body
// Long companyId = *something* // how i can extract from request ?
return companiesRepository.findById(companyId).map(company -> {
employee.setCompany(company);
return employeeRepository.save(employee);
}).orElseThrow(() -> new ResourceNotFoundException("Company not found"));
}
I know i can pass company ID as path variable. But i do want it in request body not in URI.
Thanks
company_id can not be mapped if your Employee class contains companyId.
I guess your company class like:
public class Employee {
private String firstname;
private String lastname;
private Long companyId;
//skip getter setter
}
change it to :
public class Employee {
private String firstname;
private String lastname;
#Transient
#JsonProperty("company_id")
private Long companyId;
//skip getter setter
}
You can simply take the company id from the object received:
employee.getCompany_id();
Please ensure, your Employee class should be something like below:
public class Employee
{
private String company_id;
private String lastname;
private String firstname;
// getter and setters of all these member fields
}
Name of the variables should be same as the one in JSON or use the
appropriate annotations.
Related
#Valid check is working for respective fields. Is there any way to reject requests if any unknown fields are present in JSON requestbody of POST/PUT requests.Below is my sample DTO class and controller.
For below sample request body (for example), the request should be rejected/throw exception.
Any help or suggestion would be appreciated.
{
"accountid" : "P12345",
"name" : "Cardiology",
"domain" : "Apollo"
}
public class Account {
#NotEmpty(message = "accountid is required")
private String accountid;
#NotEmpty(message = "name is required")
private String name;
//getters & setters
}
**********************************************************************************************
public class BeanController {
#PostMapping(path = "/accounts")
public ResponseEntity<?> getAllAccounts(#RequestBody #Valid Account account) {
System.out.println("::: Account is " + account + " :::");
return ResponseEntity.ok().body("SUCCESS");
}
}
You can do it by using #JsonIgnoreProperties.
#JsonIgnoreProperties(ignoreUnknown = false)
public class Account {
#NotEmpty(message = "accountid is required")
private String accountid;
#NotEmpty(message = "name is required")
private String name;
//getters & setters
}
Add below properties in application.yml to working in spring-boot latest version.
spring:
jackson:
deserialization:
fail-on-unknown-properties: true
How to mention "Required" and "Optional" fields in the Response class of Retrofit2. In my case this is the response of API call
Json Class:
{
"id":"133544", //Required
"name":"abcd" //Optional
}
ModelClass :
public class User {
#SerializedName("id")
private String id;
#SerializedName("name")
private String name;
public String getId() {
return id;
}
public String getName() {
return name;
}
}
How to differentiate the required and optional fields here?
Gson will set your serialized fields value to null. In your example if the JSON response you are getting does not include a field name, the resulting POJO will have null for the name.
I didn't have this problem before, with other POJOs, I'm not sure what's different this time, but I can't get this working and I could not find an exact solution for this.
I have this POJO called Component (with some Hibernate annotations):
#Entity
#Table(name="component", uniqueConstraints={#UniqueConstraint(
columnNames = {"name", "component_type"})})
public class Component {
#Column(name="id")
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="name")
private String name;
#Column(name="component_type")
private String componentType;
#Column(name="serial_number")
private int serialNumber;
#Column(name="active_since")
private String activeSince;
#Embedded
private ComponentWearoutModel wearout;
public Component() {
}
public Component(String name, String componentType, int serialNumber, String activeSince,
ComponentWearoutModel wearout) {
this.name = name;
this.componentType = componentType;
this.serialNumber = serialNumber;
this.activeSince = activeSince;
this.wearout = wearout;
}
public ComponentWearoutModel getModel() {
return wearout;
}
public void setModel(ComponentWearoutModel wearout) {
this.wearout = wearout;
}
//more getters and setters
}
ComponentWearoutModel:
#Embeddable
public class ComponentWearoutModel {
private String componentType; //dont mind the stupid duplicate attribute
private Integer componentLifeExpectancy;
private Float componentWearOutLevel;
private Float actionThreshold;
public ComponentWearoutModel() {
}
public ComponentWearoutModel(String componentType, int componentLifeExpectancy, float componentWearOutLevel,
float actionThreshold) {
this.componentType = componentType;
this.componentLifeExpectancy = componentLifeExpectancy;
this.componentWearOutLevel = componentWearOutLevel;
this.actionThreshold = actionThreshold;
}
//getters and setters
}
The sample payload I use:
{
"name": "component name",
"componentType": "airfilter2",
"serialNumber": 573224,
"activeSince": "2016-04-10 17:38:41",
"wearout":
{
"componentType": "airfilter",
"componentLifeExpectancy": 1000,
"componentWearOutLevel": 0.24,
"actionThreshold": 0.2
}
}
And finally the resource class:
#Path("myresource")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
public class MyResource {
DatabaseManager dm = DatabaseManager.getInstance();
#PUT
#Path("Component")
public Response storeComponent(Component component){
System.out.println("reached");
System.out.println(component.getComponentType()); //okay
System.out.println(component.getModel().getComponentType()); //nullpointerexception
ComponentWearoutModel model = new ComponentWearoutModel("type", 1000, 1f, 0.2f);
component.setModel(model); //this way it's saved in the db just fine
dm.save(component);
return Response.status(Status.OK).entity(component).build();
}
}
Without the prints, only the fields which are not part of the ComponentWearoutModel class are stored in the database table, the other columns are null. So when I try to print one of them, I get an exception, I just dont understand why. If I create a ComponentWearoutModel in the resource method and add it to the component, everything is fine in the database.
UPDATE:
so my mistake was that I named the ComponentWearoutModel attribute as "wearout" in the Component.class, but the autogenerated getters and setter were called getModel/setModel and moxy could not parse my payload because of this. Solution: change the attribute name to "model" in Component class and in payload too.
Please ensure that the attribute names you are using in the POJO are same as what are being sent in the json string.
Since there are no jackson etc annotations being used in your POJO to tell it the corresponding json mapping, the underlying code will directly use the names given in json string. If you are using the string "model", the convertor code will look for a "setModel" method in your POJO.
In the above example, either call everything "model", or "wearable".
I am using drop wizard which uses Jackson for returning classes as JSON.
How can I return only certain properties in a class as JSON rather than returning all the properties.
For example the User POJO
public class User {
private int id;
private String username;
private String password
//getter setters
}
and the signin path:
#GET
#Path("/signin")
public User signin(#Auth User user) {
return user;
}
returns {"password":null,"id":0,"username":"foobar"} How can I only return {"username":"foobar"}
You can annotate the field or getter/setter with
#JsonIgnore
Or annotate the class with
#JsonIgnoreProperties(value = {"password", "id"})
I need to receive a list of JSON entity as input to my WS.
Here my entity definition:
#XmlRootElement
public class ContactClass {
public String action;
public Long userId;
public String phone;
public String fbId;
}
here my WS function definition:
#PUT
#Path("/{userId}/adBook")
public String synchAdBookContacts(#PathParam("userId") Long userId, ArrayList<ContactClass> contacts)
Removing ArrayList<> It works fine, but I need an array of ContactClass as input.
Can you help me please?
Thank you!
Update:
Finally I found the solution, here the article that have solved my issue:
https://blogs.oracle.com/japod/entry/missing_brackets_at_json_one
Bean 1:
#XmlRootElement
public class Contact {
private String name;
private String phoneNumber;
// Getters, setters, default constructor
}
Bean 2:
#XmlRootElement
public class Contacts {
private List<Contact> contacts;
//Getter for contacts
#XMLElement(name = "listContacts")
public List<Contact> getContacts() {
....
// Getters, setters, default constructor
}
You Json fiel should have the following format:
"listContacts":[{"json for contact1"},{"json for contact2"},{"json for contact3"}...]
Your Resource:
#PUT
#Path("/{userId}/adBook")
public String synchAdBookContacts(#PathParam("userId") Long userId, Contacts contacts) {
//Here you can get your contacts contacts.
Deserializing to a list should work just fine. The following code works with RESTeasy + Jackson:
Bean:
#XmlRootElement
public class Contact implements Serializable {
private static final long serialVersionUID = 2075967128376374506L;
private String name;
private String phoneNumber;
// Getters, setters, default constructor
}
Resource:
#Path("/othertest")
public class AnotherTestResource {
#POST
#Path("/list/{id}")
#Produces("application/json")
#Consumes("application/json")
public Response requestWithList(#PathParam("id") String id,
List<Contact> contacts) {
return Response.ok("Hello World: " + contacts.size()).build();
}
}
Annotating your synchAdBookContacts method with #Consumes("application/json") should do it. Which JAX-RS implementation are you using and what error are you exactly getting?