I have a model class with an #XmlRootElement annotation. I want to know how I can receive it as a response in a function.
My model class:
#XmlRootElement
public class SurveyAnswers {
List<Long> Q_id;
Date date;
String SurveyType;
List<Answers> answers;
float versionid;
String mac;
String remarks;
// getter and setter here
}
I have previously used MultivaluedMap<String, String> for all my string based responses, but here it is a different structure to receive.
If your SurveyAnswers class is the only POST param then you can simply do like this:
#POST
#Path("/postpath")
#Consumes(MediaType.APPLICATION_JSON)
public Response handlePostRequest(SurveyAnswers surveyAnswers)
Follow this sample to learn more about consuming custom classes as the input params to jersey webservices:
http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/
Related
I have been given an OpenAPI yaml file and have used the maven openapi generator plugin to turn this into Java. This is being deployed to Weblogic 12.2.1.4 which should have Jersey 2.22 intalled.
This is largely working except for some UUID columns which are just coming through as null.
There is an API class
#Path("/jobtest")
public class JobTestAPI {
#POST
#Consumes({ "application/json" })
public Response jobTestNotification(#Valid #NotNull JobTestNotification jobTetNotification) {
return Response.ok().entity("OK").build();
}
}
and a data class
#JsonTypeName ("JobTestNotification")
public class JobTestNotification {
private #Valid UUID jobId;
private #Valid Date jobTimestamp;
private #Valid String jobDescription;
#JsonProperty("jobId")
#NotNull
public UUID getJobId() {
return jobId;
}
#JsonProperty("jobId")
public void setJobId(UUID jobId) {
this.jobId = jobId;
}
// Other getters / setters with same annotations
}
Sending
{
"jobId": "abcdef12-abcd-ef12-1234-abcdef123456",
"jobTimestamp": "2022-11-10T09:00:00.000Z",
"jobDescription": "Some description"
}
I am getting a bad request and adding in an ExceptionMapper I see it is complaining that the UUID is null. Indeed if I take out the #Valid annotation on the API method and print out the object I can see the other two values are there but the UUID field is null.
If I change the datatype of jobId to String it works.
My understanding is that as UUID implements a static fromString method there is no need for a custom converter (and indeed trying to implement one didn't seem to work).
Why are these fields not being mapped through (I have treble checked they are being passed with correct names and are definitely there)? Other than just changing the values to String what can I do to get this work
I have a Spring Boot application with Jackson to process JSON, and I am using Retrofit2 to make HTTP requests. I would like to send body parameters with the name set in the #JsonProperty annotation:
public class OAuthTokenRequest {
#JsonProperty("oauth_consumer_key")
private String consumerKey;
#JsonProperty("oauth_nonce")
private String nonce;
#JsonProperty("oauth_timestamp")
private Long timestamp;
...
}
And this would be the request:
#POST("/oauth-service/oauth/request_token")
Call<ResponseBody> getOauthToken(#Body OAuthTokenRequest request);
In this code fragment, I would like to send the parameters as named in the annotations (oauth_consumer_key, oauth_nonce, oauth_timestamp, etc.). However, the parameters are being sent like this:
Above your class add below annotaion
#JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class OAuthTokenRequest {
#JsonProperty("oauth_consumer_key")
private String consumerKey;
#JsonProperty("oauth_nonce")
private String nonce;
#JsonProperty("oauth_timestamp")
private Long timestamp;
...
}
It's pretty like params in #RequestMapping annotation, which narrows down the matching methods with query parameters. Instead, I want to achieve this with body parameters (like JSON-format). Do I need to implement a custom #RequestMapping annotation?
YOu can achieve it using #RequestBody. It matches payload with names specified in code.
https://www.baeldung.com/spring-request-response-body
You just have to use #RequestBody. Note that this not only allows POJO, you can use it with a Map too.
With a POJO:
#RequestMapping(value="/",method = RequestMethod.POST)
public String doSomething(#RequestBody MyDto dto) {
return service.requestOTP(dto.getField1(), dto.getField2());
}
With a Map:
#RequestMapping(value="/",method = RequestMethod.POST)
public String doSomething(#RequestBody Map<String, Object> body) {
return service.requestOTP(body.get("field1").toString(), body.get("field2").toString());
}
NOTE: If you would like to validate properties of an object used with #RequestBody, you can add #Valid annotation. For instance, the following will cascade the validation on the model and the models sub model fields(if found).
public class MyDto {
#NotNull
#Valid
private String field1;
private String field2;
//getters and setters
}
#RequestMapping(value="/",method = RequestMethod.POST)
public String doSomething(**#Valid** #RequestBody MyDto dto) {
return service.requestOTP(dto.getField1(), dto.getField2());
}
Check here for a brave introduction for #Valid https://www.logicbig.com/tutorials/java-ee-tutorial/bean-validation/cascaded-validation.html
I'm using springfox-swagger2 and springfox-swagger-ui for autogenerated REST documentation.
Problem: any GET requests are documented just fine. But when it comes to POST requests, the request body parameter descriptions are not shown in the swagger ui. But why?
#RestController
public class PersonController {
#GetMapping
public PersonRsp findPerson(PersonDTO p) {
//this works just fine an shows the #ApiParam fields in documentation
}
#PostMapping
public PersonRsp updatePerson(#RequestBody PersonDTO p) {
//service logic
return rsp;
}
}
class PersonDTO {
#ApiParam(required = true, value = "the persons family name")
private String lastname;
private String firstname;
#ApiParam(value = "date of birth in format YYYY-MM-DD")
private Date dob;
}
Question: how can I get the #ApiParam annotation hints being show in the swagger-ui documentation?
Simple answer: it seems one has to use #ApiModelProperty("some description") for POST requests, and #ApiParam for GET requests.
I cannot seem to get this to work for me ,I have seen this in other posts and was hoping someone may be able to spot what im doing wrong.I am trying to get the body of a request to this rest api but cannot seem to pull back what i need and just get null in the string below.
#POST
#Path("/SetFeeds")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String setFeed(#PathParam("name")String name2, #QueryParam("name") String name,#Context UriInfo uriInfo){
MultivaluedMap<String,String> queryParams = uriInfo.getQueryParameters();
String query = uriInfo.getRequestUri().getQuery();
String response = queryParams.getFirst("name");
return response;
}
A method parameter to accept the body of the request should not be annotated with anything (except in few cases like individual form params and multipart). So to get the raw JSON, you could simply add a String parameter
public String setFeed(#PathParam("name")String name2,
#QueryParam("name") String name,
#Context UriInfo uriInfo,
String jsonBody){
Or if you want to do the more common thing and use POJOs (so you don't need to parse the JSON yourself), you should look at this answer
Great answer, but I would like to add that you can use an object instead of a String and the Jackson of REST will take care the transformation without any further definition.
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String setFeed(#PathParam("name")String name2,
#QueryParam("name") String name,
MyJson json,
#Context UriInfo uriInfo){
MultivaluedMap<String,String> queryParams = uriInfo.getQueryParameters();
String query = uriInfo.getRequestUri().getQuery();
String response = queryParams.getFirst("name");
return response;
and a pojo as a json object:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyJson{
private String name;
public MyJson(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}