JAX-RS Request Body Validation - rest

We are using JAX-RS to implement a REST API for one of our projects. Requirement is that the users would pass in the request object in JSON format.
Let us assume that we have a method that is invoked on hitting an API endpoint
#POST
#PATH("/api/user")
#Produces("application/json")
#Consumes("application/json")
public CustomResponse methodA(#RequestBody UserInfo userDTO)
Sample Request Object:
{
"firstName":"Test",
"lastName":"Name",
"sno":"A123"
}
UserInfo DTO
private String firstName;
private String lastName;
private String sno;
getters and setters
Now if the user tries to add other parameters to the request object given above (for ex: "age") and invokes api endpoint, we have not been able to intercept and report the same back to the user saying "Invalid parameter age" as it seems that the request is being filtered out for invalid/unknown parameters and not reporting any error as such.
Any thoughts on how this can be addressed?

I was able to identify unrecognized properties by adding following piece of code:
Change the method signature to
public CustomResponse methodA(#RequestBody String reqObj)
and then
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
UserInfo userDTO = mapper.readValue(reqObj, UserInfo.class);
We now see a
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "<>" for any unsupported parameter

Related

Liferay 7.2 Api Rest Session parameter

I have Liferay 7.2.
I created a module rest.
It is possibile to save a variable in session ad use it in other method?
My idea of code is:
#GET
#Path("/save/paramt")
public String jsonSaveParamRequest() throws Exception {
String json = "xx";
//SAVE IN SESSION json
return "ok";
}
#GET
#Path("/get/paramt")
public String jsonGetParamRequest() throws Exception {
String xx= SESSION VARIABLE json
return xx;
}
Saving state in a HTTP session in a REST API is not recommended and should be avoided. Please refer to the discussions here SO:how-to-understand-restful-api-is-stateless.
Technically, I guess this is possible as you can inject the HttpServletRequest as a method param via #Context HttpServletRequest request to your annotated method and use getSession(). But I am not sure if you can rely on that.

Need to pass email id in the request URL in Springs(RESTful webservice)

I need to pass email id in the request URI :
#RequestMapping(value = "/version2/auth/users/{userid}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
Example :
http://localhost:8081/myServices/version2/auth/users/me#myMail.com
I am getting the following exception:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not
find acceptable representation at
org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:234)
Can you please help me on this.
Thanks in advance.
I assume this method returns an object of some User class. Does your user class have the proper public getters and setters? Do you have the jackson libraries added?

ReSTful service getting contradict due to path parameter value has forward slash

I have API like this-
/objectname/name
/objectname/collection/id
Both API's are indirectly related.
Problem occurs when calling first API with name value as "A/B Type". So rest controller actually calling second API rather first (/objectname/A/B Type) because forward slash. How to deal with this situation.
As a side note I am encoding the parameters values.
I developed the restful services using SpringBoot and RestTemplate.
The conflict comes by specifying the name directly in the resource path and passed to the function as a #PathVariable.
Your code looks something like this:
#RequestMapping(value = "objectname/{name}", method = RequestMethod.GET)
public String yourMethodName(#PathVariable String name){
return name;
}
What I would recommend in order to avoid this kind of conflict is (if you're allowed to modify the #RestController or #RepositoryRestResource layers) to pass the value of the object in a #RequestParam
For instance:
#RequestMapping(value = "/objectname", method = RequestMethod.GET)
public String yourMethodName(#RequestParam(name = "name", required = true) String name){
return name;
}
That said, When you are constructing your the request using RestTemplate then you should url encode your name (A%2FB%20Testing) and construct the following url:
http://localhost:8080/objectname?name=A%2FB%20Testing
I tested this locally and worked alright for me.

#BeanParam gives exception A message body reader for Java class was not found

I am trying to make a jersey based web service. In this if i take input params using #FormParam it works fine:
#POST
#Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, "application/x-www-form-urlencoded"})
#Path("/registeruser")
public Response registerUser(#FormParam ("email") String email,#FormParam ("name") String name ){
System.out.println("Inside register device");
System.out.println("registered" + email);
return null;
}
but when I try using #BeanParam it does not works and gives me an exception
#POST
#Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, "application/x-www-form-urlencoded"})
#Path("/registeruser")
public Response registerUser(#BeanParam UserForm userForm ){
System.out.println("Inside register device");
service.registerUser(userForm);
System.out.println("registered" + userForm.getEmail());
return null;
}
A message body reader for Java class com.stc.dms.forms.UserForm, and Java type class com.stc.dms.forms.UserForm, and MIME media type application/octet-stream was not found.
You don't need to use #BeanParam to pass an object as input. Just pass it like this :
#POST
#Path("register")
#Consumes(MediaType.APPLICATION_JSON)
public Response registerUser(UserForm dto) {
// ...
}
Just make sure to include the libraries for producing/consuming json. If the client is in javascript you don't need anything else (just use JSON.stringify() on your form object), for the server add some json libraries such as Jackson
EDIT :
If you want to stick with #BeanParam, take a look at this tutorial here. Basically it seems that you don't need to specify the mediatype, as Jersey will handle that for you.

extracting the complete envelope xml from MessageContext

I have an interceptor like this:
public class WebServiceInterceptor extends EndpointInterceptorAdapter {
#Inject
private Jaxb2Marshaller myJaxb2Marshaller;
#Inject
private WebServiceHistoryDao webServiceHistoryDao;
#Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {
Source payloadSource = messageContext.getRequest().getPayloadSource();
Object unmarshaled = myJaxb2Marshaller.unmarshal(payloadSource);
//EXTRACT XML HERE
//is there a better way than this:
String extractedXml = myJaxb2Marshaller.marshal(unmarshaled);
return true;
}
}
How can i extract the whole xml of envelope (for logging purposes - to write it to the DB)
You don't need to write one, there's an existing one in the API - SoapEnvelopeLoggingInterceptor. See the javadoc.
SOAP-specific EndpointInterceptor that logs the complete request and response envelope of SoapMessage messages. By default, request, response and fault messages are logged, but this behaviour can be changed using the logRequest, logResponse, logFault properties.
If you only need to see the payload, rather than the entire SOAP envelope, then there's PayloadLoggingInterceptor.