Contents


5 things you didn't know about...

MicroProfile 1.3

Discover five new APIs in Eclipse MicroProfile 1.3

Comments

Content series:

This content is part # of # in the series: 5 things you didn't know about...

Stay tuned for additional content in this series.

This content is part of the series:5 things you didn't know about...

Stay tuned for additional content in this series.

Established in 2016, the Eclipse MicroProfile community is dedicated to rapidly developing new tools and specifications for microservices architectures in Java™. Each new release increases the collection of technologies best suited for developing Java cloud-native microservices. MicroProfile is now in its third release, version 1.3.

This article guides you through the highlights of MicroProfile 1.3's five new APIs:

  • REST Client 1.0
  • Metrics 1.1
  • OpenAPI 1.0
  • OpenTracing 1.0
  • Config 1.2

All the MicroProfile APIs are built on top of the following Java EE 7 APIs:

  • CDI 1.2 is utilized by all APIs and is at the heart of the platform.
  • JAX-RS 2.1 provides client and server features for creating RESTful APIs.
  • The JSON-P 1.0 provides JSON processing capabilities.
  • Commons Annotation 1.2 provides annotations for common semantic concepts.

See the MicroProfile project page to learn about the Java MicroProfile APIs released in version 1.2: Fault Tolerance 1.0, Health Check 1.0, and JWT Authentication 1.0.

Install MicroProfile 1.3

MicroProfile 1.3 requires at least Java SE 8 to run. Listing 1 shows the dependency to add to your pom.xml for MicroProfile 1.3.

Listing 1. Maven coordinates for MicroProfile 1.3
<dependency>
   <groupId>org.eclipse.microprofile</groupId>
   <artifactId>microprofile</artifactId>
   <version>1.3</version>
   <type>pom</type>
   <scope>provided</scope>
</dependency>

You can also generate a MicroProfile project for IBM Liberty through the IBM Cloud Developer tools or IBM Cloud UI.

History of the MicroProfile project

MicroProfile was born in response to Oracle’s lack of progress developing Java EE back in 2016. At that time, Java EE’s slow release cadence did not allow for integrating support for microservices and cloud-native solutions. A group of vendors and user groups proposed the Java MicroProfile to address this demand, and their proposal quickly gathered momentum.

Many other vendors have since joined the MicroProfile community and MicroProfile has since been moved to the Eclipse Foundation, where it is maintained as an Eclipse project.

The Java MicroProfile specification is a community effort: new contributors are welcome to get involved. You could start by joining discussions in the MicroProfile Community Google Group. Developers are also welcome to contribute code to the MicroProfile project hosted on GitHub.

The next sections will reveal five things about MicroProfile 1.3: namely the five new APIs featured in this release.

1. Rest Client 1.0

The Rest Client API is based on JAR-RS 2.0 and provides a typesafe way to invoke RESTful endpoints over HTTP. The BookClientService interface in Listing 2 represents the remote interface, which provides the ability to create and to retrieve a book based on its ISBN.

Listing 2. Creating the BookClientService interface
@Path("/books")
public interface BookClientService {
    @GET
    @Path("/{isbn}")
    Book getBook(@PathParam("isbn") String isbn);


    @POST
    String addBook(Book book);
}

In Listing 3, the BookClientService class is passed to a builder method of RestClientBuilder. Interface methods are then called to create and retrieve a book.

Listing 3. Using the BookClientService interface
URI bookSrvUri = new URI("http://localhost:8081/bookservice");
BookClientService bookSrv = RestClientBuilder.newBuilder()
            .baseUri(bookSrvUri)
            .build(BookClientService.class);

Book book = new Book ("Fun with Microprofile","Alex Theedom");
String isbn = bookSrv.addBook(book);
Book newBook = bookSrv.getBook(isbn);

2. Metrics 1.1

The Metrics API provides a way for developers to portably instrument microservices. The API has been designed to be similar to the Dropwizard Metrics API, which is already familiar to many developers. Using the Metrics API simply removes the dependency on third-party libraries.

Furthering ease-of-use, developers familiar with the popular Prometheus format can simply set up Prometheus to grab those metrics and monitor their services.

The Metrics API differs from the Health Check API 1.2 (released in MicroProfile 1.2) by providing more than a simple binary yes/no representation of a service’s health. It provides detailed metadata about the service’s performance, as well.

Enabling metrics in cloud and microservices applications

