Book Image

Hands-On Cloud-Native Microservices with Jakarta EE

By : Luigi Fugaro, Mauro Vocale
Book Image

Hands-On Cloud-Native Microservices with Jakarta EE

By: Luigi Fugaro, Mauro Vocale

Overview of this book

Businesses today are evolving rapidly, and developers now face the challenge of building applications that are resilient, flexible, and native to the cloud. To achieve this, you'll need to be aware of the environment, tools, and resources that you're coding against. The book will begin by introducing you to cloud-native architecture and simplifying the major concepts. You'll learn to build microservices in Jakarta EE using MicroProfile with Thorntail and Narayana LRA. You'll then delve into cloud-native application x-rays, understanding the MicroProfile specification and the implementation/testing of microservices. As you progress further, you'll focus on continuous integration and continuous delivery, in addition to learning how to dockerize your services. You'll also cover concepts and techniques relating to security, monitoring, and troubleshooting problems that might occur with applications after you've written them. By the end of this book, you will be equipped with the skills you need to build highly resilient applications using cloud-native microservice architecture.
Table of Contents (14 chapters)

Java EE – MicroProfile.io – Jakarta EE

The Java EE platform is one of the main tools for creating enterprise applications, thanks to a series of standards and specifications whose implementations have allowed us to manage crucial aspects such as transactions, security, scalability, concurrency, and management of the components it is deploying.

Together with Spring and Pivotal technology, Java EE represents the implementation model for modern Java-based enterprise applications on any kind of deployment platform.

As previously stated, the delay in the evolution of the platform and, consequently, in the release of new versions able to meet the new requirements related to the implementation of microservices in cloud environments have generated in the community a sense of distrust in its use.

I don't want to start some sort of religion war on which technology among Java EE, Spring, or others is regarded as the best to implement modern applications. Java EE 7, the latest stable and supported version, was released in 2013, and it received very positive feedback from the community.

Java EE 7's relevance in the ecosystem of enterprise applications has been very
important, as evidenced by the following survey—Developers Affirm Strong Support for Java EE 7 in DZone Survey

