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.