RepositoryRestController cant handle complex object deserialization [DATAREST-687]
George T opened DATAREST-687 and commented
I am trying to override AppointmentRepository POST /appointments using a custom controller annotated with @RepositoryRestController.
@RepositoryRestResource(collectionResourceRel = "appointments", path = "appointments")
public interface AppointmentRepository extends CrudRepository<Appointment, Long> {
}
@RepositoryRestController
public class AppointmentController {
@Autowired
private AppointmentRepository appointmentRepository;
@RequestMapping(method = RequestMethod.POST, value = "/appointments")
public ResponseEntity<String> post(@RequestBody Appointment appointment) {
............
appointment = appointmentRepository.save(appointment);
HttpHeaders httpHeaders = new HttpHeaders();
return new ResponseEntity<>("{}", httpHeaders, HttpStatus.CREATED);
}
}
Appointment.java
@Entity
public class Appointment {
public Appointment() {
}
@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
Address address;
//Getters, Setters
}
Address.java
@Entity
public class Address {
@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
@OneToMany(mappedBy="address")
List<Appointment> appointment;
//Getters, Setters
}
When I post to /appointments the following
{ "address":"http://localhost:8080/addresses/1"}
I get
{
"timestamp": "2015-09-24T10:52:02.824+0000",
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read document: Can not instantiate value of type [simple type, class com.address.Address] from String value ('http://localhost:8080/addresses/1'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@674e5fc9; line: 1, column: 52] (through reference chain: com.appointment.Appointment[\"address\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.address.Address] from String value ('http://localhost:8080/addresses/1'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@674e5fc9; line: 1, column: 52] (through reference chain: com.appointment.Appointment[\"address\"])",
"path": "/appointments"
}
If I don't include the address property or use @RestController instead of @RepositoryRestController everything works as expected.
Is this expected behavior?
Affects: 2.2.2 (Evans SR2)
8 votes, 10 watchers
Ali Shahbour commented
Have you tried changing the Controller
@RequestMapping(method = RequestMethod.POST, value = "/appointments")
public ResponseEntity<String> post(@RequestBody Resource<Appointment> appointment) {
............
appointment = appointmentRepository.save(appointment);
HttpHeaders httpHeaders = new HttpHeaders();
return new ResponseEntity<>("{}", httpHeaders, HttpStatus.CREATED);
}
}
Robert Rackl commented
I am exposing my Repositores with @RepositoryRestResource (as spring-data-rest HATEOAS Resources) I do not have any RepositoryRestController. But I get the same error. How can I work around it?
Daniele Renda commented
I've the same problem and the workaround suggested doesn't work. If I follow that suggestion the Resource object has content null and empty links
What's wrong?
Ali Shahbour commented
Have you tried changing the Controller
@RequestMapping(method = RequestMethod.POST, value = "/appointments") public ResponseEntity<String> post(@RequestBody Resource<Appointment> appointment) { ............ appointment = appointmentRepository.save(appointment); HttpHeaders httpHeaders = new HttpHeaders(); return new ResponseEntity<>("{}", httpHeaders, HttpStatus.CREATED); } }
i did the same think here but it didn't work for me i'm using Spring Rest Data, any suggestion please ?
Resource has been renamed to EntityModel in HATEOAS