Spring's influence on Java EE was clear and helped to improve the platform by making it significantly less complex for example, through the following:

  • The arrival of Spring and Hibernate has provided new ideas and approaches to development, which has given birth to EJB 3 and JPA 1, which represent the two major innovations introduced in Java EE 5.
  • Spring Dependency Injection was the base on which Context and Dependency Injection (CDI) was built.
  • Spring Batch has merged into JBatch specification (JSR 352 https://www.jcp.org/en/jsr/detail?id=352).

Since its creation, Spring has become popular among developers, thanks to the ease-of-use approach and a speedy time to market that allow us to quickly adopt technological innovations, such as microservices and cloud native applications.

Java EE, instead, and in particular after version 5, has a slower time to market; the reasons are related to the length of time needed to write specifications, and the implementation and certification time. Usually, several months are needed for a specification release to be supported and certified by the application servers.

Recently, this gap has widened:

  • Spring Boot has increased its ease of use through the convention-over-configuration principle.
  • Spring Cloud is becoming the major platform used in cloud-native developments by leveraging open source components from Netflix, which creates modules that implement important cloud concepts such as service registry, service discovery, load balancing, monitoring, and so on.

Now the question could be—is Java EE still a good choice to make microservices and cloud-native applications?

In my opinion, the answer is yes.

First of all, Java EE, in particular version 8, introduced or has consolidated a great number of specifications that are extremely useful for microservices implementation, such as the following:

  • CDI 2.0
  • Java API for JSON Processing (JSONP) 1.1
  • Java API for JSON Binding (JSON-B) 1.0
  • Java API for RESTful Web Services (JAX-­RS) 2.1
  • Java Servlet 4.0

CDI 2.0 defines the behavior of CDI outside of a Java EE container, allowing the use of patterns such as inversion of control even in contexts such as third-party utility libraries.

The specification is split in three parts—core CDI, CDI for Java SE, and CDI for Java EE. This split makes CDI more modular in order to help other Java EE specifications better integrate with it.

The de facto standard for API communications in microservices environments is the JSON format. Java EE has two great specifications, JSON-B and JSONP that can help developers to easily produce and process a JSON payload.

JSONP has great support, with utilities such as JSON Pointer, JSON Patch, JSON Merge Patch, and so on, for meeting the Internet Engineering Task Force (IETF) standards (https://www.ietf.org/standards/). It has also added editing operations to JSONObject and JSONArray, and introduced helper classes and methods to better utilize Java SE 8 Stream operations.

JSON-B set a JAXB-­like API to easily marshal or unmarshal Java objects to/from JSON. It created a default mapping between classes and JSON, and a standard support to handle the application/JSON media type for JAX-­RS. It's a natural follow-on to JSON­P specifications, and closes the JSON support gap.

JAX-RS 2.1 standardized some features most used in microservices development, as follows:

  • Server-­sent events
  • Non-­blocking I/O in providers (filters, interceptors, and so on)
  • Reactive programming paradigms to improve JAX-­RS asynchronous clients
  • Hypermedia API enhancements

In this way, it has facilitated integration with other JSRs and frameworks.

Servlet 4.0 introduced support for HTTP/2 protocol and the use of request/response multiplexing, server push notifications, and so on. It's also aligned with the latest HTTP 1.1 RFCs.

All the specifications and features described previously are certainly useful, but not sufficient to make Java EE suitable to meet the needs of cloud-native applications and microservices.

Now, the main targets are as follows:

  • Deploy the applications onto the cloud
  • Build microservices in an easy manner
  • Enable more rapid evolution of applications

The community, through the Java EE guardians (https://javaee-guardians.io/) and the Java User Groups (JUG), pushed for modernizing Java EE for cloud and microservices environments. The target is to extend the Java EE platform in order to make it able to build microservice architecture, while still maintaining backwards compatibility with previous Java EE versions. Furthermore, the community wanted a migration path to evolve the consolidated applications into cloud-ready applications that could take advantage of new cloud development and deployment models.

In detail, the request was to obtain functionalities as follows:

  • Client-side circuit breakers in order to make remote REST invocations fault-tolerant
  • A standard way of health checking Java apps
  • A secret vault to shadow sensitive data
  • Multitenancy support to accommodate the needs of complex applications
  • OAuth and OpenID support technologies have rapidly emerged as a de facto standard in security context implementation
  • An externalized configuration store to make it an easy process to promote applications across environments

The answers to these requests were essentially two, as follows:

  • The creation of the MicroProfile.io project, in the middle of 2016
  • The new life on Java EE with the Jakarta EE community project at the end of April 2018

MicroProfile

MicroProfile.io is an open source community specification for Enterprise Java microservices, and it aims at optimizing Enterprise Java for a microservice architecture.

The delay in the release of the new version of Java EE, and the rapid change of the technological scenario (which is increasingly oriented toward cloud platforms and microservice architectures), have pushed a community of individuals, organizations, and vendors collaborating within an open source (Eclipse) project to bring microservice features to the Enterprise Java community.

Some of the major players in the history of the Java EE platform are involved in this project, such as Payara, Fujitsu, Tomitribe, IBM, Red Hat, Hammock, SmartBear, Hazelcast, and Oracle to name a few.

The project is based on the idea of extending the main features of the Java EE with new specifications essential to meeting the requirements of the new technological context.

At the time of writing this book, the project is at version 1.3, and is composed of the specifications shown below:

New Implementations Updated Implementations Unchanged implementations
OpenTracing 1.0 Metrics 1.1 Fault tolerance 1.0
OpenAPI 1.0 Config 1.2 JWT propagation 1.0
REST client 1.0 Health check 1.0
CDI 1.2
JSONP 1.0
JAX-RS 2.0

As mentioned previously, in addition to the specifications relating to CDI, JSONP, and JAX-RS used to expose the API via RESTful web services in JSON format, there are a number of new specifications such as configuration, fault tolerance, JSON Web Tokens (JWTs), metrics, health checks, JWT propagation, OpenTracing, OpenAPI, and the REST client that are able to allow the realization of microservices in cloud environments.

In the following chapters, we will analyze in detail these specifications, with examples of code that will allow us to understand their purposes well. For now, let's have a quick introduction to the objectives of each of these new specifications, based on the descriptions that are given in their GitHub repositories:

  • Config: A common feature, not strictly related to cloud or microservice architecture, is the ability of the applications to be configured based on the running environment. Usually they use properties files in different formats, but the request is to have the opportunity to update the configuration properties without the need to rebuild and repackage the application. Also, the changed values should be retrieved by the client without the need to redeploy and restart the application. This requirement is extremely important for microservices running in a cloud environment. The MicroProfile Config specification defines the way to implement this concept.
  • REST client: This specification defines how to invoke RESTful services over the HTTP protocol. The REST client implementation outlines a continuity with Java EE/Jakarta EE, suggesting the use of JAX-RS 2.0 specifications in order to give the ability to reuse code written in tradition Java EE applications.
  • Fault tolerance: One of the most important features required in cloud and microservice environments is resiliency to failure. This specification defines a way to provide different strategies to drive the execution and the result of computation implemented by the code; for example, providing fall backs and an alternative result when code execution fails due to unexpected exceptions. Retry strategies, bulkheads, and circuit breakers are enterprise integration patterns that you should implement to adhere to this specification.
  • Metrics: In a distributed environment such as a Platform as a Service (PaaS), it is essential to retrieve metrics related to the execution environment. Usually, companies use agents that shadow the complexity to retrieve this information. In the past, the Java Management Extension (JMX) was implemented for this purpose. This specification extends JMX and defines another two main aspects, as follows:
    • A standard way for MicroProfile servers to expose monitoring data to management agents
    • A standard Java API that applications should use to expose their telemetry data to operations teams
  • OpenAPI: The main goal of this specification is to define a standard Java API that implements the OpenAPI version 3 specification defined here: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md. The applications should adhere to this specification to expose their API documentation.
  • JWT propagation: The most used technology in microservice architecture is the RESTful web service as compared to the HTTP protocol, and so the security of the APIs exposed must be guaranteed. The RESTful architecture services should be stateless—this means that any security state associated with a client is sent to the requested service every time a new request is performed. The security context is always recreated and the systems must perform both authentication and authorization validation on every request. The principal security protocols are based on security tokens—OAuth2, WS-Federation, OpenID Connect, WS-Trust, and Security Assertion Markup Language (SAML) are the main ones. The target technologies of JWT propagation specification are based on standards defined by OAuth2, JWT, and OpenID Connect.
  • OpenTracing: The microservice usually runs in distributed system environments, so it's extremely important to trace requests in order to rebuild the execution flow of the code. This specification defines APIs that describe how incoming and outgoing requests should be traced by an OpenTracing-compliant Tracer Object. They also set the way to access a configured Tracer Object.
  • Health check: The monitoring of the production infrastructure is a key point of the operation teams—it's important to always know the state of a node in order to react quickly if there are issues. These APIs describe the rules for determining the state of a node. In a PaaS health check specifications could be used to determine whether a node needs to be discarded and replaced by another instance using automatic mechanisms, reducing the out-of-service time.

One of the main goals of these specifications is the compatibility with the well-known cloud platforms, such as, Kubernetes.

It is expected that MicroProfile 2.0 will align all APIs to Java EE 8 in order to obtain a set of features, as shown below:

New Implementations Updated Implementations Unchanged implementations

JSON-B 1.0

CDI 2.0

OpenTracing 1.0

JSONP 1.1

OpenAPI 1.0

JAX-RS 2.1

REST client 1.0

Fault tolerance 1.0

Metrics 1.1

JWT propgation 1.0

Health check 1.0

Config 1.2

At this moment, there are some products that have already passed the Technology Compatibility Kit (TCK) tests of the JSRs described before, or that are in the in progress state.

The main products are as follows:

You can find the updated list of the MicroProfile implementation at the Eclipse MicroProfile Wiki (https://wiki.eclipse.org/MicroProfile/Implementation).

So, now we have a great community, that of MicroProfile.io that is building a Java EE on steroids. But, how will Java EE evolve, and how will the new features made available by MicroProfile be included in it?

The evolution of Java EE is Jakarta EE.

Jakarta EE

Last September, Oracle announced, with the support of IBM and Red Hat that Java EE was going to move to the Eclipse Foundation. Since then, some other important companies have joined the initiative with strategic or participating-level commitments.

Following are the members involved in the Jakarta EE project:

  • Strategic members:
    • Fujitsu
    • IBM
    • Oracle
    • Payara
    • Red Hat
    • Tomitribe
  • Participating members:
    • CloudBees
    • DocDoku
    • Genuitec
    • IncQuery Labs
    • Lightbend
    • Microsoft
    • Mizuho
    • Pivotal
    • RCP Vision
    • SAP
    • UseOpen
    • Vaadin
    • Webtide

The community requires that the Jakarta EE platform evolve faster than Java EE—to continue to be a reference platform for cloud architectures and microservices, which evolve rapidly, it is necessary to quickly incorporate into new versions of the platform the new features coming from open source communities, such as Eclipse MicroProfile.

Jakarta EE should make developers able to build cloud-native and mission-critical applications using the decades of developer experience built that Java EE was built upon.

The migration process from Java EE to Jakarta EE is complex, but, despite everything, it is proceeding relatively quickly.

After dealing with all the legal aspects related to the use of the name Java and javax within the specifications, it started the phase of migration of projects, specifications, and reference implementations to the Eclipse Foundation repositories.

This process requires a lot of effort because there are approximately 110 repositories to transfer. You can find the complete list with the project statuses here https://dmitrykornilov.net/2018/05/09/jakarta-ee-projects-summary/.

The community is performing the following activities:

  • Internal license checking in order to make sure licenses are correct.
  • Internal third-party analysis in order to identify what dependencies should be replaced with their latest versions to fix major bugs and security issues.
  • Renaming the original projects with the following scheme:
    • Eclipse Project for XXX for API projects
    • Eclipse XXX for implementation projects
  • Issuing transfers in order to preserve issue numbers and history without losing the previous job.
  • Building environments in order to create the infrastructure needed to compile and run, in an agile continuous-integration way, the projects that make up the Jakarta EE platform.
  • Aligning the previous projects' repositories in order to set a message that communicates that the project has been transferred to the Eclipse Foundation.

The base version for the final first release of Jakarta EE is Java EE 8.

At the end of the process, we will have a platform that will make all actors (vendors, Java communities, individuals, and so on) able to interact as peers with no one vendor holding, as in the spirit of the open source model.

So, with the power of the open source model, expressed in Jakarta EE and MicroProfile, do you think Java can still be a major player in the cloud and microservice world?

In my opinion, the answer is yes, and throughout the rest of the book, we will see together how to maximize the potential of Java and of the PaaS to create microservices in distributed environments.