I have a Spring project with spring-data-rest
as a dependency. I have quite a number of repositories in my project, which spring-data-rest
automatically created REST API endpoints for. This suited my needs pretty well until now. Now I have a requirement to change the default functionality of one endpoint for all my repositories, specifically, /BASE_PATH/REPOSITORY
. This path responds with a paged list of all records of my db.
Now I want to reimplement this endpoint for all my repositories. This is where I am hitting a roadblock. I tried
@RestController
public class MyTableResource {
private MyTableService myTableService;
@Autowired
public MyTableResource(MyTableService myTableService) {
this.myTableService = myTableService;
}
@GetMapping(value = "/api/v1/myTables", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity getMyTables(@QuerydslPredicate(root = MyTable.class) Predicate predicate) throws NoSuchMethodException {
// My custom implementation
}
}
Now this somewhat works but the problem is I need to write almost the same code for all my repositories. I tried @GetMapping(value = "/api/v1/{repository}", produces = MediaTypes.HAL_JSON_VALUE)
but this is also matching /api/v1/notarepository
which I have implemented separately.
Also, even if I do @GetMapping(value = "/api/v1/{repository}", produces = MediaTypes.HAL_JSON_VALUE)
I would like to get a handle to a repository object (MyTable
) using {repository}
path variable, which would be myTables
in this case.
In short, I want to write a single custom controller for all my repositories, since the logic would be the same for each of them, while making sure the correct repository is called based on the path called also making sure that any path variables I introduce does not hide other controller classes I have written.
More things I have tried
I was attempting to get paged HATEOAS resource objects automatically from my list of entities. For this I found that I can use PagedResourceAssembler
@RestController
public class MyTableResource {
private MyTableService myTableService;
@Autowired
public MyTableResource(MyTableService myTableService) {
this.myTableService = myTableService;
}
@GetMapping(value = "/api/v1/myTables", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity getMyTables(@QuerydslPredicate(root = MyTable.class) Predicate predicate, PagedResourcesAssembler<Object> pagedResourcesAssembler) throws NoSuchMethodException {
// My custom implementation
return ResponseEntity.ok(pagedResourcesAssembler.toResource(myTableList);
}
}
This gives me a good response with the required links for the page but does not give links per entity. Then I found I can hook up PersistentEntityResourceAssembler
and pass it to toResource
above so I did
@RestController
public class MyTableResource {
private MyTableService myTableService;
@Autowired
public MyTableResource(MyTableService myTableService) {
this.myTableService = myTableService;
}
@GetMapping(value = "/api/v1/myTables", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity getMyTables(@QuerydslPredicate(root = MyTable.class) Predicate predicate, PagedResourcesAssembler<Object> pagedResourcesAssembler, PersistentEntityResourceAssembler assembler) throws NoSuchMethodException {
// My custom implementation
return ResponseEntity.ok(pagedResourcesAssembler.toResource(myTableList, assembler);
}
}
This does not work as reported in How to have PersistentEntityResourceAssembler injected into request methods of custom @RepositoryRestController in a @WebMvcTest unit test .
It kind of works if I replace @RestController
with RepositoryRestController
but then Predicate
stops working as mentioned in https://jira.spring.io/browse/DATAREST-838 .
So, I tried using @QuerydslPredicate RootResourceInformation resourceInformation
instead of @QuerydslPredicate(root = MyTable.class) Predicate predicate
. This also did not work as my controller endpoint does not have /{repository}
in it.
Then I tried setting @GetMapping(value = "/{repository}" produces = MediaTypes.HAL_JSON_VALUE)
. This threw a mapping conflict error.
So I am completely stuck as to what to do next.