Getting Started with MicroProfile applications

With the transition of Java EE to Jakarta EE, you can now adopt both Jakarta EE standards and MicroProfile stack for your projects. In this tutorial we will learn more about the MicroProfile API and the difference with other standars we have formerly used such as Java EE and SOA.

The era of monolithic application appears obsolete as many enterprises in the industries are looking for frameworks and APIs that would enable them to move efficiently into the cloud and microservies world.

Therefore, in parallel to the evolution of Jakarta EE, that will remain the main reference for complex scenarios (such as XA Transactions or communication with communication a Common Object Request Broker Architecture) a new architecture called MicroProfile emerged.

MicroProfile API components are built upon the model of Java EE making natural the transition to microservices development. Therefore, you will be able to reuse the valuable knowledge of java EE you have accumulated in these years, while having the flexibility to use multiple vendor specs to define application requirements. At this point we should briefly define what MicroServices are.

The best fitting definition for MicroServices is:

“You can think of microservices as modular, decoupled applications that can be independently deployed, modified, scaled and integrated with other systems and services.

Microservices are agile components that can be easily updated therefore you won’t need to stop the entire platform for days, until changes are propagated.”

Microservices vs SOA

You can think of Microservices as an evolution of the Service Oriented Architecture (SOA), with some similarities and notable differences though.

Let’s start from the similarities: both SOA and microservices architectures, unlike monolithic apps, deliver components which are solely responsible for a particular task. It follows that each component can also be developed using a different technology stack.

The first difference is that when developing microservices, each team can develop and deploy applications independently of other services. On the other hand, when using SOA, each team developing a service needs to know about the common communication mechanism to be used to achieve the SOA.

The second main difference between SOA and microservices is that in a SOA the Service Bus, used as communication layer between services, can potentially become a bottleneck or single point of failure. This does not happen in a microservices architecture where each service works independently from others so you can can fine tune its fault tolerance and resiliency.

In terms of storage, a SOA architecture normally used traditional shared data storage solution like a RDBMS. A microservice architecture, on the other hand, has a more flexible approach which is often declined as container native storage. That is, you define your storage as a container itself, just like your applications. Every approach as pros and cons: using a shared data solution makes easier to re-use data between applications. On the other hand, for applications that run independently from each other, an independent storage solution (like container storage) can be easier to bootstrap and to maintain.

Finally, the last difference, as you can imagine, is the size. A Microservice is a significantly smaller artifact and can be deployed indendently from other services. On the other hand, a SOA can be either deployed as a monolith or it can be as well comprised of multiple smaller services.

Developing with MicroProfile

Having clear what a MicroService is, how do we develop them using the MicroProfile architecture ? The main standard that is emerging is Eclipse MicroProfile which is a collection of community-driven open source specifications that define an enterprise Java microservices platform.

Here is an overview of the technology stack that is available using the MicroProfile stack:

microprofiles jakarta ee wildfly thorntail tutorial

As you can see, the technology stack mostly focuses on REST and CDI Services for the interaction between the microservices. JSON-P and JSON-B is also included out of the box as common transport language. (In blue you can see recently updated API in the Microprofile 2.0 spec)

There are multiple implementations of MicroProfile on the top of which vendors can add their customizations. For example, if you want to add Persistence stack to your microservices, then you can use Thorntail persistence implementation which is the well-known JPA Stack.

Throntail is not the only available option to develop with MicroProfile. Here is a list of the top options:

  • Red Hat – Thorntail
  • Red Hat – Red Hat Application Runtimes
  • IBM – WebSphere Liberty
  • IBM – Open Liberty
  • Payara Foundation – Payara Micro
  • Payara Foundation – Payara Server
  • Tomitribe – TomEE
  • Oracle – Helidon
  • Fujitsu – Launcher
  • SmallRye
  • Hammock
  • KumuluzEE

Coding a MicroProfile application

In order to kickstart a MicroProfile application, you can either use the multi-technology starter available at: https://start.microprofile.io/

microprofiles jakarta ee wildfly thorntail tutorial

Or you can use the starter for your specific implementation of MicroProfile. For example, if you are going to use Thorntail, then you can begin your journey with: https://thorntail.io/generator/

microprofile tutorial

We have discussed in this article how to bootstrap a project using Thorntail generator: Introduction to Thorntail

We will now have a look how to kick start a basic MicroProfile project that includes a mix of technologies. So get to https://start.microprofile.io/

As you can see from the Generator, the most important selection is related to the MicroProfile Server. The effect of your choice will be simply the Maven plugin that will be added to compile and bootstrap the microservice JAR.

For example, if you selected Payara Micro as Server, the following Maven plugin will be added to your pom.xml

 <build>
    <plugins>
      <plugin>
        <groupId>fish.payara.maven.plugins</groupId>
        <artifactId>payara-micro-maven-plugin</artifactId>
        <version>1.0.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>bundle</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <payaraVersion>5.191</payaraVersion>
        </configuration>
      </plugin>
    </plugins>
</build>

On the other hand, if you selected a Thorntail server, the Thorntail BOM and plugin will be added instead:

<build>
    <plugins>
      <plugin>
        <groupId>io.thorntail</groupId>
        <artifactId>thorntail-maven-plugin</artifactId>
        <version>${version.thorntail}</version>
        <executions>
          <execution>
            <goals>
              <goal>package</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
</build>
<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.thorntail</groupId>
        <artifactId>bom-all</artifactId>
        <version>${version.thorntail}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
</dependencyManagement>      

Let’s try generating a Thorntail-compatible application. The self-generated archive will contain the following artifacts:

├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── demo
│   │   │               ├── config
│   │   │               │   └── ConfigTestController.java
│   │   │               ├── DemoRestApplication.java
│   │   │               ├── health
│   │   │               │   └── ServiceHealthCheck.java
│   │   │               ├── HelloController.java
│   │   │               ├── metric
│   │   │               │   └── MetricController.java
│   │   │               ├── resilient
│   │   │               │   └── ResilienceController.java
│   │   │               └── secure
│   │   │                   └── ProtectedController.java
│   │   ├── resources
│   │   │   ├── jwt-roles.properties
│   │   │   ├── META-INF
│   │   │   │   ├── microprofile-config.properties
│   │   │   │   └── MP-JWT-SIGNER
│   │   │   └── project-defaults.yml
│   │   └── webapp
│   │       ├── index.html
│   │       └── WEB-INF
│   │           ├── beans.xml
│   │           └── web.xml
│   └── test
│       ├── java
│       │   └── com
│       │       └── example
│       │           └── demo
│       │               ├── JWTClient.java
│       │               └── MPJWTToken.java
│       └── resources
│           └── privateKey.pem

As you can see, a mini demo of MicroProfile healt, Config and Metrics has been generated. A configuration file which is peculiar for Thorntail has been included as well in resources/META-INF/project-defaults.yml

You can build and run the project with:

$ mvn thorntail:run

As Thorntail is bootstrapped, you can reach the demo at: http://localhost:8080

microprofiles jakarta ee wildfly thorntail tutorial

The example application is organized as a simple REST application, exposing a set of MicroProfile functionalities.

If you want to learn more about the Metrics API, check this article: Microprofile Metrics using WildFly application Server