DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Java
  4. Java EE MicroProfile With KumuluzEE

Java EE MicroProfile With KumuluzEE

In the world of Java EE microservices, all eyes are on MicroProfile. But KumuluzEE is already in the game. Let's link and configure some microservices.

Piotr Mińkowski user avatar by
Piotr Mińkowski
CORE ·
Aug. 01, 17 · Tutorial
Like (6)
Save
Tweet
Share
9.90K Views

Join the DZone community and get the full member experience.

Join For Free

Enterprise Java seems to be a step back from the others when it comes to microservices architecture. Some weeks ago, I took a part in Code Europe – the programming conference in Warsaw. One of the speakers was Ivar Grimstad, who was talking about MicroProfile – an open initiative for optimizing Enterprise Java for a microservices architecture. This idea is very interesting, but at the moment, it is rather at the beginning of the road.

However, while I was reading about the microprofile initiative, I came across information about JavaEE framework developed by Slovenian company – KumuluzEE. The solution seemed to be interesting enough that I decided to take a closer look at it. Well, we can read on the website that KumuluzEE is the Java Duke’s Choice Award Winner, so there is still a hope for JavaEE and microservices

What’s KumuluzEE

Can KumuluzEE be a competitor to the Spring Cloud framework? It is certainly not as popular and advanced when it comes to solutions for microservices like Spring Cloud, but it has basic modules for service registration, discovery, distributed configuration propagation, circuit breaking, metrics, and support for Docker and Kubernetes. It uses CDI on JBoss Weld containers for dependency injection and Jersey as a REST API provider. Modules for configuration and discovery are based on Consul or etcd, though they are at the early stage of development (1.0.0-SNAPSHOT).

But let’s try it out.

Preparation

I’ll show you a sample application that consists of two independent microservices — account-service and customer-service. Both of them expose a REST API, and one of the customer-service methods invokes a method from account-service. Every microservice registers itself in Consul and is able to get configuration properties from Consul. The sample application source code is available on GitHub. Before we begin, let’s start a Consul instance using a Docker container.

docker run -d --name consul -p 8500:8500 -p 8600:8600 consul


We should also add some KumuluzEE dependencies to the Maven pom.xml.

<dependency>
    <groupId>com.kumuluz.ee</groupId>
    <artifactId>kumuluzee-core</artifactId>
</dependency>
<dependency>
    <groupId>com.kumuluz.ee</groupId>
    <artifactId>kumuluzee-servlet-jetty</artifactId>
</dependency>
<dependency>
    <groupId>com.kumuluz.ee</groupId>
    <artifactId>kumuluzee-jax-rs-jersey</artifactId>
</dependency>
<dependency>
    <groupId>com.kumuluz.ee</groupId>
    <artifactId>kumuluzee-cdi-weld</artifactId>
</dependency>


Service Registration

To enable service registration, we should add one additional dependency to our pom.xml. I chose Consul as a registration and discovery server, but you can also use etcd (kumuluzee-discovery-consul).

<dependency>
    <groupId>com.kumuluz.ee.discovery</groupId>
    <artifactId>kumuluzee-discovery-consul</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>


Inside the application configuration file, we should set discovery properties and a server URL. For me, it is 192.168.99.100.

kumuluzee:
  service-name: account-service
  env: dev
  version: 1.0.0
  discovery:
    consul:
      agent: http://192.168.99.100:8500
      hosts: http://192.168.99.100:8500
    ttl: 20
    ping-interval: 15


Here’s the account microservice's main class. As you probably guess, the annotation @RegisterService enables registration on the server.

@RegisterService("account-service")
@ApplicationPath("v1")
public class AccountApplication extends Application {
 
}


We start the application by running:

