Getting Started With Jakarta EE and Eclipse MicroProfile
In this article, get started with Jakarta EE and Eclipse MicroProfile.
Join the DZone community and get the full member experience.
Join For FreeNever heard of Jakarta EE and Eclipse MicroProfile yet? Then it's time to give it the first try and see how the Java Enterprise standard evolved. By developing a small application, this post demonstrates how to use these two technologies to build cloud-ready and state-of-the-art enterprise applications.
What Is Jakarta EE?
In a nutshell, it's a set of specifications (JAX-RS, CDI, JPA, JSON-P, etc.) to write enterprise applications with Java. These specifications are documents defining the API and interaction of a technology.
In Java words: the specification documents are like interfaces with formal definitions and the actual implementation of these interfaces is up to an application server vendor (e.g. WildFly, Open Liberty, Payara, TomEE). To ensure a vendor does not implement the specification in the wrong way, each specification provides a Technology Compatibility Kit (TCK). These are a set of tests to verify an implementation is compliant to the specification. Once an application server passes the TCKs for all specifications, it's compliant to the whole standard.
For many years, Java EE has been the standard way to write enterprise applications. Java EE (named J2EE in the earlier days) was for a long time maintained by Oracle. In 2017 Oracle decided to no longer evolve the enterprise standard under its umbrella and handed it over to the Eclipse Foundation. Due to legal reasons, they had to rebrand it and decided to name it Jakarta EE.
You can find all specifications of Jakarta EE at the official homepage and will also find more information about how the specification process now works at the Eclipse Foundation.
What Is Eclipse MicroProfile?
As the process of releasing and adapting new features for Java EE was rather slow, a group of vendors and community members decided to create MicroProfile in 2016. The main goal is to keep up with changes in the industry an optimize the existing platform for a microservice architecture.
Eclipse MicroProfile currently contains twelve specifications. Four of them are also part of Jakarta EE. This allows you to create standalone applications with just MicroProfile. All specifications are vendor-agnostic and the implementation is shipped with the application server.
You can see the Jakarta EE specifications as a solid foundation to build enterprise applications. On top of this, Eclipse MicroProfile fills the gap to build distributed systems following the Twelve-Factor App methodology.
Bootstrap Your First Project
Let's bootstrap a Jakarta EE and Eclipse MicroProfile with Java 11 using Maven. The pom.xml
is pretty straightforward:
x
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.rieckpil.blog</groupId>
<artifactId>jakarta-ee-microprofile</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jakarta.jakartaee-api.version>8.0.0</jakarta.jakartaee-api.version>
<microprofile.version>3.2</microprofile.version>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakarta.jakartaee-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>${microprofile.version}</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>
Both dependencies for Jakarta EE and Eclipse MicroProfile are marked as provided
. As the application server provides the actual implementation of the different specifications, we don't have to ship any library with our war
file.
This results in a so-called thin war of just some kilobytes and hence making deployment fast.
When it comes to deploying your application, you have to pick an application server. All Jakarta EE compliant application servers are listed on the following overview page and most of them also implement the Eclipse MicroProfile specification.
For this demo, I'm choosing Open Liberty, a light-weight open-source application server from IBM.
Manually downloading configuring the application server is sometimes a hurdle for Jakarta EE newcomers. Fortunately, the Open Liberty team provides an easy-to-use Maven plugin for rapid development experience. Once you include it to your pom.xml
, starting/stopping a local Open Liberty server is no big deal:
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>3.1</version>
</plugin>
This plugin also comes with a dev mode to have hot-reloading during local development and even shorter feedback cycles: mvn liberty:dev
.
Configure Open Liberty for Jakarta EE and Eclipse MicroProfile
First, let's configure Open Liberty. For this, create a server.xml
file inside src/main/liberty/config
with the following content:
xxxxxxxxxx
<server description="new server">
<featureManager>
<feature>javaee-8.0</feature>
<feature>microProfile-3.2</feature>
</featureManager>
<mpMetrics authentication="false"/>
<httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>
<quickStartSecurity userName="duke" userPassword="duke"/>
<ssl id="defaultSSLConfig" trustDefaultCerts="true"/>
</server>
Open Liberty provides a simple way to configure the features we need for our application. For this demo, I'm including the features javaee-8.0
and microProfile-3.2
. They will pull all specifications of Jakarta EE and Eclipse MicroProfile. As the Jakarta EE 8 specification versions are compatible with Java EE 8, we can use javaee-8.0
for our Jakarta EE application.
It's also possible to define only the features that are actually in-use and cherry-pick them to improve memory footprint and startup time.
For convenience, I'm disabling authentication for the MicroProfile metrics endpoint using mpMetrics
. Furthermore, httpEndpoint
defines which ports Open Liberty will use. The quickStartSecurity
configures a default user to access restricted pages of the application server. Using the ssl
configuration we instruct Open Liberty to use the default certificates provided by the JDK. We'll need this, as our application will, later on, call a remote API using HTTPS.
For more information on how to configure Open Liberty, consider using this cheat sheet.
Create a JAX-RS Endpoint
The goal of this application is to return a quote of the day. We'll expose this information using a JAX-RS (Jakarta RESTful Web Services) endpoint.
You can bootstrap a JAX-RS application by providing a subclass of javax.ws.rs.core.Application
on your classpath:
"resources") (
public class JAXRSConfiguration extends Application {
}
The application path will be used as a prefix for all endpoints of the application. The actual public endpoint is defined in a different class and can be accessed via HTTP GET at /resources/quotes
:
x
"quotes") (
public class QuotesResource {
private QuotesClient quotesClient;
MediaType.APPLICATION_JSON) (
public Response getQuoteOfTheDay() {
JsonObject quoteOfTheDay = quotesClient.getQuoteOfTheDay();
JsonPointer quotePointer = Json.createPointer("/contents/quotes/0/quote");
JsonObject result = Json.createObjectBuilder()
.add("quoteOfTheDay", quotePointer.getValue(quoteOfTheDay)).build();
return Response.ok(result).build();
}
}
Our JAX-RS endpoint requires an instance of the QuotesClient
to work. This client is using the MicroProfile Rest Client specification. You'll see the client in the following chapter.
With CDI (Contexts and Dependency Injection) Jakarta EE provides a specification to make use of dependency injection. The @Inject
annotation tells the CDI container to inject an instance of the QuotesClient
to our class.
Multiple things are happening inside the getQuoteOfTheDay
method. First, we get the JSON response of the remote API using the QuotesClient
. As the actual quote is nested inside the JSON, I'm creating a JsonPointer
(part of JSON-P) to easily access the field inside the nested object. Finally, we'll use the pointer to extract the quote from the JSON and return it.
The @Metered
annotation is part of MicroProfile Metrics and will measure the throughput of our endpoint using one-, five- and fifteen-minute rates. This might be a useful metric to monitor to see how our application is performing.
Fetch Data From a Remote API
As we are lazy developers, we don't want to implement boilerplate code to make an HTTP call. With MicroProfile Rest Client we solely define an interface and declare the remote endpoints using well-known annotations from JAX-RS. If you have experience with Feign, this might seem familiar:
xxxxxxxxxx
baseUri = "https://quotes.rest/") (
public interface QuotesClient {
"qod") (
maxRetries = 3, maxDuration = 3000L) (
fallbackMethod = "getFallbackQuote") (
JsonObject getQuoteOfTheDay();
default JsonObject getFallbackQuote() {
return Json.createObjectBuilder()
.add("contents",
Json.createObjectBuilder()
.add("quotes", Json.createArrayBuilder()
.add(Json.createObjectBuilder().add("quote", "Lorem ipsum dolor sit amet"))))
.build();
}
}
On top of this, we can make our remote calls more resilient using MicroProfile Fault Tolerance. This specification provides a set of strategies to build resilient and fault-tolerant services. For our example, I'm using @Retry
and @Fallback
. This ensures that we'll try to access the API three times (in case the first and second call failed) and will return a fallback in case this is not successful we are exceeding 3 seconds for this operation.
Eclipse MicroProfile Fault Tolerance has an integration with the Metrics specification that allows us to get statistics about our retry out-of-the-box.
Inspect Application Metrics
The application is now ready to be deployed. Given the Open Liberty Maven plugin, we can start the server and deploy the application in the foreground with mvn liberty:run
. You should see something similar like this to ensure the application is up and running:
xxxxxxxxxx
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/jwt/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/openapi/ui/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/metrics/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/health/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/openapi/
[INFO] [AUDIT ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/ibm/api/
[INFO] [AUDIT ] CWWKF0012I: The server installed the following features: [appClientSupport-1.0, appSecurity-2.0, appSecurity-3.0, batch-1.0, beanValidation-2.0, cdi-2.0, concurrent-1.0, distributedMap-1.0, ejb-3.2, ejbHome-3.2, ejbLite-3.2, ejbPersistentTimer-3.2, ejbRemote-3.2, el-3.0, j2eeManagement-1.1, jacc-1.5, jaspic-1.1, javaMail-1.6, javaee-8.0, jaxb-2.2, jaxrs-2.1, jaxrsClient-2.1, jaxws-2.2, jca-1.7, jcaInboundSecurity-1.0, jdbc-4.2, jms-2.0, jndi-1.0, jpa-2.2, jpaContainer-2.2, jsf-2.3, json-1.0, jsonb-1.0, jsonp-1.1, jsp-2.3, jwt-1.0, managedBeans-1.0, mdb-3.2, microProfile-3.2, mpConfig-1.3, mpFaultTolerance-2.0, mpHealth-2.1, mpJwt-1.1, mpMetrics-2.2, mpOpenAPI-1.1, mpOpenTracing-1.3, mpRestClient-1.3, opentracing-1.3, servlet-4.0, ssl-1.0, wasJmsClient-2.0, wasJmsSecurity-1.0, wasJmsServer-1.0, webProfile-8.0, websocket-1.1].
[INFO] [AUDIT ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 9.941 seconds.
Now you can start accessing the public endpoint to fetch the quote of the day:
x
curl -v http://localhost:9080/resources/quotes
< HTTP/1.1 200 OK
< X-Powered-By: Servlet/4.0
< Content-Type: application/json
< Date: Mon, 30 Mar 2020 07:47:26 GMT
< Content-Language: en-US
< Content-Length: 127
<
{"quoteOfTheDay":"From now on we live in a world where man has walked on the Moon. It's not a miracle; we just decided to go."}
In case of an error (more than three retries/seconds for calling the remote API), our application responds with a fallback:
{"quoteOfTheDay":"Lorem ipsum dolor sit amet"}
To get insights for the retry statistics, the throughput of the endpoint and further technical metrics like CPU usage and memory, you can access http://localhost:9080/metrics
:
x
# TYPE application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_invocations_total counter
application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_invocations_total 5
# TYPE application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsSucceededRetried_total counter
application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsSucceededRetried_total 0
# TYPE application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsFailed_total counter
application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsFailed_total 0
# TYPE application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_total counter
application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_total 5
# TYPE application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_rate_per_second gauge
application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_rate_per_second 0.008803184637398256
# TYPE application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_one_min_rate_per_second gauge
application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_one_min_rate_per_second 0.03532066437518856
# TYPE application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_five_min_rate_per_second gauge
application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_five_min_rate_per_second 0.04249155859338982
# TYPE application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_fifteen_min_rate_per_second gauge
application_de_rieckpil_learning_QuotesResource_getQuoteOfTheDay_fifteen_min_rate_per_second 0.11158522807330326
# TYPE application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsSucceededNotRetried_total counter
application_ft_de_rieckpil_learning_QuotesClient_getQuoteOfTheDay_retry_callsSucceededNotRetried_total 5
Summary
This was a first (and rather quick) guide to both Jakarta EE and Eclipse MicroProfile. Given the following specifications: CDI, JAX-RS, JSON-P, JSON-B, MicroProfile Metrics/Fault Tolerance/Rest Client we were able to build a small resilient and monitorable application.
There are way more specifications to explore. JWT Auth, OpenAPI support, distributed tracing, configuration, health checks, just to name some for Eclipse MicroProfile. Major parts of Jakarta EE, that were not covered with the demo, are JPA for persistence and JMS for messaging.
The source code for this application with instructions to run it is available on GitHub.
If you want to learn more about Eclipse MicroProfile, consider signing up for my free course bundle (E-Book and Video Course). For more hands-on examples on Jakarta EE, I'm frequently uploading videos on YouTube to make you familiar with this technology.
Further resources on both topics are available at the official homepages:
Have fun being productive with Jakarta EE and Eclipse MicroProfile,
Phil
Opinions expressed by DZone contributors are their own.
Comments