At Tomitribe we are active stakeholders on projects like Apache TomEE, MicroProfile, and JakartaEE and provide Enterprise Support for these and other Open Source projects like Apache Tomcat & Active MQ.
In this article, we will cover how developers can create a microservice with Java using the MicroProfile specifications with the DevOps friendly application server, Apache TomEE.
If MicroProfile is a topic you want to learn more about, we have many other blog posts covering the basics of MicroProfile with details of each of the specifications along with examples. The official Apache TomEE project website also has a series of example projects built with Java, Maven and MicroProfile.
MicroProfile meets TomEE
By now, you should be familiar with the MicroProfile specifications illustrated below, but it’s important to highlight that TomEE MicroProfile is based on TomEE JAX-RS. As a result, many of the Jakarta EE (formally Java EE) technologies in TomEE already support MicroProfile out of the box.
Create a microservice using TomEE tomee-webapp-archetype
In order to create a project using the Tomee webapp
archetype, execute the following command in a console:
$ mvn archetype:generate -B -DarchetypeGroupId=org.apache.tomee.maven -DarchetypeArtifactId=tomee-webapp-archetype -DarchetypeVersion=8.0.0-M2 -DgroupId=superbiz.foo -DartifactId=book-microservice
The project structure contains the following specifications and technologies out of the box to give you a sample of what you can do with a vanilla JakartaEE project:
- Stateless EJB:
BookService.java
- Java API: Book.java,
persistence.xml
- CDI Bean:
BookBean.java
- JSF: book.xhtml and
result.xhtml
Arquillian.xml
: Commented out for you to decide to use it or not later in your integration tests.
book-microservice$ tree
.
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── superbiz
│ │ └── foo
│ │ ├── application
│ │ │ └── BookService.java
│ │ ├── entities
│ │ │ └── Book.java
│ │ └── presentation
│ │ └── BookBean.java
│ ├── resources
│ │ └── META-INF
│ │ └── persistence.xml
│ └── webapp
│ ├── WEB-INF
│ │ ├── beans.xml
│ │ └── faces-config.xml
│ ├── book.xhtml
│ ├── index.jsp
│ └── result.xhtml
└── test
└── resources
└── arquillian.xml
14 directories, 11 files
To add MicroProfile capabilities to our project we need to update the <dependencies<
section in the pom.xml
by adding the MicroProfile dependency with a provided scope to indicate that our application will rely on TomEE to provide the necessary libs:
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>2.0.1</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
Finally, we need to update the <configuration>
from the tomee-maven-plugin
. We need to include the <tomeeClassifier>
to declare the microprofile TomEE version we want to use with the plugin.
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>8.0.0-M2</version>
<configuration>
<context>ROOT</context>
<tomeeClassifier>microprofile</tomeeClassifier>
</configuration>
</plugin>
On a terminal you can build and run the project using the Tomee Maven plugin:
$ mvn clean package tomee:run
You will notice that the MicroProfile metrics endpoints appear on the startup log:
INFO Service URI: http://localhost:8080/health INFO GET http://localhost:8080/metrics/{registry}/{metric} INFO OPTIONS http://localhost:8080/metrics/{registry} INFO OPTIONS http://localhost:8080/metrics/{registry}/{metric} Starting ProtocolHandler ["http-nio-8080"] Starting ProtocolHandler ["ajp-nio-8009"] Server startup in 3964 ms
When the Maven command is finished you can visit the URL http://localhost:8080/metrics and visualize the corresponding server metrics:
# TYPE base:classloader_total_loaded_class_count counter base:classloader_total_loaded_class_count 9898.0 # TYPE base:thread_count counter base:thread_count 42.0 # TYPE base:classloader_current_loaded_class_count counter base:classloader_current_loaded_class_count 9898.0 # TYPE base:jvm_uptime_seconds gauge base:jvm_uptime_seconds 0.05792 # TYPE base:gc_ps_mark_sweep_count counter base:gc_ps_mark_sweep_count 2.0 # TYPE base:gc_ps_scavenge_count counter base:gc_ps_scavenge_count 8.0 # TYPE base:memory_committed_heap_bytes gauge base:memory_committed_heap_bytes 3.62807296E8 # TYPE base:thread_max_count counter base:thread_max_count 42.0 # TYPE base:cpu_available_processors gauge base:cpu_available_processors 4.0 # TYPE base:thread_daemon_count counter base:thread_daemon_count 41.0 # TYPE base:classloader_total_unloaded_class_count counter base:classloader_total_unloaded_class_count 9898.0 # TYPE base:memory_max_heap_bytes gauge base:memory_max_heap_bytes 3.817865216E9 # TYPE base:gc_ps_mark_sweep_time_seconds gauge base:gc_ps_mark_sweep_time_seconds 2.25E-4 # TYPE base:memory_used_heap_bytes gauge base:memory_used_heap_bytes 7.280616E7 # TYPE base:gc_ps_scavenge_time_seconds gauge base:gc_ps_scavenge_time_seconds 2.14E-4 # TYPE vendor:start_time counter vendor:start_time 1.565888981255E12
Remember that instead of the Prometheus format you can also request the JSON format by adding the Accept
request header with the value application/json
.
{
"application": {
},
"vendor": {
"startTime": 1565748321261
},
"base": {
"classloader.totalLoadedClass.count": 9816,
"thread.count": 42,
"classloader.currentLoadedClass.count": 9816,
"jvm.uptime": 29459,
"gc.PS MarkSweep.count": 2,
"thread.max.count": 42,
"memory.committedHeap": 363855872,
"gc.PS Scavenge.count": 8,
"cpu.availableProcessors": 4,
"thread.daemon.count": 41,
"classloader.totalUnloadedClass.count": 9816,
"memory.maxHeap": 3817865216,
"memory.usedHeap": 70708544,
"gc.PS MarkSweep.time": 106,
"gc.PS Scavenge.time": 94
}
}
To quit the microservice type on the terminal crtl+c
Create a microservice using MicroProfile Starter Website
The MicroProfile community offers the MicroProfile Starter website to build Maven basic projects with or without examples.To create a new project you can visit the URL: https://start.microprofile.io/ and fill out your project details. For this example we will use the following:
- groupId:
superbiz.foo
- artifactId:
movie-microservice
- MicroProfile versión:
2.0
- MicroProfile server:
Apache TomEE 8.0.0-M2
- Example of specifications: Deselect everything except for “Config” ( MicroProfile configuration).
After clicking on the DOWNLOAD button, a movie-microservice.zip
file is downloaded to your computer. After extracting the zip file you will see that the structure of the maven based project is pretty similar to what we got by using the Tomee web app archetype:
movie-microservice$ tree
.
├── pom.xml
├── readme.md
└── src
├── main
│ ├── java
│ │ └── superbiz
│ │ └── foo
│ │ └── movie
│ │ └── microservice
│ │ ├── HelloController.java
│ │ ├── MoviemicroserviceRestApplication.java
│ │ └── config
│ │ └── ConfigTestController.java
│ ├── resources
│ │ ├── META-INF
│ │ │ └── microprofile-config.properties
│ │ └── publicKey.pem
│ └── webapp
│ ├── WEB-INF
│ │ └── beans.xml
│ └── index.html
└── test
└── java
14 directories, 9 files
This time the project structure contains the following technologies and specifications:
- Java JAX-RS: HelloController.java and
MoviemicroserviceRestApplication.java
- JAX-RS endpoint with MicroProfile Config injection:
ConfigTestController.java
- MicroProfile config configuration file:
META-INF/microprofile-config.properties
There is one important difference in the project pom.xml
file compared against to the one used with the Tomee webapp
archetype, the project generated by the MicroProfile Starter already contains the maven MicroProfile dependency and tomeeClassifier
in the maven-plugin configuration.
On a terminal, you can build and run the movie-microservice
project using the Tomee Maven plugin:
Make sure you quit the microservice we created previously before proceeding.
$ mvn clean package tomee:run
You will notice that the MicroProfile metrics endpoints appear on the startup log again but now with the application context as prefix:
INFO Service URI: http://localhost:8080/data/health INFO GET http://localhost:8080/data/metrics/{registry}/{metric} INFO OPTIONS http://localhost:8080/data/metrics/{registry} INFO OPTIONS http://localhost:8080/data/metrics/{registry}/{metric} Starting ProtocolHandler ["http-nio-8080"] Starting ProtocolHandler ["ajp-nio-8009"] Server startup in 3964 ms
You can visit now you the URL http://localhost:8080/data/metrics and visualize the corresponding server metrics (shown below in the JSON format):
{
"application": {
},
"vendor": {
"startTime": 1565794360335
},
"base": {
"classloader.totalLoadedClass.count": 9153,
"thread.count": 39,
"classloader.currentLoadedClass.count": 9153,
"jvm.uptime": 106749,
"gc.PS MarkSweep.count": 2,
"thread.max.count": 39,
"memory.committedHeap": 353370112,
"gc.PS Scavenge.count": 8,
"cpu.availableProcessors": 4,
"thread.daemon.count": 38,
"classloader.totalUnloadedClass.count": 9153,
"memory.maxHeap": 3817865216,
"memory.usedHeap": 103169320,
"gc.PS MarkSweep.time": 124,
"gc.PS Scavenge.time": 118
}
}
You also can visit the endpoint http://localhost:8080/data/config/injected that shows the value injected in the JAX-RS endpoint using MicroProfile config:
$ curl http://localhost:8080/data/config/injected Config value as Injected by CDI Injected value
Create a microservice using MicroProfile Starter REST API
MicroProfile Starter also offers a REST API that you can use to create a new project with the parameters and options available on the website version.
To create the song-microservice
with the same structure as the movie-microservice
you need to do a GET
request with the following parameters:
$ curl -O -J 'https://start.microprofile.io/api/1/project?supportedServer=TOMEE&groupId=superbiz.foo&artifactId=songs-microservice&selectedSpecs=CONFIG'
Curl -O
-J
tells curl to save the zip file in the current directory.
The songs-microservice.zip
gets downloaded and the project structure is the same we got for the movie-microservice
:
songs-microservice$ tree
.
├── pom.xml
├── readme.md
└── src
├── main
│ ├── java
│ │ └── superbiz
│ │ └── foo
│ │ └── songs
│ │ └── microservice
│ │ ├── HelloController.java
│ │ ├── SongsmicroserviceRestApplication.java
│ │ └── config
│ │ └── ConfigTestController.java
│ ├── resources
│ │ ├── META-INF
│ │ │ └── microprofile-config.properties
│ │ └── publicKey.pem
│ └── webapp
│ ├── WEB-INF
│ │ └── beans.xml
│ └── index.html
└── test
└── java
14 directories, 9 files
On a terminal you can build and run the songs-microservice
project using the Tomee Maven plugin:
Again, make sure you quit the microservice we created previously before proceeding.
$ mvn clean package tomee:run
You can visit now you the URL http://localhost:8080/data/metrics and visualize the corresponding server metrics.
Contribute and join the conversation
Both the Tomee webapp
archetype and MicroProfile Starter are OpenSource projects. You can join the discussions about these projects and collaborate on both code bases by visiting:
Conclusion
In this article, we covered how you can create a MicroProfile project from scratch with TomEE DevOps features using maven archetypes and rest endpoints. Now, it is easy to take advantage of TomEE’s Jakarta EE (formerly Java EE) capabilities in your newly created project and integrate MicroProfile in your existing projects.