0
votes

I have a requirement wherein I have to have custom business logic in the POST, PATCH and PUT endpoints. Using SDR events is not a possibility since I would need to do a couple of transactional operation in the request. So, I decided to create my custom endpoint for the entity which is attached to the repository by a service class.

@RepositoryRestController
@RequestMapping("/myEntity")
@ExposesResourceFor(MyEntity.class)
public class MyEntityResource {
    @PostMapping(value = "", produces = MediaTypes.HAL_JSON_VALUE)
    public ResponseEntity postResult(@RequestBody Entity entity) {
        // my logic
    }
}

Now I am facing an issue where my POST request can have association links to other entities. The default implementation of SDR handles this gracefully but I am facing a Jackson mapping error.

JSON parse error: Cannot construct instance of `com.foo.bar.Entity` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('/api/v1/entity/12345678-1234-1234-1234-123456789012')

Thus I looked up how Spring's implementation is and I have found the following method

@ResponseBody
@RequestMapping(value = BASE_MAPPING, method = RequestMethod.POST)
public ResponseEntity<ResourceSupport> postCollectionResource(RootResourceInformation resourceInformation,
        PersistentEntityResource payload, PersistentEntityResourceAssembler assembler,
        @RequestHeader(value = ACCEPT_HEADER, required = false) String acceptHeader)

and I have found that the PersistentEntityResource payload gets populated with the fetched associated entity and the main entity gets saved by a normal save call to the repository.

So, I tried autowiring PersistentEntityResource but that fails essentially because the invoker of PersistentEntityResource expects the mapping url to be of the form /{repository}/<optional id> and as I already know what my path is, PersistentEntityResource is unable to initialise. It also doesn't help that PersistentEntityResource is not generic (it was upto SDR 2.0.0.M1 after which it was removed). Also being able to use PersistentEntityResource would have made implementing PATCH and PUT a lot easier too.

Is there any way to to handle this?

1
Event handlers are transactional. - Alan Hay
@AlanHay Are they under the same transaction as the SDR call itself? - Sayak Mukhopadhyay
The whole SDR request is embedded into a transaction via a filter. - Selindek

1 Answers

0
votes

I found the answer after some digging. On hindsight, it's pretty trivial. Just use Resource<Entity> instead of Entity in the method paramaters.

@RepositoryRestController
@RequestMapping("/myEntity")
@ExposesResourceFor(MyEntity.class)
public class MyEntityResource {
    @PostMapping(value = "", produces = MediaTypes.HAL_JSON_VALUE)
    public ResponseEntity postResult(@RequestBody Resource<Entity> entity) {
        // my logic. Fetch the entity with entity.getContent()
    }
}

You can fetch the entity itself using entity.getContent()