When I use Lombok in my Spring Data REST application to define complex types like:
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(name = "BOOK")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Long id;
    private String title;
    @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
    private Person author;
    // ...
}
with a Spring Data REST controllers like:
@RepositoryRestController
public class BookRepositoryRestController {
    private final BookRepository repository;
    @Autowired
    public BookRepositoryRestController(BookRepository repository) {
        this.repository = repository;
    }
    @RequestMapping(method = RequestMethod.POST,value = "/books")
    public @ResponseBody PersistentEntityResource post(
        @RequestBody Book book,
        PersistentEntityResourceAssembler assembler) {
        Book entity = processPost(book);
        return assembler.toResource(entity);
    }
    private Book processPost(Book book) {
        // ...
        return this.repository.save(book);
    }
}
I get an ugly error:
no String-argument constructor/factory method to deserialize from String value
from Spring Data REST's use of Jackson with a Book POST like:
curl -X POST 
     -H 'content-type: application/json' 
     -d '{"title":"Skip Like a Pro", "author": "/people/123"}'
     http://localhost:8080/api/books/
The de-serialization error happens when Jackson tries to resolve the /people/123 local URI which should resolve to a single, unique Person. If I remove my @RepositoryRestController, everything works fine. Any idea what's wrong with my REST controller definition?
In the @RepositoryRestController, change the type of the @RequestBody argument from Book to Resource<Book>:
import org.springframework.hateoas.Resource;
    // ...
    @RequestMapping(method = RequestMethod.POST,value = "/books")
    public @ResponseBody PersistentEntityResource post(
        @RequestBody Resource<Book> bookResource,             // Resource<Book>
        PersistentEntityResourceAssembler assembler) {
        Book book = bookResource.getContent()
        // ...
    }
and in the Book entity definition modify the AllArgsConstructor annotation to be: @AllArgsConstructor(suppressConstructorProperties = true).
See Spring Data REST #687 for more information.
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