MicroProfile: What You Need to Know
Learn everything you need to know about MicroProfile.
Join the DZone community and get the full member experience.
Join For FreeThis article is featured in the new DZone Guide to Java: New Developments & Features. Get your free copy for insightful articles, industry stats, and more!
MicroProfile is an open-source specification that brings a number of microservices-centric features to the Java EE ecosystem. It was born out of the need to accelerate Java EE innovation at a time when Oracle appeared to stop all Java EE 8 development. MicroProfile is already part of the Eclipse Foundation and very likely serves as an incubator to eventual standardization via Jakarta EE proper (Oracle donated Java EE to the Eclipse Foundation as Jakarta EE shortly after Java EE 8 was released).
The graphic below shows current MicroProfile technologies.MicroProfile is supported by major industry players like IBM, Red Hat, Oracle, Microsoft, Payara, and Tomitribe. Some notable MicroProfile API implementations include Payara, WebSphereLiberty, Quarkus, Helidon, KumuluzEE, and TomEE.
This article is a brief look at the current state of MicroProfile. This includes history, latest changes, road map, and a code example-driven look at features.
History
One of the key tenets of MicroProfile has been rapid release cycles, especially as compared with Java EE in recent years. The following chart shows the MicroProfile release history:
Version | Date | Changes |
1.0 | September, 2016 | Initial release with JAX-RS 2.0,JSON-P 1.0, and CDI 1.2 (parts ofJava EE 7). |
1.1 | August, 2017 | Addition of Configuration 1.0. |
1.2 | September, 2017 | Addition of Health Check 1.0,Metrics 1.0, Fault Tolerance 1.0,and JWT Propagation 1.0.Updating to Configuration 1.1. |
1.3 | January, 2018 | Addition of Open Tracing 1.0, Open API 1.0, and REST Client 1.0. Updating to Metrics 1.1 and Configuration 1.2. |
1.4 | June 2018 | Updating to Open Tracing 1.1,REST Client 1.1, Fault Tolerance1.1, JWT Propagation 1.1, andConfiguration 1.3. |
2.0 | June 2018 | Updating to CDI 2.0, JAX-RS 2.1, and JSON-P 1.1 as well as adding JSON-B 1.0 (parts of Java EE 8). |
2.1 | October, 2018 | Updating to Open Tracing 1.2. |
2.2 | February, 2019 | Updating to Open Tracing 1.3, Open API 1.1., REST client 1.2, and Fault Tolerance 2.0. |
Most Recent Developments
As the version increment indicates, MicroProfile 2.2 is mostly a minor update of interest to existing adopters. Below are some significant changes:
Open Tracing 1.3 improves integration with
MicroProfileRest
Clients.Open API 1.1 adds support for the JAX-RS 2.1 PATCH method and improves integration with MicroProfile Rest Clients.
Rest Client 1.2 improves support for HTTP headers, especially via the new
@ClientHeaderParam
annotation.Fault Tolerance 2.0 was upgraded to CDI 2.0. In addition, the
@Asynchronous
annotation now supportsCompletionStage
.
Aside from the umbrella release, Reactive Streams Operators 1.0 was released as a standalone feature. This is a lower level SPI style technology that will likely be incorporated into other parts of MicroProfile going forward.
A beta release of the MicroProfile Starter was just made available. This is an online project generation tool that makes it a lot easier to get started with MicroProfile projects.
Roadmap
The likely contents of MicroProfile 3.0 are shown in the graphic below. It is due to be released in June 2019. It should contain major updates to Metrics as well as Health Check. Outside of the umbrella release, Reactive Streams Operators will have a minor release when GraphQL, Long Running Actions (LRA), and MicroProfile Concurrency are projected to have their initial release. Once these APIs mature, it is likely they will be included in the umbrella release.
The topics currently actively under discussion in the MicroProfile forums include the following:
Long Running Actions (LRA)
Reactive Messaging
GraphQL
Concurrency
Reactive Relational Database Access
Event Data
Service Meshes
MicroProfile APIs
The following is a high-level overview of the current MicroProfileAPIs with brief code examples.
Open API
MicroProfile Open API provides a JAX-RS binding for the OpenAPI specification. The Open API specification is an API description format for REST. One way to think of it is that it is WSDL (Web Services Description Language) for REST. The feature is enabled by default in all MicroProfile applications and automatically generates API documentation for JAX-RS endpoints.
@GET
@Operation(description="Get all current
memberships")
@APIResponses({
@APIResponse(responseCode="200",
description="Successful, returning
memberships"),
...
})
public List<Membership> getAllMemberships() {
The Open API @Operation
and @APIResponses
annotations provide overrides for what MicroProfile would automatically generate by scanning JAX-RS annotations.
Open Tracing
MicroProfile Open Tracing provides a Java binding for the OpenTracing specification. Tracing the flow of a request in a distributed environment has always been challenging. The Open Tracing specification solves this problem by providing a standard for instrumenting microservices for distributed tracing in a technology agnostic manner. One way to think of the concept is that it is a stack trace for REST services. Tools that support the concept include Jaeger and Zipkin.
@GET
@Path("{id}")
@Traced(operationName="GetMembershipById",
value=true)
public Membership getMembership(
@NotNull @PathParam(value="id") int id) {
The Open Tracing @Traced
annotation in the code example assigns a more meaningful name to the method being traced and specifies that call values should be traced.
JWT Propagation
MicroProfile JWT Propagation provides a Java binding for the JWT (JSON Web Token) specification. REST services are usually stateless, and any security state associated with a client is sent to the target service on every request in order to allow services to re-create a security context for the caller and perform both authentication and authorization checks. This is basically what OAuth2, OpenID Connect, and JWT do. It could be thought of as SAML for REST.
@GET
@RolesAllowed({"admin"})
public List<Membership> getAllMemberships() {
MicroProfile detects the presence of a JWT token in the inbound client request and translates it under the hood to an authenticated user principal. The code above checks that the principal includes the "admin" role before allowing access.
Configuration
Java EE has always included the ability to configure applications. However, such configuration is mostly static after deployment. In a cloud environment, it should be possible to modify configuration values from outside an application at runtime so that the application itself does not need to be repackaged. MicroProfile Configuration makes it possible to read configuration values from various sources such as property files, system properties, and environment variables. It is even possible to read configuration values from sources such as the secure configuration store of the cloud provider (such as theAzure Key Vault). The client code for MicroProfile configuration is quite simple:
@Inject
@ConfigProperty(name="host.name",
defaultValue="localhost")
private String hostname;
The @ConfigProperty
annotation injects the "host.name"value from somewhere in the environment. If it is not found, the default value of "localhost" is injected.
Rest Client
JAX-RS provides a powerful client API, but it can be hard to use and not really type safe. Several JAX-RS implementations support the ability to take an interface definition (typically for a JAX-RS endpoint) and create a JAX-RS client proxy from it. This is very similar to how JAX-WS/SOAP clients work. MicroProfile Rest Client standardizes this capability:
String apiUrl = "http://localhost:9080/
movieReviewService";
MovieReviewService reviewService =
RestClientBuilder.newBuilder()
.baseUrl(apiUrl)
.build(MovieReviewService.class);
Review review = new Review(3 /*stars*/, "Good
Movie.");
reviewService.submitReview(movie, review);
The MovieReviewService
in the code example is a generated proxy client (from a JAX-RS server-side endpoint) that is hydrated using the RestClientBuilder
factory.
Health Check
Health checks probe the state of a computing node from another machine (such as the Azure Kubernetes Service controller) in order to facilitate things like monitoring dashboards and auto-restarts/self-healing. MicroProfile HealthCheck
allows the publishing of health data in a standard way using a convenient API:
@Health
@ApplicationScoped
public class CheckDiskSpace implements HealthCheck
{
...
public HealthCheckResponse call() {
...
}
}
The MicroProfile @Health
annotation publishes health information using a standard format at a standard URL. The returned HealthCheckResponse
includes a field to indicate if a service is up or down. You can also add arbitrary metadata that might be helpful in understanding service health (such as perhaps remaining free space in our case). There are simple factories in the API to easily create and populate a HealthCheckResponse
.
Metrics
Similar to health checks, metrics publish common statistics in a standard location and format. This information is collected and used by distributed metrics registries and consoles such as Prometheus/Kubernetes. MicroProfile Metrics publish a required base set of metrics (such as CPU and memory) and some vendor-specific metrics (such as thread pool usage information). You can also add application-specific metrics.
@GET
@Timed(name="get_all_memberships_time",
absolute=true,
unit=MetricUnits.MICROSECONDS)
public List<Membership> getAllMemberships() {
...
@POST
@Counted(name="memberships_created", absolute=true,
monotonic=true)
public Membership createMembership(
...
Membership membership){
In the code example, two application specific metrics are added. @Timed
measures the average time required to get all memberships while @Counted
measures how many new memberships were added. Other such MicroProfile Metrics annotations include @Gauge
and @Metered
.
Fault Tolerance
Microservices, especially running on the cloud, are inherently unreliable. MicroProfile Fault Tolerance makes dealing with this unreliability a little easier by standardizing a set of common failure-handling patterns via annotations. Without these annotations, you would wind up with convoluted if-then-else statements in your business logic. Retries, timeouts, bulkheads, fallbacks, and circuit breakers are some of the common patterns that the API supports.
@GET
@Path("{id}")
@CircuitBreaker(failOn=RuntimeException.class,
requestVolumeThreshold=1,
failureRatio=1, delay=10, delayUnit=ChronoUnit.
SECONDS)
@Timeout(value=3, unit=ChronoUnit.SECONDS)
@Bulkhead(2)
public Membership getMembership(
@NotNull @PathParam(value = "id") int id) {
In the code example, the @Timeout
annotation causes the method call to fail unless it executes within three seconds. The @Bulkhead
annotation limits concurrent requests to two. Finally, the @CircuitBreaker
annotation specifies that the method should not be accessed if an unchecked exception occurs. Once a failure occurs, the method can be accessed again after 10 seconds. Other annotations in the API include @Retry
, @Fallback
, and @Asynchronous
.
Summary
As you can see, MicroProfile fills an important gap by providing some cool features that are perhaps even useful outside of microservices. I would encourage you to start trying them out using one of the many good MicroProfile implementations. Once you have tried things out, a very useful thing to do is get engaged with the highly active and responsive MicroProfile community!
Resources
Home page: microprofile.io
Starter: start.microprofile.io
This article is featured in the new DZone Guide to Java: New Developments & Features. Get your free copy for insightful articles, industry stats, and more!
Opinions expressed by DZone contributors are their own.
Comments