For CRUD operations, a PUT request to a URL is common and usually
overwrites the entire object. In our case however, this is not possible:
some object properties are read-only, and others can only be written if
the object has a certain status. So what we need is a _partial_ update.
And although it is usually possible to omit fields from the request body, this does not do what we want. What happens is
We’ve created an annotation
This controller method now only has to call the service method that updates the database. The code looks like this:
The examples in this article show that it is easy to extend the default Spring functionality to extract any information you want from the request. You can augment the existing functionality with, for example, JSR-303 validations. Or you can completely roll your own solution, including merging the request information with existing data. Combined with the generic Spring concept that any REST call is a method invocation, anything is possible. Your business needs are in control, not the technology.
And although it is usually possible to omit fields from the request body, this does not do what we want. What happens is
for missing fields, use the default value from the constructor. But what we want is:
for missing fields, to not change the value in the database.
We’ve created an annotation
@RequestEntity
to handle these parameters. Like @PathEntity
,
a URL template is tied to a domain entity, but now the request body is
used to update the (detached) record. An example usage would be:
1
2
3
4
5
|
@RequestMapping(value = "/", method = RequestMethod.PUT)
@ResponseBody
public Invoice updateInvoice(@RequestEntity("invoiceId") Invoice invoice) {
// ...
}
|
This controller method now only has to call the service method that updates the database. The code looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.jay.demo;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to indicate a method parameter should be bound to the web request body. Used for {@link
* org.springframework.web.bind.annotation.RequestMapping @RequestMapping} annotated methods.
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestEntity {
/**
* The name of the URL template that contains the .
*
* @return the name of the URL template that is the entity id
*/
String value();
}
|
CRUD applications
The provided examples show the building blocks to reduce a CRUD application to almost no code beyond searching:- Create
- The
@RequestBody
annotation combined with@Valid
(see the first example) ensure that the controller only needs to save the record. - Read
- The
@PathEntity
annotation in the second example already provides a loaded record, so the controller can simply return it. Only returning multiple records (i.e. searches) requires more code. - Update
- The
@RequestEntity
annotation in the third example provides a detached, updated and optionally validated record. This includes partial updates The controller method only has to save it. - Delete
- The
@PathEntity
annotation provides a record, so it can simply be removed.
Conclusion
The examples in this article show that it is easy to extend the default Spring functionality to extract any information you want from the request. You can augment the existing functionality with, for example, JSR-303 validations. Or you can completely roll your own solution, including merging the request information with existing data. Combined with the generic Spring concept that any REST call is a method invocation, anything is possible. Your business needs are in control, not the technology.
No comments:
Post a Comment