Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring how to resolve entity uri in @RepositoryRestController

I'm using Spring boot 1.5.3, Spring Data REST, Spring HATEOAS. Spring Data REST is amazing and does a perfect job, but sometimes it's needed custom business logic and therfore I need to create a custom controller.

I'm going to use a @RepositoryRestController to benefit of Spring Data REST functionality (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.overriding-sdr-response-handlers).

Because Spring Data REST use HATEOAS by default, I'm using that. I need a controller like this:

@RepositoryRestController
@RequestMapping(path = "/api/v1/workSessions")
public class WorkSessionController {

    @Autowired
    private EntityLinks entityLinks;

    @Autowired
    private WorkSessionRepository workSessionRepository;

    @Autowired
    private UserRepository userRepository;

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(method = RequestMethod.POST, path = "/start")
    public ResponseEntity<?> start(@RequestBody(required = true) CheckPoint checkPoint) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (checkPoint == null) {
            throw new RuntimeException("Checkpoint cannot be empty");
        }

        if (workSessionRepository.findByAgentUsernameAndEndDateIsNull(auth.getName()).size() > 0) {
            // TODO return exception
            throw new RuntimeException("Exist a open work session for the user {0}");
        }

        // ...otherwise it's opened a new work session
        WorkSession workSession = new WorkSession();
        workSession.setAgent(userRepository.findByUsername(auth.getName()));
        workSession.setCheckPoint(checkPoint);
        workSession = workSessionRepository.save(workSession);

        Resource<WorkSession> resource = new Resource<>(workSession); 
        resource.add(entityLinks.linkFor(WorkSession.class).slash(workSession.getId()).withSelfRel());
        return ResponseEntity.ok(resource);
    }
}

Because the parameter CheckPoint must be an existant resource, I want the client send the link of the resourse (like you can do in Spring Data REST POST methods). Unfortunately when I try to do that, server side I receive an empty CheckPoint object.

I already read Resolving entity URI in custom controller (Spring HATEOAS) and converting URI to entity with custom controller in spring data rest? and expecially Accepting a Spring Data REST URI in custom controller.

I'm wondering if there is a best practice to do this avoiding to expose id to the client, followind so the HATEOAS principles.

like image 618
drenda Avatar asked Sep 05 '25 03:09

drenda


1 Answers

Try to change you controller like this:

@RepositoryRestController
@RequestMapping(path = "/checkPoints")
public class CheckPointController {

    //...

    @Transactional
    @PostMapping("/{id}/start")
    public ResponseEntity<?> startWorkSession(@PathVariable("id") CheckPoint checkPoint) {

        //...           
    }
}

That will mean: "For CheckPoint with given ID start new WorkSession". Your POST request will be like: localhost:8080/api/v1/checkPoints/1/start.

like image 192
Cepr0 Avatar answered Sep 07 '25 17:09

Cepr0