Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotated detection strategy breaks URL detection on a HATEOAS Resource [DATAREST-1195] #1515

Open
spring-projects-issues opened this issue Feb 8, 2018 · 1 comment
Assignees
Labels
in: repository type: bug type: documentation

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Feb 8, 2018

Rafael Renan Pacheco opened DATAREST-1195 and commented

Hi there!

When setting the ANNOTATED property for the repository detection strategy breaks the Resource<MyEntity> param on a @RestController endpoint. This happens if the @RequestBody payload has a foreign key reference, which should be referenced as an URL. The exception message is the following:

"JSON parse error: Can not construct instance of com.myproject.entity.ParentEntity: no String-argument constructor/factory method to deserialize from String value ('parent/3');
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.myproject.entity.ParentEntity:
no String-argument constructor/factory method to deserialize from String value ('parent/3')\n
at [Source: java.io.PushbackInputStream@12de10ef; line: 6, column: 1] (through reference chain: com.myproject.entity.ParentEntity[\"parentEntity\"])"

If I unset the detection strategy to use it's default value, the issue is gone and Spring Data Rest is able to find the parent entity just fine.

Here is some snippets to better understand the current situation:

This is the JSON that is POSTed to the /users endpoint to create some user. Note that the foreign key profile is referenced by a URL, since we are using HATEOAS:

{
	"profile": "profiles/1",
	"name": "Some User",
	"username": "some@email.com",
	"password": "password"
}

This is the UserRepository:

public interface UserRepository extends JpaRepository<User, Integer> {
}

This is the UserController (the ProfileController and CRUD endpoints also exists):

@RestController
@RequestMapping("/users")
public class UserController {

    private UserRepository userRepository;

    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @GetMapping("")
    public ResponseEntity<PagedResources<UserResource>> all(Pageable page,
                                                            PagedResourcesAssembler<User> assembler) {
        // find all and return, working fine
    }

    @GetMapping("{id}")
    public ResponseEntity<UserResource> get(@PathVariable Integer id) {
        // fine one and return, working fine
    }

    // Here the Resource<User> breaks if ANNOTATED strategy is used.
    @PostMapping("")
    public ResponseEntity<Void> create(@RequestBody Resource<User> userResource) {
        User user = userResource.getContent();

        userRepository.save(user);

        // and return with some location header
    }

    @PatchMapping("{id}")
    public ResponseEntity<Void> update(@RequestBody Resource<User> userResource, @PathVariable Integer id) {
        // same issue here because of Resource<>
    }

    @DeleteMapping("{id}")
    public ResponseEntity<Void> delete(@PathVariable Integer id) {
        // delete one, working fine
    }
}

In this project I need all my endpoints to be @RestController, and I can't have any endpoint generated by the JPA Repositories. I need @RestController to create custom endpoints beyond the CRUD ones, and also to write business logic on the CRUD endpoints. For now I have to be very careful when creating an JPA Repository, because I'm using the default detection strategy, which exposes lots of JPA Repositories endpoints that are not shadowed by a full CRUD from a @RestRepository.

Question: Is disabling Resource URL references expected when using ANNOTATED strategy, or could this be a bug?

Extra question: The documentation lists an ANNOTATION option for the detection strategy, but this enum doesn't exist. Just ANNOTATED works for now.

Dependencies:

[INFO] +- org.springframework.boot:spring-boot-starter-data-rest:jar:1.5.10.RELEASE:compile
[INFO] |  \- org.springframework.data:spring-data-rest-webmvc:jar:2.6.10.RELEASE:compile
[INFO] |     \- org.springframework.data:spring-data-rest-core:jar:2.6.10.RELEASE:compile

Affects: 2.6.10 (Ingalls SR10)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Feb 8, 2018

Rafael Renan Pacheco commented

I think I am on the wrong path here.

To handle HATEOAS hassle free, wouldn't be better to stick with @RepositoryRestController and handle the business logic using data rest events? Something like BeforeSaveEvent, run some logic?

Another change would be to add custom links to those entities, but this is another story.

Best regards,
Rafael Pacheco

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: repository type: bug type: documentation
Projects
None yet
Development

No branches or pull requests

2 participants