Reputation: 7330
I have the API:
@GetMapping(path = "/users/{userId}")
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
//logic here
}
it returns JSON response, as it should.
And there's another app that I don't have access to, and it calls my API as, for example, GET /users/123.xml
in order to receive XML response.
But in this case, my API fails with 400
error, because it cannot parse 123.xml
into Long
.
Option @GetMapping(value = {"/users/{userId}", "/users/{userId}.xml"})
fails with the same error.
What can I do to respond with XML syntax when calling /{userId}.xml
and in the mean time, respond with JSON syntax when calling /{userId}
?
EDIT:
I want it to do without specifically adding 'Accept' headers, and without writing any additional logic, that'll parse {userId}.xml
and then set the appropriate response type.
Upvotes: 1
Views: 809
Reputation: 124
That's can be done by using a ContentNegotiationConfigurer, you can configure it as follow :
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML)
.mediaType("json", MediaType.APPLICATION_JSON);
}
}
It should work fine with your endpoint :
@GetMapping(path = "/users/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
return new ResponseEntity<>(userService.get(userId), HttpStatus.OK);
}
Upvotes: 2
Reputation: 2029
As an owner of the API you should declare what kind of a responses you are able to produce - in your case it is either JSON or XML:
@GetMapping(path = "/users/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
return new ResponseEntity<>(userService.get(userId), HttpStatus.OK);
}
Any client of the API can now choose which response format is preferred using Accept
header - for example Accept: application/xml
. Spring will respect that and return response in requested format.
To make it work you need to add additional dependency that will be used by Spring to produce XML responses:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
If you really need to go in /users/123.xml
direction you'll have to change userId
type to String
and parse it yourself like this:
@GetMapping(path = "/users/{userId}")
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") String userId) {
if (hasXMLExtension(userId)) {
return ResponseEntity
.ok()
.contentType(MediaType.XML)
.body(requestdUser);
} else {
return ResponseEntity
.ok()
.contentType(MediaType.JSON)
.body(requestdUser);
}
}
Upvotes: 1
Reputation: 891
The easiest solution that I can think right off will be to have an optional Request parameter "responseType" with default value as json, and if someone wants XML response, they can call the url like :GET /users/123?responseType=xml Since the default value of the parameter will be 'json' and it will have property "required= false", you wouldn't need to worry in use cases where json response is desired, and if someone wants XML response, they can add the optional RequestParam. Also, I guess you will need to specify produces with json and xml return types for the controller to let spring-boot know that it can produce different kinds of responses, something like -
@RequestMapping(value = "/users/{userid}", method = RequestMethod.GET,
produces = { MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE)
public ResponseEntity<User> getuserById(@PathVariable String
userid,@RequestParam(required=
false,defaultValue="json",name="responseType"),@RequestHeader ("content-type") String
contentType)
)
EDIT : You can use either the request param or the Request header, I provided both in the example for your reference
Upvotes: 1