In order enable metrics in your MicroProfile applications, you will have to create and register metrics with the application registry. You can do this in one of the following ways:

  • Use the MetricRegistry. This approach requires you to explicitly create and register your metrics.
  • Inject the metrics and use metric annotations. Metrics are automatically instantiated by the CDI container and registered with the MetricRegistry application.

Viewing metric values

Metrics are presented by calling the URI /metrics endpoint in your service, as shown in Listing 4. The metric endpoint in located on localhost, running on port 9091.

Listing 4. Metric endpoint
https://localhost:9091/metrics

Enabling metrics with MetricRegistry

The purpose of the MetricRegistry application is to store all metrics and their metadata. Metrics and metadata can be registered and retrieved using any of the ways listed above. Let's take a closer look at each of these approaches.

Create and register metrics manually

An instance of the MetricRegistry is injected into your class, as shown in Listing 5, and various method are called to register and retrieve those metrics.

Listing 5. Injecting the MetricRegistry
@Inject
private MetricRegistry registry;

On the MetricRegistry class there are methods that retrieve and register metrics as shown in Listing 6. This code snippet shows how to create and register a count type metric. The four types of metric are counters, gauges, meters, histograms, and timers.

Listing 6. Create a new metadata counter metric
Metadata counter = new Metadata(
    "hitsCounter",                            // name
    "Hits Count",                             // display name
    "Number of hits",                         // description
    MetricType.COUNTER,                       // type
    MetricUnits.NONE);                        // units

Metrics are registered programmatically with the MetricRegistry as shown in Listing 7.

Listing 7. Register the counter metrics
Counter hitsCounter = registry.counter(counter);

Once the metric is registered it can then be used to record metrics, as shown in Listing 8.

Listing 8. Increment hitsCounter metric
@GET
@Path("/messages")
public String getMessage() {
    hitsCounter.inc();
    return "Hello world";
}

Once recorded, metrics are stored in the MetricRegistry and retrieved when the /metric URI is called. To retrieve the hit counter metric created above, you would call the following URI: https://localhost:9091/metrics/application/.

The output in Listing 9 is the result generated from the REST endpoints:

Listing 9. Metric stats generated by REST endpoints
https://localhost:9091/metrics/application/hitsCounter
# TYPE application:hits_count counter
# HELP application:hits_count Number of hits
application:stats_hits 499

These metrics are presented in the Prometheus format. If you wanted the stats in JSON format, you would call the same endpoint but configure the HTTP Accept header as application/json, as shown in Listing 10.

Listing 10. Obtain stats in JSON format
https://localhost:9091/metrics/application/statsHits
{"hitsCount":499}

Inject metrics and use annotations

CDI injection is an easier and more natural way to enable metrics in your applications. You would still create and register your metrics with the MetricRegistry, but rather than creating a metadata instance, you would pass the metric configuration data as parameters of the @Metric annotation, as shown in Listing 11.

Listing 11. Configure metrics with @Metric
@Inject
@Metric(name="hitsCounter", displayName="Hits Count", description="Number of hits", absolute=true)
Counter hitsCounter;

The @Metric annotation provokes the server to create and register a counter in the MetricRegistry and provide it for the application to use.

3. OpenAPI 1.0

New in MicroProfile 1.3, OpenAPI 1.0 provides a contract for RESTful services similar to the WSDL contract for SOAP web services. OpenAPI 1.0 is based on the OpenAPI specification and provides a set of Java interfaces and programming models that allow developers to produce OpenAPI v3 documents from JAX-RS applications.

OpenAPI produces a valid OpenAPI document from a JAX-RS 2.0 application. It processes all the JAX-RS annotations (include the @Path and @Consumes/@Produces annotations) as well as POJOs used as input or output to JAX-RS operations.

Start and configure OpenAPI

To start using OpenAPI 1.0, just deploy your existing JAX-RS application into a MicroProfile server such as Open Liberty and checkout the output from the OpenAPI URI /openapi.

Once you’ve seen the output from calling /openapi you will want to configure your RESTful resources to provide better documentation. This is done by annotating the various elements of the RESTful API.

Table 1 shows a list of the key annotations for the OpenAPI 1.0 spec. All of the OpenAPI annotations are listed in the org.eclipse.microprofile.openapi.annotations package.

Table 1. Key OpenAPI annotations
AnnotationDescription
@OperationDescribes an operation or typically an HTTP method against a specific path.
@APIResponseDescribes a single response from an API operation.
@RequestBodyDescribes a single request body.
@ContentProvides schema and examples for a particular media type.
@SchemaAllows the definition of input and output data types.
@ServerA container for multiple server definitions.
@ServerVariableRepresents a server variable for server URL template substitution.
@OpenAPIDefinitionGeneral metadata for an OpenAPI definition.

