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.
Related
I have a #RestController with multiple methods like this:
#GetMapping(value = "/getSomething", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<SomeClassXml> getSomething() {
...
return ResponseEntity.ok(something);
}
Response goes through MappingJackson2XmlHttpMessageConverter and i have response containing XML.
But in one of methods i am obtaining String with already prepared XML content from 3rd party source.
If i'm using something like this:
#GetMapping(value = "/getXmlPreparedEarlier", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> getXmlPreparedEarlier() {
...
return ResponseEntity.ok(stringWithXml);
}
i have broken response:
<String>
<tag>xml content</tag>
</String>
Is there a way to return xml content as is? I don't need to serialize/convert/sanitize it. Response has to keep content type "application/xml" and it would be nice to save method's "produces" annotation because it is also used by swagger doc generator.
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 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\"}";
}
I implemented a REST API via Spring MVC. Here is an example of a mapping:
#RequestMapping(value = "/videos", method = RequestMethod.GET, headers = "Accept=application/json", produces = "application/json")
There are many of them, so I wonder if it's possible to factorize the headers and produces attributes, so that I don't have to specify them in each mapping, in order to lighten my code?
The best would be a custom annotation which automatically sets the two attributes, for example:
#JsonRequestMapping(value = "/videos", method = RequestMethod.GET)
But I haven't been able to implement such one...
You can put #RequestMapping also on a class next to a method (see reference guide). If you want globally available attributes put a #RequestMapping on a class, this will be merged with the one on the method.
#Controller
#RequestMapping(headers = "Accept=application/json", produces = "application/json")
public class YourController { ... }
Then your method only contains the method and url.
#RequestMapping(value="/videos", method=RequestMethod.GET)
public Object someMethod(...) { ... }
You also might want to take a look at #RestController as that also configures some defaults for your controller. Like not needing a #ResponseBody anymore on your methods.
#RestController
public class YourController { ... }
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)));
}