AndroidAnnotations, REST and custom response - rest

I'm using AndroidAnnotations in my project. This works fine so far...
But now I try to access a given Webservice with a custom response like this:
{
success: true,
total: 100,
items: [],
}
This response format is the same for every GET request. The items property holds the response objects I'm interested in and the items contains different object type(like user, product etc)
I'm using "MappingJackson2HttpMessageConverter"...
How can I access them?
Thanks,
Stefan

You have to create the response class, which can be deserialized from the JSON response:
public class CustomResponse {
boolean success;
int total;
List<Integer> items;
}
This is just an example, because it is ambigous from your JSON snippet, what exact types you are using.
Then you can use this response class in your REST client:
#Get("/getsomething")
public CustomResponse getSomething();
It is not necessary to use MappingJackson2HttpMessageConverter, you could use any converter which can convert your JSON response (like a GSON converter).

Related

Using JAX-RS how to collect an array of data returned by an API service into a list of java objects?

What is the correct way to get List of objects from an API service using JAX-RS?
Environment: Helidon (MP 1.4.4), Java 8. The external api service returns an Array of objects. Paper is a POJO.
Client client = ClientBuilder.newClient();
...
...
public List<Paper> getPapers() {
return client
.target(REST_URI)
.request(MediaType.APPLICATION_JSON)
.header("api-key", "xxxxxx")
.get(new GenericType<List<Paper>>() { });
}
Error:
javax.ws.rs.client.ResponseProcessingException: javax.json.bind.JsonbException: Can't deserialize JSON array into: class java.lang.String
You have to use arrays instead of List. Of course you can still convert the array to a List or any other collection type if you need.
public Paper[] getPapers() {
return client
.target(REST_URI)
.request(MediaType.APPLICATION_JSON)
.header("api-key", "xxxxxx")
.get(Paper[].class);
}

Wiremock: choose body file name based on request parameter

I am using wiremock to mock http server and I am returning responses from json files (using withBodyFile method).
Now I want to choose and return response json file based on request parameter. For the example below, I want to define one stub so that the body file is chosen based on request parameter.
myMockServer.stubFor(
get(urlEqualTo(myEndPoint+ "?key=key1"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json")
.withBodyFile("response_key1.json")
myMockServer.stubFor(
get(urlEqualTo(myEndPoint+ "?key=key2"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json")
.withBodyFile("response_key2.json")
myMockServer.stubFor(
get(urlEqualTo(myEndPoint+ "?key=key3"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json")
.withBodyFile("response_key3.json")
Any idea how this would be possible? I tried defining transformer but it was not possible to get Stream Source Path from Response object in overridden method so can't use that appraoch. Thanks a lot..
Body File name can't be parameterized in wiremock as of now. I had a similar requirement, I needed to return the file based on the request URL. So I implemented a transformer as below:
public class BodyFileNameResponseTransformer extends ResponseDefinitionTransformer {
public ResponseDefinition transform(Request request, ResponseDefinition rd,
FileSource fileSource, Parameters parameters) {
if (rd.getBodyFileName().startsWith("{{")) {
return new ResponseDefinitionBuilder().**withBodyFile**(request.getUrl().substring(1))
.withStatus(rd.getStatus())
.withHeaders(rd.getHeaders())
.withTransformers(
rd.getTransformers().toArray(new String[rd.getTransformers().size()]))
.build();
}
return rd;
}
public String getName() {
return "BodyFileNameTransformer";
}
}
you can use request.queryParameter(key) instead of request.getUrl() and form any
file path. Create the file path based on your need and set it as bodyFile on returned ResponseDefinition.
Don't forget to start wiremock with --extensions: Extension class names
More details at Extending Wiremock
This is possible by using the inbuilt template helpers provided by Handlebar.
myMockServer.stubFor(
get(urlEqualTo(myEndPoint+ "?key=key3"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json")
.withBodyFile("response_{{request.query.key}}.json")
Check for the various models available at http://wiremock.org/docs/response-templating/.

Spring MVC REST using #RequestBody List<?> returns HTTP 400 syntactically incorrect

I am using Spring 4 + Jackson 2 and have written a fully functional POST method using #RequestBody on a custom class. This method has no trouble unmarshalling the object.
#ResponseBody
#RequestMapping(value="store", method = RequestMethod.POST)
public ServiceResponse store(#RequestBody CustomClass list) {
...
}
// Request: { code: "A", amount: 200 }
When I attempted to add another method to handle a collection of the same class instead, my POST requests were returning with the following error.
HTTP Status 400: The request sent by the client was syntactically incorrect.
I note that this error typically occurs when the JSON submitted does not match the entity class. However, all I am doing is submitting an array of the same object instead of the object itself, which has already proven to work.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody List<CustomClass> list) {
...
}
// Request: [{ code: "A", amount: 200 }, { code: "B", amount: 400 }]
Am I missing something here?
In Java, type information for generics is erased at runtime, so Spring sees your List<CustomClass> object as List<Object> object, thus it cannot understand how to parse it.
One of ways to solve it, you could capture the type information by creating a wrapper class for your list, like this:
public class CustomClassList extends ArrayList<CustomClass> {
}
Sergey is right that the issue is due to type erasure. Your easiest way out is to bind to an array, so
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody CustomClass[] object) {
...
}
The answer is that Spring 4 doesn't actually get rid of type erasure, contrary to what some other solutions suggest. While experimenting on debugging via manual unmarshalling, I decided to just handle that step myself instead of an implicit cast that I have no control over. I do hope someone comes along and proves me wrong, demonstrating a more intuitive solution though.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody String json) {
try {
List<CustomClass> list = new ObjectMapper().readValue(json, new TypeReference<List<CustomClass>>() { });
...
} catch (Exception e) {
...
}
}
Bonus: Right after I got this working, I bumped into this exception:
IllegalStateException: Already had POJO for id
If anyone gets this, it's because the objects in the list happen to reference some object that another item in the list already references. I could work around this since that object was identical for my entire collection, so I just removed the reference from the JSON side from all but the first object. I then added the missing references back after the JSON was unmarshalled into the List object.
Two-liner for the Java 8 users (the User object reference was the issue in my case):
User user = list.get(0).getUser();
list.stream().filter(c -> c.getUser() == null).forEach(t -> t.setUser(user));

Return raw string from REST service method

I have a REST service method written in C#, defined as below:
[WebGet(UriTemplate = "/{par1}/{par2}/{par3}")]
public string ProcessGet(string par1, string par2, string par3)
{
return Execute(...);
}
It should return result as XML or JSON, based on one parameter (I generate the json and XML serialization)
How can I make this method to return the RAW string, just as I created it, without HTMLEncoding it?
Thank you
Return it as a Stream - that causes the "raw" mode to be used and WCF will not touch your response. You can find more information at http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx.

Are list parameters supported in OpenRasta? how they should be sent?

If I have a resource handler method receiving an object list as parameter (int list, string list or any object type list), i.e.:
public class TasksCollecionHandler
{
public TaskCollection GetTasksByEngineer(List<int> engineerIds)
{
....
}
public TaskCollecion GetTasksByEngineer(List<Engineer> engineers)
{
....
}
}
Is OpenRasta supporting this kind of arguments?
How the HTTP request including values for kind of arguments should look like?
Depends on the codec. Using json or xml data contracts it'd be whatever format the datacontract mapping follows.
If you use forms and html, the format would be
engineers:0.FirstName=john&engineers:0.LastName=doe&engineers:1.FirstName=other