{{announcement.body}}
{{announcement.title}}

MicroProfile: What You Need to Know

DZone 's Guide to

MicroProfile: What You Need to Know

Learn everything you need to know about MicroProfile.

· Java Zone ·
Free Resource

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!

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. 

Image titleThis 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 supports CompletionStage.

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.

Image title

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

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!

Topics:
java ,microprofile ,apis ,openapi ,rest client ,jwt ,propagation ,fault tolerance

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}