spring-projects / spring-projects/spring-data-rest

Behavior of @RestResource is inconsistent/confusing [DATAREST-1517]

Open
#1,823 0 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 31, 2020.

type: bug
Dominant language
Java
Stars
958
Forks
568
PR merge metrics
No merged PRs in 30d

Description

jvanheesch opened DATAREST-1517 and commented

This issue was discussed on Gitter.

The annotation @RestResource(exported=false) has the following effect:

  1. Placed on association (e.g. book.author):
    the association resource is not exported: requests to the corresponding uri (/books/\{id}/author) result in 404.
  2. Placed on query method (e.g. bookRepository.findAllByAuthorId()):
    the query method resource is not exported: requests to the corresponding uri (/books/search/findAllByAuthorId) result in 404.
  3. Placed on "special crud method" (e.g. bookRepository.findById(), see DefaultCrudMethods):
    the resource is still exported (no 404), instead the corresponding http method is disabled (405).

The behavior of 3 significantly differs from that of 1 and 2: @RestResource cannot be used to not-export the item resource, it can only be used to modify the exposure of http methods.
This leads to confusion, as demonstrated by this question on Stack Overflow, where findById() is not even declared yet an item resource is exported.
In addition, when annotating bookRepository.findById() with @RestResource(exported=false):

  • PUT/PATCH/DELETE to item resource are still supported if their corresponding methods are not explicitly annotated (and default exposure is used)
  • The item's association resources (e.g. /books/\{id}/publisher) are still exported (GET /books/\{id}/publisher) still returns the book's publisher).

These 3 cases are demonstrated by unit tests (see reference url).
I don't have a detailed proposal for how things should work, but I do think the current functionality is confusing and should be reconsidered.

Side note: there is some other 404/405 behavior that seems strange to me (not demonstrated in reproducer):

  • PUT/PATCH/DELETE to collection resource results in 404 (whereas I'd expect 405, as the uri exists)
  • POST to item resource results in 404 (whereas I'd expect 405, as the uri exists)
  • As demonstrated by the earlier Stack Overflow question, PUT/PATCH to item resource results in 500 if findById() is not declared, yet DELETE results in 405.
    This is due to && crudMethods.hasFindOneMethod() in DefaultExposureAwareCrudMethods.exposesDelete.
    We can't do something similar for DefaultExposureAwareCrudMethods.exposesSave, as exposesSave is also used for POST to collection resource (create).
    This does not seem like a big deal to me, but it does show that the && crudMethods.hasFindOneMethod() logic in DefaultExposureAwareCrudMethods.exposesDelete may be kind of a smell

Reference URL: https://github.com/jvanheesch/spring-data-rest-404-405

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.