How to force spring's #ResponseBody to use xmlConvertor - java

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

Spring, how to return XML response from string without additional converters?

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.

Why Spring MVC transform parameter [""] to [null] during mapping json to java bean?

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

returning multiple different objects in #RestController method

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\"}";
}

Automatically add "headers" and "produces" attributes to my #RequestMapping

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 { ... }

Spring restful webservice returning JSON

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)));
}

Categories