I am currently working with Spring Rest Web Services and I have set up a #RestController with some methods that each have a #RequestMapping. The problem is that each method can of course only return objects of one type. However, for each request, I might want to return an instance of Class A, one property of Class B and a List containing objects of Class C. Of course, I could make multiple requests, but is there a way we can return multiple different objects with one request?
For further information: I would like to send the objects back to a mobile client in XML format.
You can make your method to return Map<String,Object>:
#RequestMapping(value = "testMap", method = RequestMethod.GET)
public Map<String,Object> getTestMap() {
Map<String,Object> map=new HashMap<>();
//put all the values in the map
return map;
}
You can return a JsonNode
#RequestMapping(..)
#ResponseBody
public JsonNode myGetRequest(){
...
//rawJsonString is the raw Json that we want to proxy back to the client
return objectMapper.readTree(rawJsonString);
}
The Jackson converter know how to transform the JsonNode into plain Json.
Or you can tell Spring that your method produces json produces="application/json"
#RequestMapping(value = "test", method = RequestMethod.GET, produces="application/json")
public #ResponseBody
String getTest() {
return "{\"a\":1, \"b\":\"foo\"}";
}
Related
First of all, thank you in advance for your support.
My problem;
First I am successfully getting my specific parameters in Employer. However, I also have a constantly changing parameter list in request. I want to get them with Map too.
My dto:
public class Employee {
private String name;
private MultipartFile document;
}
#RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Mono<Employee> saveEmployee(#ModelAttribute Employee employee, Map<String,Object> otherValues) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
I attached a request example aslo.
NOTE:
I used #RequestParam, #RequestPart before Map<String,Object> otherValues like this;
#RequestParam Map<String,Object> otherValues
#RequestPart Map<String,Object> otherValues
But I still couldn't get the rest of the data.
When you want to get values from form data, you can create a model like a DTO, with field of both entity (employee) and additional data (otherValues). Because #ModelAttribute can bind data to only one named model attribute
This is working for Spring MVC. But When you work with Spring WebFlux for reactive applications, it doesn't work.
#RequestMapping(path = "/employee", method = POST, consumes ={MediaType.MULTIPART_FORM_DATA_VALUE })
public Employee saveEmployee(
#ModelAttribute Employee employee,
#RequestParam Map<Object,Object> otherValues,
#RequestParam("file") MultipartFile file) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
Main trick is to use Object for key and value;
#RequestParam Map<Object,Object> otherValues
I want to know why spring mvc transform [""] to [null] when I use PostMan to test my API.
here is my controller:
#RequestMapping(value = "", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public #ResponseBody ResponseEntity<Object> participateRstActivities(
HttpServletRequest request, #RequestBody RstActivityFrom rstForm)
throws ServiceException {
log.info("list size:{}, frist object:{}",rstForm.getRestaurant_ids().size(), rstForm.getRestaurant_ids().get(0));
}
here is my java bean:
public class RstActivityFrom {
private List<Integer> restaurant_ids;
private int activity_id;
// omit getter & setter
}
here is my request body when I use postman to test my api:
{
"restaurant_ids":[""],
"activity_id":119129
}
and the log in controller print :
list size:1, frist object:null.
this problem makes me feel confuse, I want to know why. Thanks
Since restaurant_ids is a List and not String, Change your JSON for restaurant_ids:
{
"restaurant_ids":[],
"activity_id":119129
}
If you don't want to allow an empty String value for objects mapped from your JSON, you can look into setting the Jackson's ObjectMapper Features as described here:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html
The Java API for Jackson's DeserializationConfig.Feature(s) can be found here:
http://fasterxml.github.io/jackson-core/javadoc/1.9/org/codehaus/jackson/map/DeserializationConfig.Feature.html
I want to create a REST-GET controller in spring-mvc that takes a list of objects, eg 10 ids as follows:
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.GET)
public Object test(#RequestParam value="id" required=false) List<Integer> ids) {
Sysout(ids);
}
}
Anyway when I call it, I have to repeat the id param multiple times:
localhost:8080/app?id=1&id=2&id=3&...
It is possible to change the param to some kind of list? Eg
app?id=1,2,3,4,5
And if yes, is this advisable? What's better from the client point of view?
Its better to use POST message with JSON or XML as request body.
As you never know how many id's will be passed.
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.POST)
public Object test(#RequestBody IDRequest request) {
Sysout(ids);
}
public static final class IDRequest {
List<Integer> ids;
<!-- getter/setters--->
}
}
where the request will be some kind of a JSON or XML like this
{"ids":[1,2,3,4,5,6,7,8,9]}
You can provide list of objects to rest service as request param.Here is the example
#RequestMapping(value = "/animals, method = RequestMethod.GET)
public void test(#RequestParam(value="animalsNames[]") String[] animalsNames) {
Sysout(animalsNames);
}
And your request looks like
http://localhost:8080/appname/animals?animalsNames[]=dog,horse
HTTP Method type : GET
Controller :
public #ResponseBody String getInfos(HttpServletRequest request,
#RequestParam #DateTimeFormat( #RequestParam List<Long> ids) {...}
Request :
http://localhost:8080/test/api?ids=1,2,3
I just took the tutorial over at Spring.io http://spring.io/guides/gs/rest-service/ and created a simple rest service. But, does anybody know how I can return multiple objects in JSON format? If I for instance have a person class with a name and an id, how can I add three persons to /persons?
You can use the #ResponseBody annotation and just return whatever you want, providing that those objects can be jsonized.
For example, you can have a bean like this:
#Data
public class SomePojo {
private String someProp;
private List<String> someListOfProps;
}
and then in your controller you can have:
#ResponseBody
#RequestMapping("/someRequestMapping")
public List<SomePojo> getSomePojos(){
return Arrays.<String>asList(new SomePojo("someProp", Arrays.<String>asList("prop1", "prop2"));
}
and Spring by default would use its Jackson mapper to do it, so you'd get a response like:
[{"someProp":"someProp", "someListOfProps": ["prop1", "prop2"]}]
The same way, you can bind to some objects, but this time, using the #RequestBody annotation, where jackson would be used this time to pre-convert the json for you.
what you can do is
#RequestMapping("/someOtherRequestMapping")
public void doStuff(#RequestBody List<SomePojo> somePojos) {
//do stuff with the pojos
}
Try returning a list from the method:
#RequestMapping("/greetings")
public #ResponseBody List<Greeting> greetings(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return Arrays.asList(new Greeting(counter.incrementAndGet(),String.format(template, name)));
}
When I return a single object from a controller like this,
#ResponseBody
public MyClass module(...) {
...
}
I get the xml output on the client and log shows like this,
2011-09-07 18:22:06,963 [qtp1409490836-27] DEBUG
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- Written [com.domain.MyClass#4374820d] as "application/xhtml+xml"
using
[org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter#b4e1f3]
But If I use a list like this,
#ResponseBody
public List<MyClass> module(...) {
...
}
It uses jsonConvertor and returns the json output.
2011-09-07 18:38:31,026 [qtp420370595-26] DEBUG
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- Written [[com.domain.MyClass#654309f0]] as
"application/json;charset=UTF-8" using
[org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#14419f80]
The MyClass is annotated with jaxb. In jersey I could say
#Produces({ MediaType.APPLICATION_XML })
How do I force spring to use the xmlconverter always?
There is some bug that means you cannot return your class in a list. You need to create a new class to hold your list of objects and return that in the #ResponseBody. Something like this:
#RequestMapping(value = Constants.URL, method = RequestMethod.GET)
public #ResponseBody ListHolder getFoos(HttpServletResponse response) {
response.setContentType("application/xml");
List<Foo> foos = getFoos();
ListHolder listHolder = new ListHolder();
listHolder.setFoos(foos);
return listHolder;
}
Annotate your ListHolder class with #XmlRootElement and if your have the jaxb jar or Java 6 then it should work.
If Spring cant find a JSON convert it can't send JSON. Try to remove jackson.jar from the class path and it should default to XML through XStream for all request.