Spring Web Service: Adding Arrays/Collections to a response - java

Currently my webservice will return a response which queries for one specific record. A request has been made to allow for multiple similar records to be returned via the response message.
For Example:
I return name, address 1, address 2, postalcode for a specific person
They'd like to have a return of all names/addresses for the postalcode passed in. With that being said, my resultExtractor and response are doing single strings/ints currently. Is there any documentation out there explaining the process of using arrays with your response message?
Thanks!

Using spring, you can annotate the controller method with #ResponseBody.
Your java return type will be then be parsed and sent over the wire, if jackson is on your classpath then it will be converted to JSON.
Spring MVC ResponseBody docs
Similar question which has Java and xml config answers

The best way is to use Json in the response. So who make the request will need to convert the json into the right Object.
For example you can use Gson library of google: Gson Library
Ther is an example MVC controller that works in my project
#RequestMapping(value = "services/utente/getUtenteByUsername", method = RequestMethod.GET)
#ResponseBody
public String getUtenteDaUsername( #RequestParam("username") String username, Model model) {
utente = utenteBo.findByUsername(username);
String jsonResult = "";
if (utente != null) {
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
jsonResult = gson.toJson(utente);
return jsonResult;
}
else {
return null;
}
}

Related

Java instanceof with Object

I have a spring boot project with Java 17. I am calling a third party API to get the list of records. If the records are present I do get the 200 OK response with list of records and in case records are not present I do get a 200 OK response with another JSON schema. To verify whether the response if of a type list of records or an error I am using instanceof but it is not working and always go to else condition.
HttpEntity<Void> request = new HttpEntity<>(httpHeaders);
ResponseEntity<Object> response = restTemplate.exchange(uri, HttpMethod.GET, request, Object.class);
if (response.getBody() instanceof ZohoError zohoError) {
return Collections.emptyList();
} else {
return (List<Leave>) response.getBody();
}
#Getter
#Setter
#ToString
#EqualsAndHashCode
public class ZohoError {
private String message;
#JsonAlias("errorcode")
private String errorCode;
#JsonAlias("Response status")
private int responseStatus;
}
As your third party API returns different schemas with same http code (which smells for me), you can't use RestTemplate to get needed object - you don't know the object type.
You can get RestTemplate response as String, parse it to JsonNode using ObjectMapper (Jackson). Then decide which schema is this by some telling attributes. And parse response string to defined type using ObjectMapper.

How to pass List or String array to getForObject with Spring RestTemplate

