14

I'm developing a component based CRUD application using Spring Data JPA and Spring Data REST. I have several components. For example system component has the User model and the UserRepository. Components are differenciated by the package names. like com.example.app.<component_name>

So to make my REST API look cleaner, I need to implement the API URL as below.

host:8080/<component_name>/<model_collection_name>

for example

host:8080/system/users

I did the following in my repository

@RepositoryRestResource(collectionResourceRel = "users", path = "system/users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
   ...
}

this generates the following, when I goto http://localhost:8080

{
   "_links": {
   "users": {
   "href": "http://localhost:8080/system/users{?page,size,sort}",
    "templated": true
},
...

But when I goto http://localhost:8080/system/users

It gives an error

Fri May 22 17:56:37 IST 2015 There was an unexpected error (type=Not Found, status=404). No message available

NOTE : If I mapped the path to system-users then it works fine, but when I use a / in the path such as system/users, it breaks and gives the error.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
Faraj Farook
  • 14,385
  • 16
  • 71
  • 97

2 Answers2

15

tl;dr

Not supported.

Details

Generally speaking: don't focus on designing URLs. The structure of a URI must not matter to a REST client by definition:

At no time whatsoever do the server or client software need to know or understand the meaning of a URI -- they merely act as a conduit through which the creator of a resource (a human naming authority) can associate representations with the semantics identified by the URI.

(from Roy Fielding - Architectural Styles and the Design of Network-based Software Architectures - Section 6.2.4)

If you follow that criteria, you take care of choosing relation names, design the representations for the resources you expose etc.

That said, what you're looking for is currently not supported. If you think it's worthwhile adding this feature (I think it's not, due to the argument given above), feel free to open a ticket in our bug tracker.

It's probably quite tricky to implement due to the way Spring MVC mapping works and especially the combination of mapping of singular path segments and non-singular ones could cause some ambiguities. All of that makes it rather unlikely this request will get followed up on.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
  • Your argument seems valid, but nevertheless this doesn't solve my issue. I'm doing a technical feasibility study on developing a huge multi component ERP like application. Anyhow thanks allot for the time and effort you put in to answer this question. If possible please consider to fix this in future releases, as it might help others like me. I created an issue in Jira https://jira.spring.io/browse/DATAREST-555 – Faraj Farook May 26 '15 at 03:01
  • 5
    In that case do Spring Data Rest is not suitable for API versioning? – IllSc Nov 30 '15 at 03:25
  • @IllSc you can version your api by modifying the base path via the spring.data.rest.base-path property in your application.properties. – Miguel Pereira Aug 24 '17 at 01:27
  • 1
    @MiguelPereira this is not a good solution since if you change the base path, your last one will not work anymore. And the reason for using API versioning is the ability to deliver more than one version at the same time. – Felipe Desiderati Mar 26 '20 at 02:14
  • @FelipeDesiderati I used a new Spring Boot app for each new version. With dependencies on shared modules. So all API versions work just fine :). With added benefits like clean code, independent scaling, and development of each version. Love Spring but may have move to something new in the next project. Slow startup times = high operational cost in the public clouds. – Miguel Pereira Mar 27 '20 at 19:32
  • 1
    @MiguelPereira I still do not agree with this solution, it would be enough in the beginning but with time it will be impracticable. You will have to create a whole new infrastructure for each version. Suppose if you use AWS and you are going to serve all versions with the same host address: or you will have to define your custom reverse proxy; or a new rule in the ELB to point to the new version /v2; or use API Gateway. It doesn't matter how optimal your infra is, for each new version you still need to duplicate some infra configuration. I would prefer not to use Spring Data Rest in this case. – Felipe Desiderati Mar 27 '20 at 20:39
1

I think this (or: a similar) question was already answered here on stackoverflow.

Set the base uri using a custom RepositoryRestMvcConfiguration class.

Community
  • 1
  • 1
Andreas Aumayr
  • 1,006
  • 1
  • 11
  • 17
  • 2
    Thank you for the answer. But It's not the base URL im trying to change here. I can do this simply by adding a `spring.data.rest.baseUri=api` to my `application.properties` file in spring-boot. I need to have slashes in the path which i'm trying to expose as the rest links. – Faraj Farook May 24 '15 at 15:30
  • 2
    Or is there any way to have multiple base uris for the rest data for my each component. – Faraj Farook May 24 '15 at 15:31
  • so your goal is to provide two restful endpoints (component A and B, like "system") and each of them may have several repositories (repA1, repA2, ..., like "users") beneath..? http://localhost:8080/A/repA1 http://localhost:8080/A/repA2 http://localhost:8080/B/repB1 Does a component itself contain any logic or is it just a way to structure your application? – Andreas Aumayr May 24 '15 at 16:16
  • Just found another stackoverflow post. I think this one is similar to yours, but there was no solution provided: http://stackoverflow.com/questions/26808697/spring-data-rest-issue-on-rest-resource-mapping – Andreas Aumayr May 24 '15 at 16:31
  • Seems that the developers of spring-data-rest did not intend to support your scenario. This issue relates to your problem: https://jira.spring.io/browse/DATAREST-79 (you may also have a look at the comments beneath!) – Andreas Aumayr May 24 '15 at 17:05
  • 1
    Thank you again for the effort you are putting in. Components has their own logic. I have components such as `system (the core framework)`, `distribution`, `finance`, `HR` etc.. Spring doesnt let me reach what I wanted to do. Seems like i have to dump spring data rest and go for something else. – Faraj Farook May 25 '15 at 06:49