Can I make a custom controller mirror the formatting of Spring-Data-Rest / Spring-Hateoas generated classes?

后端 未结 3 1387
独厮守ぢ
独厮守ぢ 2020-11-29 20:29

I\'m trying to do something I think should be really simple. I have a Question object, setup with spring-boot, spring-data-rest and spring-hateoas. All the basi

相关标签:
3条回答
  • 2020-11-29 20:58

    I believe I've solved this problem in a fairly straightforward way, although it could have been better documented.

    After reading the implementation of SimplePagedResourceAssembler I realized a hybrid solution might work. The provided Resource<?> class renders entities correctly, but doesn't include links, so all you need to do is add them.

    My QuestionResourceAssembler implementation looks like this:

    @Component
    public class QuestionResourceAssembler implements ResourceAssembler<Question, Resource<Question>> {
    
        @Autowired EntityLinks entityLinks;
    
        @Override
        public Resource<Question> toResource(Question question) {
            Resource<Question> resource = new Resource<Question>(question);
    
            final LinkBuilder lb = 
                entityLinks.linkForSingleResource(Question.class, question.getId());
    
            resource.add(lb.withSelfRel());
            resource.add(lb.slash("answers").withRel("answers"));
            // other links
    
            return resource;
        }
    }
    

    Once that's done, in my controller I used Option 2 above:

        return pagedResourcesAssembler.toResource(page, questionResourceAssembler);
    

    This works well, and isn't too much code. The only hassle is you need to manually add links for each reference you need.

    0 讨论(0)
  • 2020-11-29 21:08

    Updated answer on this old question: You can now do that with a PersistentEntityResourceAssembler

    Inside your @RepositoryRestController:

    @RequestMapping(value = "somePath", method = POST)
    public @ResponseBody PersistentEntityResource postEntity(@RequestBody Resource<EntityModel> newEntityResource, PersistentEntityResourceAssembler resourceAssembler)
    {
      EntityModel newEntity = newEntityResource.getContent();
      // ... do something additional with new Entity if you want here ...  
      EntityModel savedEntity = entityRepo.save(newEntity);
    
      return resourceAssembler.toResource(savedEntity);  // this will create the complete HATEOAS response
    }
    
    0 讨论(0)
  • 2020-11-29 21:22

    I've found a way to imitate the behavior of Spring Data Rest completely. The trick lies in using a combination of the PagedResourcesAssembler and an argument-injected instance of PersistentEntityResourceAssembler. Simply define your controller as follows...

    @RepositoryRestController
    @RequestMapping("...")
    public class ThingController {
    
        @Autowired
        private PagedResourcesAssembler pagedResourcesAssembler;
    
        @SuppressWarnings("unchecked") // optional - ignores warning on return statement below...
        @RequestMapping(value = "...", method = RequestMethod.GET)
        @ResponseBody
        public PagedResources<PersistentEntityResource> customMethod(
                ...,
                Pageable pageable,
                // this gets automatically injected by Spring...
                PersistentEntityResourceAssembler resourceAssembler) {
    
            Page<MyEntity> page = ...;
            ...
            return pagedResourcesAssembler.toResource(page, resourceAssembler);
        }
    }
    

    This works thanks to the existence of PersistentEntityResourceAssemblerArgumentResolver, which Spring uses to inject the PersistentEntityResourceAssembler for you. The result is exactly what you'd expect from one of your repository query methods!

    0 讨论(0)
提交回复
热议问题