I am developing some restful services with Spring. I have trouble with passing/getting string array or large string as parameters to my service controller. My code examples are like below;
Controller:
#RequestMapping(value="/getLocationInformations/{pointList}", method=RequestMethod.GET)
#ResponseBody
public LocationInfoObject getLocationInformations(#PathVariable("pointList") String pointList)
{
// code block
}
Sample point list:
String pointList = "37.0433;35.2663,37.0431;35.2663,37.0429;35.2664,37.0428;35.2664,37.0426;35.2665,37.0424;35.2667,37.0422;35.2669,37.042;35.2671,37.0419;35.2673,37.0417;35.2674,37.0415;35.2674,37.0412;35.2672,37.0408;35.267,37.04;35.2667,37.0396;35.2665,37.0391;35.2663,37.0388;35.2662,37.0384;35.266,37.0381;35.2659,37.0379;35.2658,37.0377;35.2657,37.0404;35.2668,37.0377;35.2656,37.0378;35.2652,37.0378;35.2652,37.0381;35.2646,37.0382;35.264,37.0381;35.2635,37.038;35.263,37.0379;35.2627,37.0378;35.2626,37.0376;35.2626,37.0372;35.2627,37.0367;35.2628,37.0363;35.2628,37.036;35.2629,37.0357;35.2629,37.0356;35.2628,37.0356;35.2628,37.0355;35.2626";
Web service client code:
Map<String, String> vars = new HashMap<String, String>();
vars.put("pointList", pointList);
String apiUrl = "http://api.website.com/service/getLocationInformations/{pointList}";
RestTemplate restTemplate = new RestTemplate();
LocationInfoObject result = restTemplate.getForObject(apiUrl, LocationInfoObject.class, vars);
When I run client side application, it throws a HttpClientErrorException: 400 Bad Request, I think long location information string causes to this problem. So, how can I solve this issue? Or is it possible posting long string value as parameter to web service?
Thx all
List or other type of objects can post with RestTemplate's postForObject method. My solution is like below:
controller:
#RequestMapping(value="/getLocationInformations", method=RequestMethod.POST)
#ResponseBody
public LocationInfoObject getLocationInformations(#RequestBody RequestObject requestObject)
{
// code block
}
Create a request object for posting to service:
public class RequestObject implements Serializable
{
public List<Point> pointList = null;
}
public class Point
{
public Float latitude = null;
public Float longitude = null;
}
Create a response object to get values from service:
public class ResponseObject implements Serializable
{
public Boolean success = false;
public Integer statusCode = null;
public String status = null;
public LocationInfoObject locationInfo = null;
}
Post point list with request object and get response object from service:
String apiUrl = "http://api.website.com/service/getLocationInformations";
RequestObject requestObject = new RequestObject();
// create pointList and add to requestObject
requestObject.setPointList(pointList);
RestTemplate restTemplate = new RestTemplate();
ResponseObject response = restTemplate.postForObject(apiUrl, requestObject, ResponseObject.class);
// response.getSuccess(), response.getStatusCode(), response.getStatus(), response.getLocationInfo() can be used
The question is related to GET resource, not POST. Because of that I think that "accepted answer" is not the correct one.
So for other googlers like me that finds this, Ill add what helps me:
GET resources can receive a string list via #PathVariable or #RequestParam and even correctly bind it to a List<String> if you do pass the list separated by ,.
Your API can be:
#RequestMapping(value="/getLocationInformations/{pointList}", method=RequestMethod.GET)
#ResponseBody
public LocationInfoObject getLocationInformations(#PathVariable("pointList") List<String> pointList) {
// code block
}
And your call would be:
List<String> listOfPoints = ...;
String points = String.join(",", listOfPoints);
String apiUrl = "http://api.website.com/service/getLocationInformations/{pointList}";
LocationInfoObject result = restTemplate.getForObject(apiUrl, LocationInfoObject.class, points);
Note that you must send lists to API using , as separator, otherwise the API cannot recognize it as a list. Also you cannot just add your list directly as a parameter, because depending on how it's mashalled the generated string may not be compatible.
Firstly you've passed a map as parameters but your controller expects these as a path variable. All you need to do is make the 'pointlist' value part of the URL (without the curly bracket placeholders). e.g.:-
http://api.website.com/service/getLocationInformations/pointList
Next you need to ensure you have message converters set up so that your LocationInfoObject is marshalled into an appropriate representation (suggest JSON) and unmarshalled the same way.
For the Rest template:
restTemplate.setMessageConverters(...Google MappingJackson2HttpMessageConverter...);
For the server you just need to add Jackson to the classpath (if you want multiple representations you'd need to configure each one manually - Google will be your friend here aswell.

How to bind set object to controller in spring

I am trying to make a post call to a controller, but the object I am expecting contains a Set datatype and I am unsure how the post data should look.
Models:
public class Notebook{
private string name;
private Set<Todo> todos;
}
public class Todo{
private String name;
}
Controller
#RequestMapping(method = RequestMethod.POST)
public void createNotebook(Notebook q){
questionnaireService.saveOrUpdateNotebook(q);
}
Currently I have tried posting like the example below:
curl --data "name=some notebook&todos[0].name=todo1&todos[1].name=todo2" http://localhost:8080/api/notebook
Doesn't seem to work. Anyone have experience with Sets?
You should qualify Notebook q with #RequestBody annotation so that the request can be mapped to an object of type Notebook. More about the format of the input data and the converters in Spring MVC doc: Mapping the request body with the #RequestBody annotation.
We send data from the front-end in JSON format and use Jackson JSON to convert it to the Java object. If you go that route, you can directly declare the todos as Set<String> and the input would be
{
name: "some notebook",
todos: ["todo1", "todo2"]
}

Spring: Return JSON response From A Java Bean

I'm new to springs and I wondering if I can return the contents of a Java Bean as a JSON response. Basically, I would have a class XYZ,
public class XYZ {
private String name,
private String email,
//Setters and getters...
}
I was wondering if I can get a response which has
{name: 'Something', email: 'something#somethingelse.com'}
without any manual processing. Thanks in advance!
Spring #ResponseBody is used to return json automatically.
#ResponseBody
public XYZ response() {
XYZ xyz = new XYZ();
xyz.setName("name");
xyz.setEmail("email#com");
return xyz
}
You should add jackson to webapp runtime classpath.
We use fastjson to JSONize java beans. It's fast and convenient.
public #ResponseBody
String showLesson() {
Map<String, Object> map = new HashMap<String, Object>();
return JSON.toJSONString(map);
}
There are plenty of libraries out there for json conversion. You can use Jackson which is supported by Spring MVC.
XYZ obj = /*instance*/;
ObjectMapper converter = new ObjectMapper();
System.out.println(converter.writeValueAsString(obj));

Returning JSON Object from REST Web Service with Complex Objects

I have a rest enabled web service exposed which returns RETURN_OBJ.
However, RETURN_OBJ in itself contains several complex objects like list of objects from other class, maps, etc.
In such a case, will annotating the participating classes with #XmlRootElement and annotating web service with #Produces("application/json") enough?
Because just doing it is not working and I am getting no message body writer found for class error.
What is the reason, cause and solution for this error?
I hope this might help a bit,
Following is an working example for returning a json object which was constructed using Gson and tested with Poster and the url is domainname:port//Project_name/services/rest/getjson?name=gopi
Construct a complex Object as you like and finally convert to json using Gson.
#Path("rest")
public class RestImpl {
#GET
#Path("getjson")
#Produces("application/json")
public String restJson(#QueryParam("name") String name)
{
EmployeeList employeeList = new EmployeeList();
List<Employee> list = new ArrayList<Employee>();
Employee e = new Employee();
e.setName(name);
e.setCode("1234");
Address address = new Address();
address.setAddress("some Address");
e.setAddress(address);
list.add(e);
Employee e1 = new Employee();
e1.setName("shankar");
e1.setCode("54564");
Address address1 = new Address();
address.setAddress("Address ");
e1.setAddress(address);
list.add(e1);
employeeList.setEmplList(list);
Gson gson = new Gson();
System.out.println(gson.toJson(employeeList));
return gson.toJson(employeeList);
}
#GET
#Produces("text/html")
public String test()
{
return "SUCCESS";
}
}
PS: I dont want to give heads up for fight between Jackson vs Gson ;-)
#XmlRootElement
You need to use a libary with json annotations instead of xml annotations. ex: jackson (http://jackson.codehaus.org/). You can try to use a xml writer to write json.
#Produces("application/json")
When the classes are annotated with the json annotations, json will be returned.

Categories