Implementing DELETE operation
Table of contents
- What you need
- 1. Implement server-side
- 2. Test deleting a blog post
- 3. Test an error case
- 4. Add the Documentation service
- 5. Check the DocService page
- What's next
So far, we created, read, and updated a blog post. Now, let's implement and make a call to delete a blog post. Also, we'll add Armeria's Documentation Service for testing our blog service.
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.
- Generated Java code
BlogService.java
Main.java
BlogServiceTest.java
BlogNotFoundException.java
GrpcExceptionHandler.java
1. Implement server-side
Let's implement a service method deleteBlogPost()
in the BlogService
class.
Add a service method,
deleteBlogPost()
.BlogService.javaimport example.armeria.blog.grpc.DeleteBlogPostRequest; public class BlogService extends BlogServiceGrpc.BlogServiceImplBase { @Override public void deleteBlogPost(DeleteBlogPostRequest request, StreamObserver<Empty> responseObserver) { try { // Simulate a blocking API call. Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } final BlogPost removed = blogPosts.remove(request.getId()); if (removed == null) { responseObserver.onError( new BlogNotFoundException("The blog post does not exist. ID: " + request.getId())); } else { responseObserver.onNext(Empty.getDefaultInstance()); responseObserver.onCompleted(); } } }
Add Armeria's
GrpcServiceBuilder
's blocking task executor to make all gRPC methods executed in the blocking task executor's thread pool.By default, service methods are executed on the event loop and are expected to be implemented asynchronously. To implement blocking logic, call
useBlockingTaskExecutor(true)
.Main.javaprivate static Server newServer(int port) throws Exception { final GrpcService grpcService = GrpcService.builder().addService(new BlogService()) .exceptionMapping(new GrpcExceptionHandler()) .useBlockingTaskExecutor(true) // Add this .build(); ... }
2. Test deleting a blog post
Let's test deleting a blog post.
We'll delete the blog post with ID 1
, and try retrieving with the same ID to verify it is indeed deleted.
Add a test method like the following.
@Test
@Order(7)
void deleteBlogPost() {
final DeleteBlogPostRequest request = DeleteBlogPostRequest.newBuilder()
.setId(1)
.build();
client.deleteBlogPost(request);
final Throwable exception = catchThrowable(() -> {
client.getBlogPost(GetBlogPostRequest.newBuilder().setId(1).build());
});
final StatusRuntimeException statusException = (StatusRuntimeException) exception;
assertThat(statusException.getStatus().getCode()).isEqualTo(Code.NOT_FOUND);
assertThat(statusException)
.hasMessageContaining("The blog post does not exist. ID: 1");
}
Run all the test cases on your IDE or using Gradle. Check that you see the test is passed.
3. Test an error case
Let's test deleting a blog post that does not exist. Add a test method like the following.
@Test
@Order(8)
void badRequestExceptionHandlerWhenTryingDeleteMissingBlogPost() throws JsonProcessingException {
final Throwable exception = catchThrowable(() -> {
client.deleteBlogPost(DeleteBlogPostRequest.newBuilder().setId(100).build());
});
final StatusRuntimeException statusException = (StatusRuntimeException) exception;
assertThat(statusException.getStatus().getCode()).isEqualTo(Code.NOT_FOUND);
assertThat(statusException)
.hasMessageContaining("The blog post does not exist. ID: 100");
}
Run all the test cases on your IDE or using Gradle. Check that you see the test is passed.
4. Add the Documentation service
This time, we'll add Armeria's Documentation service. The Documentation service automatically creates documentation of your service methods, as well as providing means to test out the methods.
In the
newServer()
method, add aDocService
instance and a request example for creating blog posts, usingDocServiceBuilder.exampleRequests()
. Feel free to add more examples for other service methods.Main.javaimport com.linecorp.armeria.server.docs.DocService; import com.linecorp.armeria.server.docs.DocServiceFilter; import io.grpc.reflection.v1alpha.ServerReflectionGrpc; final class Main { private static Server newServer(int port) throws Exception { final BlogPost exampleRequest = BlogPost.newBuilder() .setTitle("Example title") .setContent("Example content") .build(); final DocService docService = DocService.builder() .exampleRequests(BlogServiceGrpc.SERVICE_NAME, "CreateBlogPost", exampleRequest) .exclude(DocServiceFilter.ofServiceName( ServerReflectionGrpc.SERVICE_NAME)) .build(); } }
Enable unframed requests by setting
GrpcServiceBuilder.enableUnframedRequests()
totrue
. This makes the blog service support requests that are not framed in gRPC wire format. For us, this enables making calls from a web browser.Main.javaprivate static Server newServer(int port) throws Exception { ... final GrpcService grpcService = GrpcService.builder() .addService(new BlogService()) .enableUnframedRequests(true) // Add this .exceptionMapping(new GrpcExceptionHandler()) .useBlockingTaskExecutor(true) .build(); ... }
Add the
DocService
to the server builder.Main.javaprivate static Server newServer(int port) throws Exception { ... return Server.builder() .http(port) .service(grpcService) .serviceUnder("/docs", docService) // Add this .build(); }
(Optional) To access the Documentation service result easily, edit the log message in the
main()
method.Main.javapublic static void main(String[] args) throws Exception { ... logger.info("Server has been started. Serving DocService at http://127.0.0.1:{}/docs", server.activeLocalPort()); }
Otherwise, restart the server by running the
Main.main()
method.The server and services are launched successfully if you see this message.
Server has been started. Serving DocService at http://127.0.0.1:8080/docs
5. Check the DocService page
Let's test and call our service operations using Armeria's Documentation service.
Click the URL http://127.0.0.1:8080/docs from the log message or open up the URL on a web browser.
If you see the Document service page, you've successfully launched the
DocService
and server.Click the CreateBlogPost() method link in the left panel. You can make calls to the method from the page.
Note that in the REQUEST BODY section the values specified in the
exampleRequest
are automatically displayed on the page.Main.javafinal BlogPost exampleRequest = BlogPost.newBuilder() .setTitle("Example title") .setContent("Example content") .build();
Click the SUBMIT button, and you'll see the blog post information returned in the right panel.
What's next
In this step, we've implemented a service method and client method for deleting a blog post. We've also added Documentation service to our server.
We've come to the end of this tutorial. Next, try adding more service methods to the tutorial or have a go at developing a service of your own.