I'm working with DTOs in Spring and facing an issue with the use of an interface-based projection DTO while deserialization in the @RequestBody of a method of the Controller
class.
It looks like that the use of projection based DTOs only works in one direction. Getting a DTO from the repository is pretty easy and handy:
public interface ConditionRepository extends JpaRepository<Condition, Long> {
@Query("SELECT c FROM Condition c WHERE c.controller.id = ?1")
List<ConditionDto> findAllByControllerId(Long controllerId);
}
But if Spring tries to deserialize the same projection based DTO ConditionDto
in the Controller class
@RequestMapping(value = "/{id}/conditions", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.PUT)
public ResponseEntity<List<ConditionResult>> putConditions(@RequestBody List<ConditionDto> conditionList, @PathVariable("id") Long controllerId) {
System.out.print("conditionList: ");
System.out.println(conditionList);
return null;
}
it throws an error:
Type definition error: [simple type, class dev.smarthome.weatherstation.condition.dto.ConditionDto];
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `dev.smarthome.weatherstation.condition.dto.ConditionDto`
(no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types,
have custom deserializer, or contain additional type information
The error makes sense in that way that the DTO is an interface so Spring can not instantiate it.
What would be a good solution? Do I have to convert my implementation from projection based DTO to a class DTO so it can instantiate the DTO? Or did I forget something?
Thanks in advance for your help!
What you can do is write your own HttpMessageConverter and create new anonymous instances of your interface in there (basically deserializing the JSON manually and putting the corresponding fields in the getters). But I wouldn't recommend it.
Instead, ask yourself : why is this Dto an interface ? In the case of a projection it makes sense, but projections are meant to be read, not written.
So it seems you have two solutions