Consuming a different JSON input format at the same URL and same method in Spring RESTful service

I am going to implement a RESTful web service using Spring. Let it be a regular PUT method, something like this:

@RequestMapping(method=RequestMethod.PUT, value="/foo") public @ResponseBody void updateFoo(@RequestBody Foo foo) { fooService.update(foo); } 

In this case, the input JSON format (if it corresponds to the Foo class) will be successfully converted to the Foo instance without any additional efforts, or an error will be generated if the format is incorrect. But I would like the service to be able to consume two different types of formats using the same method (e.g. PUT) and the same URL (e.g. / foo).

To make it look like this:

 //PUT method #1 @RequestMapping(method=RequestMethod.PUT, value="/foo") public @ResponseBody void updateFoo(@RequestBody Foo foo) { fooService.update(foo); } //PUT method #2 @RequestMapping(method=RequestMethod.PUT, value="/foo") public @ResponseBody void updateFoo(@RequestBody FooExtra fooExtra) { fooService.update(fooExtra); } 
Converter

and Spring tried to convert the input JSON not only to Foo, but also to FooExtra, and also called the appropriate PUT method depending on the input format.

In fact, I tried to implement it exactly as described above, but to no avail. Is it possible? Maybe I need some kind of "trick"? What is the best (and most correct) way to achieve this behavior? Of course, I could always create two different URLs, but I would like to know if this is possible with the same thing.

+5
source share
2 answers

Your attempt did not work simply because Spring tried to match your methods with the request by looking at the URL and method type, which are the same in both cases. This does not work like overloading in Java; argument types do not distinguish between your methods.
But there is good news. SpringMVC can also check request headers and request parameters when trying to match handler methods. Since what you want to convey is actually pure metadan - an alternative type of format for the same information - it makes sense to use your own request header. It is very easy to add custom headers when using the rest api. See the following link for JAX-RS: Adding a custom header .

Now on the server side you should configure the handler methods as:

 //PUT method #1 @RequestMapping(method=RequestMethod.PUT, value="/foo", headers="returnType=Foo") public @ResponseBody Foo updateFoo(@RequestBody Foo foo) { fooService.update(foo); } //PUT method #2 @RequestMapping(method=RequestMethod.PUT, value="/foo", headers="returnType=FooExtra") public @ResponseBody FooExtra updateFoo(@RequestBody FooExtra fooExtra) { fooService.update(fooExtra); } 

Note that if you want to access the return value using @ResponseBody, you must return your object, otherwise make void methods

+6
source

To understand this, we need to think about how Spring works; it uses the dispatch servlet. I donโ€™t think Spring is doing a โ€œcombinationโ€ of work for different input types.

So my answer would be this: a " trick " with two different URLs;)

0
source

Source: https://habr.com/ru/post/1207031/


All Articles