I have a Car
entity. I want to expose its data in a REST API. I'm currently using Spring Data REST to do this. After reading this post, I became comfortable doing this instead of creating a CarDto
and passing an instance of that back to the client:
The Car
Entity
@Entity
@Data
public class Car {
@Id
private Long id;
private BigDecimal askingPrice;
// other fields
}
Spring Data Repository
public interface CarRepository extends CrudRepository<Car, Long> {
}
Gradle file has the following dependency to enable clients to access Car
s at /api/cars
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
Now, I have a new Car
property. Its value is not stored in the same database as Car
entity. I get its value from a web service. I seem to be in a similar situation that is described in this post that advocates the use of DTOs.
Do I need to abandon Spring Data REST?
I know that I can modify my Car
entity to include this new field as a transient...
@Entity
@Data
public class Car {
@Id
private Long id;
private BigDecimal askingPrice;
// Value is populated from a web service
@Transient
private BigDecimal kellyBlueBookPrice;
// other fields
}
But is that a good approach? Is there a way to have Spring Data REST return some form of a DTO that includes this new property? It's possible that a few other fields may be added in the future from other data sources.
Is there a way to have Spring Data REST return some form of a DTO that includes this new property?
No way directly you can achieve this. But you need to write some code where it can get data and convert it to DTO. Also using this approach URL will be not the same it will be changed as if you still using spring-data-rest.
There is a sample given at https://stackoverflow.com/a/45401735. But it's using the old version and is not compatible with the new spring-data-rest.
The best would be to use DTO and not directly use spring data rest implementation if you have changes in response. Some of the scenarios you can consider:
To avoid boilerplate code converting Entity to DTO and vice-versa. You can use some libraries like MapStruct, ModelMapper.
MapStruct example
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class CarMapper {
public abstract CarDto carToCarDto(Car car);
@InheritInverseConfiguration
public abstract Car carDtoToCar(CarDto carDto);
}
By using DTO you can have a separate service layer where you can manage database transactions to do operations in multiple tables. You can control how much information is exposed through REST.
If you want to use the same response for operations then you can use spring-hateoas which will have _embedded/_links object.
I completely disagree with the post you refer. I think you need to understand that we are talking about several layers here if we are talking about a properly designed application: presentation (REST webservices), application services - domain services, repositories, aggregates and entities - ORM repositories and entities - database code e.g. SQL plus you can add access control and logging for any of these.
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
"The goal of Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores."
So what Spring Data repositories do is the "ORM repositories and entities - database code e.g. SQL" part of the story and what REST does is the "presentation (REST webservices)" part of the story. They are very far from each other. When you are able to simply generate the code between them, then it is a sign, that something is off with your project, because it does not do much beyond data storage and retrieval. Currently there are databases with HTTP CRUD interface which do the exact same thing. I think there is a widespread confusion that REST resources represent database entities, while they represent a bunch of callable operations on a webservice.
If you write this kind of application, then at least generate the actual code with DTOs instead of completely relying on limited frameworks and their annotations, otherwise you will hit the wall when you are trying to do something, which is a real service, not just data storage. And don't believe everything others write on stack overflow. Maybe I am wrong to...
Another thing worth to mention here, that even if we are talking about data storage, REST serves some sort of view model, which should have a structure for displaying the data instead of the structure for storing the data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With