How to parse JSON Response to POJO with AndroidAnnotations? - java

I'm using AndroidAnnotations to build a Rest for an Android Application.
On the Serverside im using PHP, which send a json looking like :
{"tag":"register","success":0,"error":2,"msg":"User already existed","body":[]}
I have two POJOS :
User.java:
public class User implements Serializable {
private String name;
private String email;
private String password;
//getter and setter Methods
}
Response.java:
public class RegistrationResponse implements Serializable {
private String tag;
private int success;
private int error;
private String msg;
private String body;
//getter and setter Methods
}
Rest Client:
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
Response sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
Activity.java:
//User and Response are POJOs
Response result = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());
But i got an Null Pointer Exception error on Activity.java. But if i change the return value of "sendUserRegistration" function to String all work. So my "Response" POJO seems not to be converted from AndroidAnnotations.
How can i convert the Rest Response to my "Response"-POJO using AndroidAnnotations?

You don't need to return the entire response object per rest call, just set the response to your custom object. Or you can also return a JsonObject also and use gson to convert it later on.
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
User sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
then just simply call
User newUser = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());

AA relies on Spring Android RestTemplate to make the rest call. And in order to build requests and handle responses this lib uses converters. And to know which converter the RestTemplate should use, it checks the content-type response header.
As MappingJacksonHttpMessageConverter and GsonHttpMessageConverter handles only http response with content-type=application/json and your result is converted to string, I'm pretty sure you forgot to set this header in your php server. So it send the default one (ie: text/plain) which is only handle by StringHttpMessageConverter.
Also, the body field is an object in your json example, but in your POJO you declared it as a String. So parsing will fail on this point.

Related

Java #requestBody doesn't work, dto empty

For some reason java can't map DTO with requestBody and all values are default ones, as for request it works, with payload for ex. "{"productId":1,"commitment":6,"returnMonths":"2"}"
DTO
#Data
public class Request {
private int productId;
private int commitment;
private String returnMonths;
// contructers
}
Controller :
#PostMapping(value = "/calculate", consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String calculatePrice(#RequestBody Request request) {
productService.calculatePrice(request);
return "Success";
}
front request:
submit: async function() {
let request = {
productId: this.productSelected,
commitment: this.optionSelected,
returnMonths: this.input
};
let data = await getCalculation(request);
console.log(data);
}
DTO maps as:
productId : 0
commitment : 0
returnMonths : null
Tried an exact copy of your code and it worked when tested with Postman. This makes me think it's either something to do with the FE or maybe some issue in the service. I'd check if the Frontend really sends the data.
Try to annotation Request class with #AllArgsConstructor like:
#AllArgsConstructor
#Data
public class Request {
private int productId;
private int commitment;
private String returnMonths;
}
If your request body contains properties that is date such as LocalDateTime, make sure to format it in your DTO using #JsonFormat(pattern="") respecting the input value.

How to retrieve the JSON message body in JAX-RS REST method?

