only Response entity shown in Postman - java

I have a response which produces #Produces(MediaType.APPLICATION_JSON) like this:
return Response.status(200).entity(product).entity("some message").build();
why postman shows me unexpected s in json view result and some message in xml view

For the Response.ResponseBuilder.entity(Object)` you can see
public abstract Response.ResponseBuilder entity(Object entity)
Set the response entity in the builder.
Any Java type instance for a response entity, that is supported by the runtime can be passed. It is the callers responsibility to wrap the actual entity with GenericEntity if preservation of its generic type is required. Note that the entity can be also set as an input stream.
A specific entity media type can be set using one of the type(...) methods.
Since you call this method twice, only the last value is saved.
Since "some message" is not at all a JSON syntax, it is saying that the s (from some) is unexpected, it is expecting a {

Related

Java Spring #ResponseBody return XML with produce attribute

Recently, I'm trying to get the xml file under the resources file. Then all the questions come out.
I read so many articles say something like:
#ResponseBody tells a controller that the object returned is
automatically serialized into JSON and passed back into the
HttpResponse object.
So my question is: the produces attribute is used to narrow the mapping by the media types that can be produced by the mapped handler, not to declare the media types the mapped handler will produce, right? Then how should I return xml content in the condition of automatically serialized into JSON format? I guess I mess up the meaning of the content showing in the view with HTTP response body... Please someone explain to me nicely and patiently :"(

How to call a rest API which returns object of two different types

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.

How can I determine the unerased type of a field?

I have a generic response wrapper class:
public class Response <T> {
T response;
}
and unrelated classes to be wrapped:
public class ServiceResponse {
String someField;
}
When I make a service request, I get a JSON response that looks something like:
{ "code":200, "response":{"someField":"some text"} }
Now, all my service responses have the same outer wrapper, i.e., they all have:
{ "code":200, "timestamp":"....", "response":... }
But the actual format/type of the response field is different for each service request. When I deserialize the response, I need to know the type of the response field so I can create the appropriate instance, if the deserialization was done within Response, I could use:
response = new T(jsonParser);
However, I'm doing all of this from within a library that is driven by reflection, so I normally deserialize the whole tree with code like:
wrapper = deserializer.parseObject(Response<ServiceResponse>.class)
but, at this point my parseObject method can't correctly determine the type of T.
I can use something like:
Response<ServiceResponse> response = new Response<>();
Field field = response.getClass().getDeclaredField("response");
Type type = field.getGenericType();
which then tells me that response is of type T but what I actually need is ServiceResponse
Per this SO question I tried casting as ParameterizedType but that would actually seem to apply to a field of type Response<ServiceResponse> and not the actual field within (and it fails because type can't be cast as ParameterizedType)
Is there any way to determine (at run time) the raw type of response?
Eventually, I may wind up having to create an annotation providing more details about how to deserialize the field, probably by providing a function to do it, but would prefer a more transparent approach.
Another possibility might be to actually assign a void instance of T to response at initialization time and then I could grab the actual type from that...
Check out this post:
http://mydailyjava.blogspot.com/2013/06/advanced-java-generics-retreiving.html
It's actually exactly what you're looking for.
According to this, you'll just need to extend your Response class and then query the generic type of its super.

How are MessageBodyReaders used

Given something like:
e.g.
class User{
String name;
String someField1;
}
#Consumes("some/media-type")
class ResourceA{
public Response test(#FormParam("u") User u, #FormParam("f) String someField){
}
}
Couple of questions:
Will a single MessageBodyReader used to de-serialize User or will each field in user be de-serialized by a different reader?
Is #context required on any/all of these?
Is #FormParam required on the fields in the User class?
I'm trying to understand if the server will take the list of readers available and for each param in test, check if ANY of the readers can de-serialize that type. Or if the first reader which matches the media type consumed is expected to de-serialize all the params.
If the server is iterating through each parameter and for each parameter finding the most appropriate reader, it kind of makes sense that the input stream being passed to readFrom is the same instance, and each reader is advancing through the input stream. Is this the case or am I totally misunderstanding how the MessageBodyReader is meant to be used?
Have a look at this documentation on how entity providers are selected. In particular:
Procedure 7.2. MessageBodyReader Selection Algorithm
Obtain the media type of the request. If the request does not contain
a Content-Type header then use application/octet-stream media type.
Identify the Java type of the parameter whose value will be mapped
from the entity body. The Java type on the server is the type of the
entity parameter of the resource method. On the client it is the Class
passed to readFrom method.
Select the set of available MessageBodyReader providers that
support the media type of the request.
Iterate through the selected MessageBodyReader classes and,
utilizing their isReadable method, choose the first
MessageBodyReader provider that supports the desired combination of
Java type/media type/annotations parameters.
If Step 4 locates a suitable MessageBodyReader, then use its
readFrom method to map the entity body to the desired Java type.
Otherwise, the server runtime MUST generate a NotSupportedException
(HTTP 415 status code) and no entity and the client runtime MUST
generate an instance of ProcessingException.
#Context is not required and #FormParam does not need to be added to your bean - just to the REST resource method.
It appears it works how I suspected.
Looking at the source for RESTEasy, the MethodInjectorImpl class uses the same request instance which has an input stream. For each parameter the injector discovers the most appropriate reader.
The input stream is not touched and is advanced by each reader which parses a value from the request.

JAX-RS (REST Easy) InMemoryClientExecutor/ClientRequest Exception

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.

Categories