I have a Java Spring API which expects 2 params, a simple String and a object:
#RequestMapping(value = "list", method = RequestMethod.GET)
public ResponseEntity<ListResource> getList(#RequestParam("agentName") String agentName,
#RequestParam("paginationInfo") PaginationInfoList paginationInfo {
//After http request i expect to have here my java Object PaginationInfoList ready to use
}
I'm, trying to send http GET request with Postman but i get this error, then i suppose that i'm not sending the data object "paginationInfo" in the correct way.
"Failed to convert value of type 'java.lang.String' to required type 'com.pippo.prova.test.model.in.PaginationInfoList'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.pippo.prova.test.model.in.PaginationInfoList': no matching editors or conversion strategy found"
Since i can't change the way of sending, infact must be GET and i have to use #ReuqestParam, i don't know how to send json data in postman parameters. I'm trying this and also other options but i always get error.
You can bind The request params to an object. In postman you will have 3 params ("agentName", "pageSize" and "pageNumber") and your controller will receive 2 objects
public ResponseEntity<ListResource> getList(#RequestParam("agentName") String agentName,
#Valid PaginationInfoList paginationInfo)
http://dolszewski.com/spring/how-to-bind-requestparam-to-object/
Related
I am calling an external API (on which I do not have a control to make any change) using Spring's RestTemplate. The API returns response with an array as response body if the results are found and if not it returns response with String as response body stating "No records found". I am getting an exception when I am getting the no company found message because I typecasted the RestTemplate call to the custom object
ResponseEntity<Student[]> studentDetails = restTemplate.getForEntity(studentUrl, Student[].class);
The above code throws exception when the API returns String message "No records found".
What is the best way to deal with such a scenario?
In that case, you probably may use it like that
ResponseEntity<Object> studentDetails = restTemplate.getForEntity(studentUrl, Object.class);
And then check for the response type and cast the result.
I have a REST service:
#POST
#Path("/shop/{prodID}/{price}")
public Response updatePrice(#PathParam("prodID") Long prodID, #PathParam("price") Double price) {
priceDAO.updatePrice(prodID, price);
return Response.ok().build();
}
If i send number for UI they work great, but if a send empty param (null) I have error:
sitesurl/shop/33/null 404 Not Found
and
Class java.lang.Double can not be instantiated using a constructor with a single String argument
on console.
If null sending as string ("null") we could see NumberFormatException.
Why my service can not parse nullable PathParam?
chrylis if you dont provide any of the path params it would throw a 404 resource not found,
I Agree with Chrylis form param would be a good idea.
Gene then you should ensure while sending the request path params are not null and complying to the resource specifications. for a Long or a double string should not be sent.
Another way of getting rid is you keep the resource spec as String, and manually cast to Long etc..
There is way to handle ParamExcption well. Create a Mapper that implements ExceptionMapper and throw your custom response
I am using Spring MVC for a Rest API and am trying to call the following method on the controller:
#RequestMapping(method=RequestMethod.POST, value=IApiVersion.VERSION_ALL_PREFIX + ORG_RESPONSE_PAUSE_WRITES_URL)
public #ResponseBody Boolean setResponsePauseWrites(#RequestParam List<Long> orgIds, #RequestParam boolean pauseWrites){
validateDatabusClient();
organizationService.setPauseResponseWrites(orgIds, pauseWrites);
return Boolean.TRUE;
}
I am using Spring's RestTemplate to submit the request like this:
#Override
public void setPauseWrites(List<Long> orgIds, boolean pauseWrites){
String orgIdString = StringUtils.collectionToCommaDelimitedString(orgIds);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("orgIds", orgIdString);
parameters.add("pauseWrites", Boolean.toString(pauseWrites));
restTemplate.postForObject(orgResponsePauseWritesURL, parameters, Boolean.class);
}
This works fine and all, but I would prefer to not need to convert the list of orgIds to a comma delimited string. I am frustrated because the spring mvc controller has no problem converting the strings back to the parameters it is expecting, List and boolean. I would expect the RestTemplate to have a built in message converter to handle basic java classes like List and Boolean.
When I try this code:
#Override
public void setPauseWrites(List<Long> orgIds, boolean pauseWrites){
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
parameters.add("orgIds", orgIds);
parameters.add("pauseWrites", Boolean.valueOf(pauseWrites));
restTemplate.postForObject(orgResponsePauseWritesURL, parameters, Boolean.class);
}
I get the following exception message:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.ArrayList]
What is my best option? I am planning on continuing to convert the parameters to Strings for the rest template call for now, but I would like to know if there is a MessageConverter I can add to my RestTemplate to make this work. Currently I am just using the default MessageConverters. I have tried adding the MappingJacksonMessageConverter and changing my content type header to support json, but I get the same results.
Thank you.
A message converter does not just deal with the Java type (such as Boolean) that is of interest to a Java programmer. Its job is to covert Java objects to and from a byte stream representation that has a format that is identified by a media type name. Spring is only ever going to provide media converters for widely used media types. There is no widely used media type for a list of arbitrary Java objects; how could there be? As for a list of integers; I doubt there will ever be such a type, ironically, because it is just a bit too simple. The TSV (tab separated values) media type is a simple type that can represent a simple list of integers.
So, yes, you will have to write your own converter.
I'm trying to use the InMemoryClientExecutor to call services on my local JVM which return javax.ws.rs.core.Response objects. I can get this to work but only by specifying the String type like so:
String response = new ClientRequest("/myService", executor)
.get(String.class)
.getEntity();
Since the signature of the service is like so:
#GET
#Path("/myService")
public Response getSomeData(#Form MyFormBean bean) {
//...blah...
}
However I would like to get the actual Response objects back so that I can get the entities out and return those objects in my new "aggregate" response. When I just return the string the Jackson Parser doesn't see this as JSON, just a regular string so it does things like encoding line breaks into \n, etc.
Whenever I do something like:
String response = new ClientRequest("/myService",executor)
.get(Response.class)
.getEntity();
or even this to just get the plain request object:
String response = new ClientRequest("/myService", executor).get().getEntity();
I get the following Exception:
Exception Occured: org.jboss.resteasy.client.ClientResponseFailure: Unable to find a MessageBodyReader of content-type application/json and type null
at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:523)
at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:514)
at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:415)
at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:377)
at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:338)
Also present further down is:
Servlet.service() for servlet Resteasy threw exception: org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.servlet.http.HttpServletRequest
at org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy.invoke(ContextParameterInjector.java:56)
at $Proxy210.getScheme(Unknown Source)
Where am I going wrong?
There is no Response object being returned from the server, just a data stream that, in your case, is the representation of some entity, in JSON format. Trying to deserialize this data back into a Response object on the client side will not work, because effectively you are saying the JSON represents a Response object, which it doesn't (it represents the entity that *used to be contained in the Response).
Good news is, there are other ways to obtain the entity, which do not require trying to back-spin it into a Response. You will need to have the entities on the classpath of your client:
MyEntity response = new ClientRequest("/myService", executor)
.get(MyEntity.class)
.getEntity();
Replace MyEntity with the type of the actual entity you are expecting to receive.
I am using cxf as a webservice.It supports xml and json format output of the requested data.I want to know that if some exception has occured in my code then i want to return him back the error code either in xml or json format.But i dont know when to give json and xml ,it depends on the requested url that user has asked.
example
#Path("/reports/ad-view/loginId/{loginId}/publisher/")
PublisherReports getPublisherReportsAdView(
#PathParam("loginId") String loginId,
#QueryParam("fromDate") String fromDate,
#QueryParam("toDate") String toDate,
#QueryParam("filterValue") String filterValue);
If you mean you want to detect the mime type used to make the request, then you can use the #Consumes annotation to dictate which method handles which type of request. So you could write:
// Called when an XML request is made
#Path("/reports/ad-view/loginId/{loginId}/publisher/")
#Consumes("application/xml")
PublisherReports getPublisherReportsAdViewXml(...
and:
// Called when a JSON request is made
#Path("/reports/ad-view/loginId/{loginId}/publisher/")
#Consumes("application/json")
PublisherReports getPublisherReportsAdViewJson(...
Then have each variant of the getPublisherReportsAdView() method call a common method to perform the actual processing logic but still handle exceptions differently depending on the method that gets called.
An alternative approach, which doesn't require additional methods, would be to add a parameter which is annotated with the #HeaderParam annotation and use that to hold the value of the 'Content-Type' request header.
e.g.:
PublisherReports getPublisherReportsAdView(
#PathParam("loginId") String loginId,
#QueryParam("fromDate") String fromDate,
#QueryParam("toDate") String toDate,
#QueryParam("filterValue") String filterValue,
#HeaderParam("Content-Type") String contentType)
{
...
The value of contentType will likely also include charset information, for example: application/json; charset=UTF-8 so you'll need to ignore that when working out if the request contained JSON or XML.