1

In my Spring Boot web application I have a JPA entity Medium that records information about uploaded files.

I have a basic Spring Data Rest repository to handle the generic operations:

@RepositoryRestResource(path = "/media")
public interface MediumRepository extends CrudRepository<Medium, Long> {
}

However, I need the client to upload a file using HTTP multipart upload, then create a Medium record and return it in the response. The structure of the response should be the same as calling repository.save(). What I cannot figure out is how to have the HATEOAS metadata added. Obviously, if I just return

return mediumRepository.save(medium);

it will return a basic JSON representation of the entity, no HATEOAS. I already learned that I should probably use a PersistentEntityResourceAssembler.

So, my current controller code is:

@RestController
@RequestMapping("/upload")
public class MediaEndpoint {

    @Autowired
    private MediumRepository mediumRepository;

    @RequestMapping(method = POST)
    public PersistentEntityResource uploadMedium(
            @RequestPart MultipartFile data,
            PersistentEntityResourceAssembler persistentEntityResourceAssembler) {

        Medium medium = new Medium();
        // setup of the medium instance
        Medium savedMedium = mediumRepository.save(medium);
        return persistentEntityResourceAssembler.toResource(savedMedium);
    }
}

However, I cannot get the persistentEntityResourceAssembler injected into the method - I'm getting

Failed to instantiate [org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.<init>()

How can I implement this?

Community
  • 1
  • 1
Adam Michalik
  • 9,678
  • 13
  • 71
  • 102

2 Answers2

2

Following Cepr0's answer, I changed my controller to a @RepositoryRestController, but I got an exception

Circular view path [upload]: would dispatch back to the current handler URL [/upload] again.
Check your ViewResolver setup! (Hint: This may be the result of an unspecified view,
due to default view name generation.)

I found that RepositoryRestControllers are not annotated with @ResponseBody and should return a ResponseEntity, so I changed my code to the following:

@RepositoryRestController
@RequestMapping("/upload")
public class MediaEndpoint {

    @Autowired
    private MediumRepository mediumRepository;

    @RequestMapping(method = POST)
    public ResponseEntity<PersistentEntityResource> uploadMedium(
            @RequestPart MultipartFile data,
            PersistentEntityResourceAssembler persistentEntityResourceAssembler) {

        Medium medium = new Medium();
        // setup of the medium instance
        Medium savedMedium = mediumRepository.save(medium);
        return ResponseEntity.ok(persistentEntityResourceAssembler.toResource(savedMedium));
    }
}

This gives me a nice JSON response with HATEOAS metadata.

Alternatively, annotating the method or the controller with @ResponseBody works the same way.

Community
  • 1
  • 1
Adam Michalik
  • 9,678
  • 13
  • 71
  • 102
1

Try to use @RepositoryRestController instead of @RestController.

Cepr0
  • 28,144
  • 8
  • 75
  • 101