Using the OpenAPI annotations

The OpenAPI annotations will mark features within a JAX-RS resource definition and provide information about that resource. In Listing 12, the findBookByISBN method is annotated with the @Operation annotation and passed information about its function.

Listing 12. Using OpenAPI annotations to mark a REST resource
@GET
@Path("/findByISBN")
@Operation(
    summary = "Finds a book by its ISBN",
    description = "Only one ISBN should be provided")
public Response findBookByISBN(...) { ... }

Output from this annotation is shown in Listing 13.

Listing 13. YAML output of the REST documentation
/books/findBookByISBN:
  get:
    summary: Finds a book by its ISBN
    description: Only one ISBN should be provided
    operationId: findBookByISBN

The default output of calling the OpenAPI URI /openapi is YAML. If you make a call to this endpoint with the HTTP Accept header set to application/json, then the response will be in JSON format.

4. OpenTracing 1.0

The OpenTracing API is an implementation of the OpenTracing Project. It allows you to trace the flow of a request across service boundaries. This is particularly important in microservices environments, where requests usually pass through many services.

To accomplish distributed tracing, each service logs a correlation ID to a service that is designated for storing the distributed trace records. Services may then provide views of the traces associated with a request.

OpenTracing can operate with or without explicit instrumentation of application code. We’ll look at both options.

OpenTracing without code instrumentation

This operation mode allows JAX-RS applications to take part in trace recording without having to add any distributed tracing code to the application. In this usage, the developer doesn’t even need to know anything about the tracing environment the application will be deployed into.

OpenTracing with code instrumentation

In some cases you may wish to actively interact with tracing. In this case you will use the @Traced annotation to specify the class or method to be traced. Explicit code instrumentation and instrumentation without code can be combined. In some scenarios, integrating the two methods will create the solution that is right for your use case.

Using the @Traced annotation

When the @Traced annotation is applied to a class it applies to all methods in that class. If you want to trace only a subset of methods, you may add the annotation to just those methods. The annotation starts a Span at the beginning of the method, and finishes the Span at the end of the method. In Listing 14, the traced operation is given the name Book Operation in the class-level annotation. The method getBookByIsbn() is excluded from the trace because it specifies false as the inclusion value.

Listing 14. Example of @Traced usage
@Path("/books")
@Traced(operationName = "Book Operation")
public class BookResource {

    @GET
    public Response getBooks() {
      // implementation code removed for brevity
    }

    @Traced(value = false)
    @GET
    @Path("/{isbm}")
    public Response getBookByIsbn(String @Param("isbn") isbn {
      // implementation code removed for brevity
    }

}

5. Config 1.2

Many methodologies have been developed to avoid having to repackage applications whenever their operating environment changes. This is especially important for microservices because they are designed to be be portable and run in multiple environments.

The Config 1.2.1 API aggregates configuration from a variety of distinct ConfigSources and presents a singular view to the user.

Configurations are stored in a String/String key and value format. A configuration key might use a dot-separated notation similar to namespacing in Java packages. Listing 15 shows an example of a Config API-compatible configuration file.

Listing 15. Example configuration file
com.readlearncode.bookservice.url = http://readlearncode.com/api/books
com.readlearncode.bookservice.port = 9091

Using the configuration object

An instance of the configuration object can be obtained automatically via injection, using @Inject Config as shown in Listing 16:

Listing 16. Using injection for configuration
public class AppConfiguration {
    public void getConfiguration() {
        Config config = ConfigProvider.getConfig();
        String bookServiceUrl = config.getValue("com.readlearncode.bookservice.url", String.class);
    }
}

It could be obtained programmatically via the ConfigProvider, as shown in Listing 17:

Listing 17. Using CDI for configuration
@ApplicationScoped
public class InjectedConfigUsageSample {

    @Inject
    private Config config;

    @Inject
    @ConfigProperty(name="com.readlearncode.bookservice.url")
    private String bookServiceUrl ;

}

Conclusion

MicroProfile offers Java developers a wide range of features that have become essential to developing microservices-based systems. The short release cycle ensures that new features will be added regularly, and we’ve seen the specification grow rapidly since its inception. Each MicroProfile API follows industry accepted best practices to help ensure that Java-based microservices are both agile and robust.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java development, Cloud computing, Open source
ArticleID=1060497
ArticleTitle=5 things you didn't know about...: MicroProfile 1.3
publish-date=04302018