2

We currently have a level 2 RESTful web service. We are updating the service to incorporate hypermedia support. We are using Spring Data Rest on the back-end to handle the setting of the HATEOAS properties. The problem we're having is that we still need to support our legacy API consumers until the migration can be completed, meaning we still need to support responses without HAL properties like "_links" and "_embedded".

For reasons that aren't really worth explaining, we cannot address this problem with URL versioning. We need instead to be able to map requests with an Accept header of "application/json" to our old controllers, and let SDR handle any requests with "application/hal+json". In essence, we'd like to use SDR as a fallback to handle API requests that are specifically requesting HAL-formatted responses.

I came across this excerpt in the SDR documentation:

We register a custom HandlerMapping instance that responds only to the RepositoryRestController and only if a path is meant to be handled by Spring Data REST. In order to keep paths that are meant to be handled by your application separate from those handled by Spring Data REST, this custom HandlerMapping inspects the URL path and checks to see if a Repository has been exported under that name. If it has, it allows the request to be handled by Spring Data REST. If there is no Repository exported under that name, it returns null, which just means "let other HandlerMapping instances try to service this request".

The Spring Data REST HandlerMapping is configured with order=(Ordered.LOWEST_PRECEDENCE - 100) which means it will usually be first in line when it comes time to map a URL path and your existing application will never get a chance to service a request that is meant for a Repository. For example, if you have a Repository exported under the name "person", then all requests to your application that start with "/person" will be handled by Spring Data REST and your application will never see that request. If your Repository is exported under a different name, however (like "people"), then requests to "/people" will go to Spring Data REST and requests to "/person" will be handled by your application.

This seems to imply that what we're trying to accomplish is possible, assuming the HandlerMapping order can be configured differently. I haven't been able to make that work so far though:

  • Setting SDR's HandlerMapping to Ordered.HIGHEST_PRECEDENCE seems to have no effect.
  • Setting SDR's HandlerMapping order to Ordered.LOWEST_PRECEDENCE seemed to disable ordering altogether, and my custom controllers did field the requests, but SDR was no longer responding to any requests. application/hal+json just resulted in a 406 status.

Is there any way to configure the HandlerMappings correctly such that my custom controllers take priority and SDR fields any requests not specifically mapped to my controllers?

  • That's actually how it's supposed to work out of the box. If you map a controller into the URI space of SD REST, your controller should be preferred. Can you come up with a minimal example that shows this failing? – Oliver Drotbohm Nov 27 '14 at 16:51
  • @OliverGierke, sure, I can provide a minimal example if it would help. However, the out-of-the-box functionality you're describing seems to be a direct contradiction to what is stated in the documentation: "[Spring Data REST] will usually be first in line when it comes time to map a URL path and your existing application will never get a chance to service a request that is meant for a Repository" – justin1080602 Nov 28 '14 at 15:00

0 Answers0