my project is moving away from a custom json format to json-hal and spring-data-rest. to continue the support for the "old" json i want to run the existing Resource-Controller parallel to the new Spring-Data-Rest provided one.
Whenever i configure spring-data-rest to use the same url as our existing controller ONLY the old controller is used and if the accept-header does not match i get an error response. when i use a different url, everything works
Is it possible to run a controller in parallel to the spring-data-rest one and respond based on the Accept-Header?
The old Controller:
@RepositoryRestController
@RequestMapping(value = "/api/accounts", produces = {"application/custom.account+json"})
public class AccountResource {
@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("#oauth2.hasScope('read') and hasRole('ROLE_ADMIN')")
public ResponseEntity<List<Account>> getAll(
@RequestParam(value = "page", required = false) Integer offset,
@RequestParam(value = "per_page", required = false) Integer limit,
@RequestParam(value = "email", required = false) String email
) throws URISyntaxException {
...
}
}
@RepositoryRestController
does not play well with @RequestMapping
at the type level.
First step, make sure you actually manage to catch the request, by removing the produces
parameter from the RequestMapping (I use the GetMapping shortcut here). I also removed the @PreAuthorize annotation for it's not relevant for now, and introduced a parameter to catch the Accept
header value (for debug):
@RepositoryRestController
public class AccountResource {
@GetMapping(value = "/api/accounts")
public ResponseEntity<List<Account>> getAll(
@RequestParam(value = "page", required = false) Integer offset,
@RequestParam(value = "per_page", required = false) Integer limit,
@RequestParam(value = "email", required = false) String email,
) throws URISyntaxException {
...
}
}
With this, you should be able to customize the GET /api/accounts at will and still benefit from POST/PUT/PATCH... /api/accounts provided automagically by Spring Data Rest, and also assert that content-type
If it works as expected, you can then:
- try to narrow the method scope with
produces = "application/custom.account+json"
(no braces required for a single value) in the GetMapping annotation, and see that both your endpoint and the Spring generated endpoint method are avaiable
- reinstate your @PreAuthorize annotation
- get rid of the @RequestHeader parameter
That gives you:
@RepositoryRestController // NO MAPPING AT THE TYPE LEVEL
public class AccountResource {
@GetMapping(value = "/api/accounts", // Mapping AT THE METHOD LEVEL
produces = "application/custom.account+json") // the content-type this method answers to
@PreAuthorize("#oauth2.hasScope('read') and hasRole('ADMIN')") // ROLE is 'ADMIN' not 'ROLE_ADMIN'
public ResponseEntity<List<Account>> getAll(
@RequestHeader("Content-Type") String contentType,
@RequestParam(value = "page", required = false) Integer offset,
@RequestParam(value = "per_page", required = false) Integer limit,
@RequestParam(value = "email", required = false) String email,
) throws URISyntaxException {
...
}
}
Now:
- curl host:port/api/accounts will hit the Spring controller endpoint
- curl host:port/api/accounts -H "Accept: application/custom.account+json" will hit your custom controller endpoint.