I have a spring-boot 1.1.7 application that uses Thymeleaf for much of the UI, so the response from my controllers hasn't really been a concern. However, now I need to provide a XML response when a user submits a request via URL.
Here is a typical Request:
http://localhost:9001/remote/search?sdnName=Victoria&address=123 Maple Ave
Here is most of my gradle configuration:
project.ext { springBootVersion = '1.1.7.RELEASE' } dependencies { compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion") compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-starter-security") compile("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion") compile("org.springframework.security:spring-security-web:4.0.0.M1") compile("org.springframework.security:spring-security-config:4.0.0.M1") compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity3:2.1.1.RELEASE') compile("org.springframework.boot:spring-boot-starter-actuator") compile('com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.5.0') }
And here is my controller:
@Controller public class RemoteSearchController { @Autowired private SdnSearchService sdnSearchService; @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE) public List<Sdn> search(@ModelAttribute SdnSearch sdnSearch) { List<Sdn> foundSdns = sdnSearchService.find( sdnSearch ); return foundSdns; }
Here is my Object to be returned:
@Entity public class Sdn { @Id private long entNum; private String sdnName; ... //getters & setters here }
I am able to receive the request via REST client (such as CocoaREST) and handle it. But When I return the list of SDN i get the following exception, even though I do have Jackson & jackson-dataformat-xml on my classpath:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:229) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:301) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:248) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:57) at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:299)
My REST Client is including a Accept Header of "text/xml" (but in all honesty I would rather them not have to set this. Ideally any call to this Controller would always get XML, regardless of header being present).
Is there a way to handle this? I thought the Media Converters were included and just returned whatever the controller told them to?
SOLUTION: See below for the answer I posted.
Data types that REST API can return are as follows: JSON (JavaScript Object Notation) XML. HTML.
The same resource may return either XML or JSON depending upon the request, but it shouldn't return both at the same time. You will know which one to return based upon the request, so there is no need to generate both -- just generate the one you'll be returning.
I had the exact same problem and I found the solution on Spring documentation website : here
In synthesis, I added the following dependency to the pom.xml
of my project :
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
Then I added the following code block to the class that the service had to return :
import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Greeting {...}
And it worked.
SOLUTION: I used a combination of both answers below (thank you very much!). I am posting here in case anyone else needs help.
My modified controller:
@Controller public class RemoteSearchController { @Autowired private SdnSearchService sdnSearchService; @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = { "application/xml", "text/xml" }, consumes = MediaType.ALL_VALUE ) @ResponseBody public SdnSearchResults search(@ModelAttribute SdnSearch sdnSearch) { List<Sdn> foundSdns = sdnSearchService.find( sdnSearch ); SdnSearchResults results = new SdnSearchResults(); results.setSdns( foundSdns ); return results; } }
And on my client, I set the request headers:
Content-type: application/text Accept: text/xml I think ultimately the problem was that my client headers were not being set correctly, so I may not have had to make some of these changes. But I liked the idea of a SearchResults class containing a list of results:
@XmlRootElement public class SdnSearchResults { private List<Sdn> sdns; ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With