Reputation: 11467
I have a Spring Boot
REST application which also include dependencies to spring-boot-starter-data-jpa
and spring-hateoas
.
My issue is want to convert a JSON payload being posted to my server.
The payload contains data to create a new Product
with a relation to a existing VAT Rate
.
This relation is modeled using a JPA @ManyToOne like:
@NotNull
@ManyToOne(fetch = FetchType.EAGER)
private VatRate vatRate;
When I post something like:
{
"description": "bla",
"price": 99.99,
"vat_rate": {
"id": 1
}
Jackson automatically converts I can persist a new Product with a relation to the given VAT Rate.
However as I'm using HATEOAS I think I should use something like:
{
"description": "bla",
"price": 99.99,
"vat_rate": {
"id": "http://somehost/vat-rates/1"
}
But this one fails as Jackson cannot convert it.
Is there a easy solution for this? As HATEOAS is not a solid requirement in my case, if this is not possible easily it will put a to high burden to use HATEOAS.
Next to that if in first example I provide a unknown vat_rate id Boot gives me back a 500.
Reason is that Jackson references/creates a VAT Rate
which does not exists and when trying to store the Product
a FK violation happens resulting in the 500 due to a org.hibernate.exception.ConstraintViolationException.
I think it would be better to return a 400 pointing out that vat_rate does not exists.
But probably I have to check the existence of the VAT Rate
manually before saving the Product
.
Upvotes: 1
Views: 651
Reputation: 116171
In this situation, I like to use a separate DTO that's passed into my controller methods, rather than trying to reuse the JPA entity. In this scenario I'd create a ProductInput
class with three properties:
class ProductInput {
private String description;
private String price;
private URI vatRate;
}
The vatRate
property is a URI
as it's referencing an existing VAT rate resource and, when you're using hypermedia, a URI is a resource's id.
In your controller you then need to use this URI
to look up a VatRate
instance. You can use UriTemplate
to extract the id from the URI
and then use the id to look it up. Something like this:
String idString = new UriTemplate(/vat-rates/{id})
.match(productInput.getVateRate().toASCIIString()).get("id");
long id = Long.valueOf(idString);
VatRate vatRate = vatRateRepository.findById(id);
if (vatRate == null) {
// Return an appropriate error response, probably a 400
// …
} else {
// Create and save the product
// …
}
I've got a very basic app that uses Spring HATEOAS on Github that might provide some useful further reading.
Upvotes: 1