MicroProfile – Part 1: Defining End-Points
- 8 minsPart 1: End-points in MicroProfile. This is a part of a series of posts to help you get started with microservices in MicroProfile and showing off some of the features it brings to the table.
Intro
In my previous two posts, I have been describing parts of a system for “checking-in” to a location using QR codes in Java. We started with generating QR codes, followed by generating PDF files.
Now, I would like to focus on building microservices around that functionality. We will be creating a few HTTP end-points built with MicroProfile. I will be using the next few posts as an opportunity to show off some of the features that you will be getting out of the box or with minimal effort using MicroProfile.
Getting started
(Assuming that you have Git, Java 9+, and Maven installed.)
Since we will continue using the QR code generator project to showcase various features of MicroProfile, it might be a good idea to familiarize yourself with the code. You might want to start with taking a look at my previous two posts that explain the code for generating QR codes, and generating PDF files in detail.
Now you can clone the project and examine the Maven dependencies in the pom.xml
file, as well as any other MicroProfile related dependencies.
After cloning and opening the project in your favorite IDE, build it (again, assuming that you have Java and Maven installed) with the following command in a terminal:
When the project is done building and you have got a Build Success
from Maven, you can run the project to make sure everything runs fine:
In a few seconds it takes for the app server to start-up, you should be able to access the starter page at http://localhost:8181/qrcreator/index.html
.
Defining End-Points
One of the most obvious features any microservice needs is an end-point to receive requests and respond with some kind of data back. Let’s have a closer look into how this is done in MicroProfile. First of all, we will need to define the application path that serves as the base URI for all resource URIs (think of it as a “root” URL) and make sure that the class where it is defined extends javax.ws.rs.core.Application
, like in ApplicationEntryPoint
class here:
This will set up all the end-point URLs to start with /api
, in our case http://localhost:8181/qrcreator/api/
.
A (Regular) JSON End-Point
Now, let’s define some endpoints. We will start with a most regular kind – a JSON end-point. This is probably the most common end-point you will encounter.
We will start with creating one that would respond to requests sent to /api/somestring/json
. Note that as you can see from the code below, @Path
defines somestring
in the URL as an id
that is passed on as an argument to the createIdKeyTuple
method.
We will also define a type of a request (in this case it is a GET
request) and specify that it will be returning a JSON document with @Produces
annotation.
Now, that we are done with annotations for the method, let’s have a look at the code for this method, that defines a JSON end-point in the QRController
class:
Note that in this code we have only simple exception handling that makes sure we return a correct HTTP status code – OK (200) on a success and server error (500) on an internal error. You can later add other HTTP codes based on your needs.
An End-Point Returning an Image
Returning an image instead of a JSON document is quite similar to the code we have already seen. Here we will have to pay attention to three aspects:
- Different MIME type defined in
@Produces
annotation:@Produces("image/png")
- Additional elements in the response header that let you control how the created file is displayed in the browser, i.e. shown in the browser “inline”, or made available through a download dialog –
"Content-Disposition", "inline;"
(see specs forContent-Disposition
for more details) - Additional elements in the response header that let you control the name for the created file:
filename=\"" + id + ".png\"
Let’s have a look at the whole method:
It is worth noting that the number of catch
statements in the try...catch
clause will vary and depend on the number and type of exceptions that can be thrown by the underlying methods.
An End-Point Returning a PDF
The last method for today – defining an end-point for returning PDF files – is nearly identical to the one we used for returning images, except for one thing:
- Different MIME type and explicit file encoding in
@Produces
:@Produces("application/pdf; charset=utf-8")
.
Of course, there are also obvious differences in the contents of the byte[]
array, but I consider that being outside the scope of this post – you can study those differences on your own.
What’s Next?
Here we have seen how easy it is to define an end-point that can return documents with various MIME types. In the next posts, we will be taking a closer look at things like how you can equip your end-points with metrics, provide auto-generated documentation based on OpenAPI, and add more resilience with fail-over and circuit-breakers.