I have the following JSON that will be passed as part of a HTTP request, in the message body.
{
"names": [
{
"id":"<number>",
"name":"<string>",
"type":"<string>",
}
]
}
My current REST handler is below. I am able to get the Id and `Version that is passed in as path params, but I am not sure how to retrieve the contents on the message body?
#PUT
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version) {
if (isNull(Id) || isEmpty(version)) {
return ResponseBuilder.badRequest().build();
}
//HOW TO RECIEVE MESSAGE BODY?
//carry out PUT request and return DTO: code not shown to keep example simple
if (dto.isSuccess()) {
return Response.ok().build();
} else {
return Response.serverError().build();
}
}
Note: I am using the JAX-RS framework.
You just need to map your name json to a POJO and add #Consumes annotation to your put method, here is an example:
#PUT
#Consumes("application/json")
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version,
List<NamObj> names) {
I assume you are trying to retrieve a list of elements if is not the case just use you POJO as it in the param.
Depending on what json library are you using in your server you may need to add #xml annotation to your POJO so the parser could know how to map the request, this is how the mapping for the example json should look like:
#XmlRootElement
public class NameObj {
#XmlElement public int id;
#XmlElement public String name;
#XmlElement public String type;
}
Jersey doc: https://jersey.java.net/documentation/latest/user-guide.html#json
#cosumes reference: http://docs.oracle.com/javaee/6/tutorial/doc/gilik.html#gipyt

Best practice to deserialize a JSON using Spring MVC

I'm developing a web application using Spring MVC; it works as follows:
a JSON request is created from a model object (a POJO)
it's sent to an external server that exposes some APIs
a JSON response is received by the controller
I need to figure out which is the best way to serialize and deserialize JSON in a Java web application. At first I was using Gson but then I began to wonder if it was the right choice.
Is it possible to serialize and deserialize JSON to/from model
object using #RestController annotation? How does it works? I only find examples of how to create a rest service, in this sense
What is the best practice in this case? RestController? Gson? Jackson? Other?
N.B. My JsonResponse object has a generic field because the responses are all the same except that for a value. An example:
AccountRequest.class
public class AccountRequest() {
private String jsonrpc;
private String method;
private Map<String, Object> params;
private int id;
//constructor, getters and setters
}
JsonResponse.class
public class JsonResponse<T> {
private String jsonrpc;
private T result;
private String id;
//constructor, getters and setters
}
LoginResult.class
public class LoginResult {
private String token;
private String product;
private String error;
private Date lastLoginDate;
//constructor, getters and setters
}
MyController.class
#Controller
public class LoginController {
String response;
[...]
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView doLogin(#ModelAttribute("user") User user) {
[...]
//???
[...]
}
}
I open connection, send request and save the response in response String in MyController class. User parameter is annotated with #ModelAttribute to retrive the User object created by the showLoginForm() method.
Using Gson I know how to serialize request from my model object:
AccountRequest accountRequest = new AccountRequest();
accountRequest.setJsonrpc("2.0");
accountRequest.setMethod("method");
accountRequest.setParams(params);
accountRequest.setId(1);
String gson = new Gson().toJson(accountRequest);
JSONObject accountRequestJson = new JSONObject(gson);
And how to deserialize response in my model object:
Type jsonType = new TypeToken<JsonResponse<LoginResult>>() {}.getType();
JsonResponse<LoginResult> jsonResponse = new Gson().fromJson(response, jsonType);
The response is now saved into jsonResponse object, and I can put it in my ModelAndView.
Now, how can I deserialize it in my model object using #RestController and Jackson? Can you confirm it's the better method to do that? Can you post an example?
I hope it's not a silly question.
Thanks in advance!

How to get JSON in Java REST / AngularJS frontend

Can someone please help me how to get a JSON String in a Webservice. I's sending JSON to my /api/register that looks like:
{"name":"MyName","surname":"MySurename","email":"mail#asd.de","street":"MyStreet","number":"3","zip":"12345","city":"myCity","pass":"myPassword"}
Here is my register.java file:
#Path("/register")
#Stateless
public class RegisterWS {
#EJB
UserBS userBS;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void createUser(){
// code to get data from json
userBS.createUser(name, surename, email, adress, number, zip, city, password);
}
}
My AngularJS Controller and Service. The Data comes from a form, that is parsed to a JSON object.
app.service('RegisterService', function ($http) {
return {
registerUser : function(user) {
$http.post('http://localhost:8080/myApp/api/register')
.success(function (user) {
return user;
})
.error(function (data) {
// failed
});
}
}
});
app.controller('RegisterCtrl', function($scope, RegisterService) {
$scope.register = function(){
RegisterService.registerUser(angular.toJson($scope.user));
}
});
You should have a POJO, which maps to the received JSON object, for example a User class. In this case this would be a very simple Java Bean, with mostly String properties for each field in the JSON.
#XmlRootElement
public class User {
String name;
String surname;
String email;
String street;
Integer number;
String zip;
String city;
String pass;
}
Of course you would use private fields, with getters and setters, but I did not want to add clutter. By the way the #XmlRootElement is a JAXB annotation, and JAX-RS uses JAXB internally.
After you have this, you just need to change your method like this
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void createUser(User user) {
...
}
You should not need to change anything on the AngularJS side, as the default for the $http.post method is JSON communication.
For your Java code, you have to add a User POJO, I dont know if you will use some persistence API or not, so the user POJO must implement serializable to output user object as JSON.
Here's a an example of REST app with EJB ... : http://tomee.apache.org/examples-trunk/rest-on-ejb/README.html
For your client app, you need to specify the content type : "Content-Type" = "application/json"
See this questions: change Content-type to "application/json" POST method, RESTful API

GWT - Serializing POST parameter in JSON before sending

I am trying to invoke a REST server from my GWT client. The server is not under my control and I am using GWT just for the client. The service expects to receive a JSON which is going to be deserialized with Jackson and mapped to a Java bean like this:
public DTO {
String username;
String password;
/*...*/
}
Therefore, on my GWT project I created this class:
import com.google.gwt.json.client.JSONObject;
import com.lh.clte.client.gui.util.CLTELabelProperties;
public class DTO extends JSONObject {
String username;
String password;
/*...*/
}
And I am trying to send a POST request this way:
DTO dto= new DTO();
dto.setUsername(username);
dto.setPassword(password);
RequestBuilder b = new RequestBuilder(RequestBuilder.POST, url);
b.setHeader("content-type", "application/x-www-form-urlencoded");
/***** ERROR *************/
String data = dto.toString(); // JSONObject.toString(), no ovveriding
/*************************/
b.setRequestData(data);
b.setCallback(new MyCallback<DTO>());
try {
b.send();
} catch (RequestException e) {
e.printStackTrace();
}
However, the toString method doesn't produce the expected JSON, but rather the string "{}". Where am I doing it wrong?
I also tried com.google.gwt.json.client.dev.JsonObject, but it doesn't change the outcome.
You have to stringify your JSO object before sending over the wire:
String data = JsonUtils.stringify(dto);
This function is available in 2.7.0-SNAPSHOT, for 2.6.1 you have to create your own JSNI method
String data = stringify(dto);
private native String stringfy(JavaScriptObject jso) /*-{
return JSON.stringify(obj);
}-*/;
JSONObject is a "map", it's not meant to be extended.
You could have your accessors store the value in an internal JSONObject rather than in fields, or you could use a JavaScriptObject with accessors written in JSNI and using JsonUtils for parsing and JSONObject for serialization (new JSONObject(myJso).toString(), pending GWT 2.7's JsonUtils.stringify), or you could use AutoBeans.
See also https://stackoverflow.com/a/10685489/116472 or How to genearte JSON on the client, among many others.
If your backend uses Jackson, you should give gwt-jackson a try.
You'll be able to use any DTO and even the server beans if you have access to the sources.
You declare your mapper like that :
public static interface DTOWriter extends ObjectWriter<DTO> {}
And then :
DTOWriter dtoWriter = GWT.create(DTOWriter.class);
String data = dtoWriter.write(dto);
BTW, shouldn't your Content-type header be application/json ?
An alternative approach will be to use RestyGWT (http://restygwt.fusesource.org/).
RestyGWT will take care of both serializing to/from JSON and also doing the POST request.
In your example, you will need a Class that defines which fields are serializable:
public class DTO {
#Json(name = "username") // 'username' will be the name of the parameter in the json object
private String username;
#Json(name = "password")
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Then, you define the service by extending RestService
public interface DTORestService extends RestService {
/**
* Utility/Convenience class.
* Use DTORestService.App.getInstance() to access static instance of DTORestService
*/
public static class App {
private static DTORestService ourInstance = null;
public static DTORestService getInstance() {
if (ourInstance == null) {
Defaults.setServiceRoot(host); // the host from the 'url' you want the POST to be sent
ourInstance = (DTORestService) GWT.create(DTORestService.class);
}
return ourInstance;
}
}
#POST
#Path("/dto.json") // the path from the 'url' you want the POST to be sent
public void getDTO(DTO dto, // the json object you want to add to the post
MethodCallback<DTO> callback); // the method callback with any json result you will receive
}
Finally, you can call it by doing:
DTO dto = new DTO();
dto.setUsername(username);
dto.setPassword(password);
DTORestService.getInstance().getDTO(dto, new AMethodCallback<DTO>());
hope it helps

Categories