Implementing UPDATE operation
Table of contents
In this step, you'll write a method for updating a blog post. By completing this step, you'll learn to map your service with the HTTP PUT (@Put) method, use parameter injection, and convert request body into a Java object using a request object (@RequestObject).
What you need
You need to have the following files obtained from previous steps. You can always download the full version, instead of creating one yourself.
Main.javaBlogPost.javaBlogService.javaBlogServiceTest.java
1. Map HTTP method
Let's start mapping the HTTP PUT method with our service method:
- Declare a service method,
updateBlogPost(), in the classBlogService. - Map this service method with the HTTP PUT method by adding the
@Putannotation. - Bind the endpoint
/blogsto the method.
import com.linecorp.armeria.server.annotation.Put;
public final class BlogService {
...
@Put("/blogs")
public void updateBlogPost(int id, BlogPost blogPost) {
// Update a blog post
}
}2. Handle parameters
For updating a blog post, let's take a blog post ID (id) and new blog post information to update with. For creating a blog post, we've used Armeria's RequestConverter to convert a request body into a Java object. For a change, let's try using @RequestObject to convert a request body.
Take in the ID value as a path parameter by adding
/blogs/:idto the@Putannotation.Inject the path parameter to the service method by annotating the parameter with
@Param.Convert request body into a Java object by annotating the
BlogPostparameter with@RequestObject.BlogService.javaimport com.linecorp.armeria.server.annotation.Param; import com.linecorp.armeria.server.annotation.RequestObject; public final class BlogService { ... // Instructions 1 to 3 @Put("/blogs/:id") public void updateBlogPost(@Param int id, @RequestObject BlogPost blogPost) { // Update a blog post } }For conversion, annotate blog post constructor to map JSON object keys to blog post object members. You can find more information on
@JsonCreatorhere.BlogPost.javaimport com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public final class BlogPost { ... @JsonCreator BlogPost(@JsonProperty("id") int id, @JsonProperty("title") String title, @JsonProperty("content") String content) { ... } }
3. Implement service code
In this step, write the code required for service itself. You need to update the information contained in the blogPosts map. In real services, you'll be retrieving and updating the blog post information from and to a database.
To update a blog post, copy the following code inside the updateBlogPost() method.
@Put("/blogs/:id")
public void updateBlogPost(@Param int id, @RequestObject BlogPost blogPost) {
BlogPost oldBlogPost = blogPosts.get(id);
// Check if the given blog post exists
if (oldBlogPost == null) {
// Return a Not Found error. See the next section for instructions
}
BlogPost newBlogPost = new BlogPost(id, blogPost.getTitle(),
blogPost.getContent(),
oldBlogPost.getCreatedAt(),
blogPost.getCreatedAt());
blogPosts.put(id, newBlogPost); // Update the info in the map
...
}4. Return response
Two possibilities are available for the response. If the blog post to update exists, we respond to the client that the update has been successful. The other response informs the client that the blog post doesn't exist.
Return error
Let's return an error for the request to update a blog post that doesn't exist.
- Replace the return type of the
updateBlogPost()method fromvoidtoHttpResponse. - Return a response using Armeria's
HttpResponsecontainingHttpStatus.NOT_FOUND.
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
public final class BlogService {
...
@Put("/blogs/:id")
public HttpResponse updateBlogPost(@Param int id, @RequestObject BlogPost blogPost) {
...
if (oldBlogPost == null) {
return HttpResponse.of(HttpStatus.NOT_FOUND);
}
...
}
}Return success
Let's return the information updated when the target blog post exists:
- Replace the return type of the
updateBlogPost()method fromvoidtoHttpResponse. - Return a response using Armeria's
HttpResponsecontaining the updated information of the post.
import com.linecorp.armeria.common.HttpResponse;
public final class BlogService {
...
@Put("/blogs/:id")
public HttpResponse updateBlogPost(@Param int id, @RequestObject BlogPost blogPost) {
...
return HttpResponse.ofJson(newBlogPost);
}
}5. Test updating a blog post
Let's try updating the content of the first blog post. Add a method like the following.
@Test
@Order(4)
void updateBlogPosts() throws JsonProcessingException {
final WebClient client = WebClient.of(server.httpUri());
final Map<String, Object> updatedContent = Map.of("id", 0,
"title", "My first blog",
"content", "Hello awesome Armeria!");
final HttpRequest updateBlogPostRequest =
HttpRequest.builder()
.put("/blogs/0")
.content(MediaType.JSON_UTF_8, mapper.writeValueAsString(updatedContent))
.build();
client.execute(updateBlogPostRequest).aggregate().join();
final AggregatedHttpResponse res = client.get("/blogs/0").aggregate().join();
final Map<String, Object> expected = Map.of("id", 0,
"title", "My first blog",
"content", "Hello awesome Armeria!");
assertThatJson(res.contentUtf8()).whenIgnoringPaths("createdAt", "modifiedAt")
.isEqualTo(mapper.writeValueAsString(expected));
}Run all the test cases on your IDE or using Gradle. Check that you see the test is passed.
You can test this also with Armeria's Documentation service. See Using DocService after adding service methods for instructions.
Next step
In this step, we've implemented a method for an UPDATE operation and used Armeria's annotations; @Put, @Param, and @RequestObject.
Next, at Step 7. Implement DELETE, we'll implement a DELETE operation to delete blog posts.