java -cp target/classes;target/dependency/* com.kumuluz.ee.EeApplication

Remember to override the default port by setting the environment property: PORT. I started two instances of account and one of the customer microservice.

kumuluzee-1

Service Discovery

The customer microservice exposes the API, but it also invokes the API method from account-service, so it has to discover and connect to this service. The Maven dependencies and configuration settings are the same as for account-service. The only difference is the resource class. Here’s the CustomerResource fragment, where we are invoking endpoint GET /customer/{id}.

@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("customers")
@RequestScoped
public class CustomerResource {
 
    private List<Customer> customers;
 
    @Inject
    @DiscoverService(value = "account-service", version = "1.0.x", environment = "dev")
    private WebTarget target;
 
    ...
 
    @GET
    @Path("{id}")
    @Log(value = LogParams.METRICS, methodCall = true)
    public Customer findById(@PathParam("id") Integer id) {
        Customer customer = customers.stream().filter(it -> it.getId().intValue() == id.intValue()).findFirst().get();
        WebTarget t = target.path("v1/accounts/customer/" + customer.getId());
        List<Account> accounts = t.request().buildGet().invoke(List.class);
        customer.setAccounts(accounts);
        return customer;
    }
}


There is one pretty cool thing about discovery with KumuluzEE. As you can see in the @DiscoverService, we can specify a version and environment for account-service instance. The version and environment for the microservice is read automatically from the config.yml during registration in discovery server. So, we can maintain many versions of a single microservice and freely invoke them from other microservices. Requests are automatically load balanced between all microservice match conditions from the annotation @ServiceDiscovery.

We can also monitor metrics, such as response time, by declaring @Log(value = LogParams.METRICS, methodCall = true) on the API method. Here’s a log fragment for account-service:

2017-07-28 13:57:01,114 TRACE ENTRY[ METHOD ] Entering method. {class=pl.piomin.services.kumuluz.account.resource.AccountResource, method=findByCustomer, parameters=[1]}
2017-07-28 13:57:01,118 TRACE EXIT[ METHOD ] Exiting method. {class=pl.piomin.services.kumuluz.account.resource.AccountResource, method=findByCustomer, parameters=[1], response-time=3, result=[pl.piomin.services.kumuluz.account.model.Account@1eb26fe3, pl.piomin.services.kumuluz.account.model.Account@2dda41c5]}


Distributed Configuration

To enable KumuluzEE Config, include the Consul implementation by adding the following dependency to your pom.xml.

<dependency>
    <groupId>com.kumuluz.ee.config</groupId>
    <artifactId>kumuluzee-config-consul</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>


I do not use a Consul agent running on the localhost, so I need to override some properties in config.yml. I also defined one configuration property, blacklist:

kumuluzee:
  config:
    start-retry-delay-ms: 500
    max-retry-delay-ms: 900000
    consul:
      agent: http://192.168.99.100:8500
 
rest-config:
  blacklist:


Here’s the class that loads the configuration properties and enables dynamic updates on any change in the configuration source by declaring @ConfigValue(watch = true) on a property.

@ApplicationScoped
@ConfigBundle("rest-config")
public class AccountConfiguration {
 
    @ConfigValue(watch = true)
    private String blacklist;
 
    public String getBlacklist() {
        return blacklist;
    }
 
    public void setBlacklist(String blacklist) {
        this.blacklist = blacklist;
    }
 
}


We use the configuration property blacklist in the resource class for filtering all accounts by blacklisted ids.

@GET
@Log(value = LogParams.METRICS, methodCall = true)
public List<Account> findAll() {
    final String blacklist = ConfigurationUtil.getInstance().get("rest-config.blacklist").orElse("nope");
    final String[] ids = blacklist.split(",");
    final List<Integer> blacklistIds = Arrays.asList(ids).stream().map(it -> new Integer(it)).collect(Collectors.toList());
    return accounts.stream().filter(it -> !blacklistIds.contains(it.getId())).collect(Collectors.toList());
}


The configuration property should be defined in the Consul UI Dashboard under the KEY/VALUE tab. KumuluzEE enforces a certain format of key names. In this case it has to be:

environments/dev/services/account-service/1.0.0/config/rest-config/blacklist

You can update a property value and test changes by invoking http://localhost:2222/v1/accounts.

kumuluzee-2

Final Words

Creating microservices with KumuluzEE is pretty easy. I showed you the main capabilities of this framework. KumulezEE has also modules for circuit breakers with Hystrix, streaming with Apache Kafka, and security with OAuth2/OpenID. I will keep a close eye on this library, and I hope it will continue to be developed.

microservice Java (programming language) Java EE Property (programming)

Published at DZone with permission of Piotr Mińkowski, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Custom Validators in Quarkus
  • Front-End Troubleshooting Using OpenTelemetry
  • How To Build a Spring Boot GraalVM Image
  • Comparing Map.of() and New HashMap() in Java

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: