Reputation: 15
So I'm trying to use Spring Data JPA to make some rest services using the repository interfaces. But I'm stuck trying to do something without having to create a custom controller.
Suppose this service only accepts PUT and GET requests. The PUT requests are used to create and update the resource. So the ID is generated client side.
The entity and repository would be something like this:
@Entity
public class Document {
@Id
private String name;
private String text;
//getters and setters
}
@RepositoryRestResource(collectionResourceRel = "documents", path = "documents")
public interface DocumentRepository extends PagingAndSortingRepository<Document, String> {
}
When I try to make a PUT request @ localhost:8080/documents/foo with the following body:
{
"text": "Lorem Ipsum dolor sit amet"
}
I get this message:
{
"timestamp": 1474930016665,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.orm.jpa.JpaSystemException",
"message": "ids for this class must be manually assigned before calling save(): hello.Document; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): hello.Document",
"path": "/documents/foo"
}
So I have to send in the body:
{
"name": "foo",
"text": "Lorem Ipsum dolor sit amet"
}
so it returns 201 Created with
{
"text": "Lorem Ipsum dolor sit amet",
"_links": {
"self": {
"href": "http://localhost:8080/documents/foo"
},
"document": {
"href": "http://localhost:8080/documents/foo"
}
}
}
Is it possible to make the PUT without having to send the id (the name field) inside json body? Since I'm already sending it in the URI?
I know that I can create a RestController and some requestmapping with a /documents/{document.name}, and use it to set the name field before saving it, but I wanted to know if there is any annotation or something.
Upvotes: 1
Views: 2095
Reputation: 17065
You could define an @HandleBeforeCreate
/ @HandleBeforeSave
method to alter the model just before saving it:
@Component
@RepositoryEventHandler(Document.class)
public class DocumentBeforeSave {
@Autowired
private HttpServletRequest req;
@HandleBeforeCreate
public void handleBeforeSave(Document document) {
if("PUT".equals(req.getMethod())){
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf('/') + 1);
document.setName(uri);
}
}
}
POST
and PUT
will trigger the @HandleBeforeCreate
method (if the body contained an id
, a PUT
request would rather trigger the @HandleBeforeSave
).RequestMethod
is PUT
before assigning the id
(in order to leave the POST
body unchanged).HttpServletRequest
is injected as a proxy and can be used by multiple threads. Read this : Can't understand `@Autowired HttpServletRequest` of spring-mvc wellUpvotes: 2