Hybrid Deployments

Java Microservices with MicroProfile – RESTful APIs and Dependency Injection

Share this post:

For microservices-based apps, knowing how to create RESTful APIs is an essential skill. Eclipse MicroProfile makes it easier.

Developers and architects are talking about microservices and how they can break the existing monoliths to smaller, more easily scaled and managed application services. But how does the communication between these microservices happen? How do they communicate with the external world? I bet that I know your answer: RESTful APIs.

Specifically for Java applications, Java EE provides JAX-RS (Java API for RESTful Web Services). With its annotations, HTTP-centric nature, and format independence supporting a wide variety of content types, JAX-RS helps us to develop RESTful APIs on the Java EE platform. Along with the RESTful APIs, Context Dependency Injection (CDI) is equally important to manage the lifecycle of the application and to provide dependency injection. This is one of the most powerful specifications in Java EE.

In today’s installment of our Java Microservices from Spring Boot series, I will focus on how our team used these awesome features to build our simple storefront application using Eclipse MicroProfile.

Eclipse MicroProfile

Eclipse MicroProfile is optimized for developers to build microservices and cloud-native applications using enterprise Java. Using the available APIs in MicroProfile, developers can easily build small and efficient microservices with the power of traditional Java EE frameworks.

Quick recap of this Java Microservices series

In our last installment, we shared how we started our journey from Spring Boot to MicroProfile. In today’s installment, I’ll cover how we refactored our microservices with JAX-RS and CDI using Eclipse MicroProfile.

For those who may have joined late, this blog series is based on my team’s experience migrating our simple storefront application from a Spring Boot-based microservices to MicroProfile, an optimized microservices programming model for enterprise Java. It was originally coded using Spring Boot (source code) and migrated to MicroProfile (source code). Both the projects are hosted on GitHub with source code and full documentation.

NB: If you would like more background on Java microservices architectures:

You can also explore the Open Liberty guides to become a MicroProfile master.

Spring Boot or MicroProfile? Choose the path of least resistance

When developers are looking to transform an existing Java EE monolith application to microservices, they have lots of options. Spring developers lean towards Spring Boot, Scala developers prefer frameworks like Play, and developers using multiple languages like Java, JavaScript, and Groovy are inclined towards Vert.x. I am a Java developer and personally prefer Java over other languages. I came across Eclipse MicroProfile and found it beneficial to build next generation microservices and cloud-native applications. 

Spring Boot and MicroProfile have many of the same goals, i.e., you can do everything in MicroProfile that you can do in Spring Boot. Both of them are built on top of the same core APIs; even though there are differences in some of the APIs, the work they do is similar. Each of the frameworks have their own advantages. So, developers have freedom to choose and work with their preferred framework—Spring Boot or MicroProfile. 

With that preamble out of the way, let’s dive into the details of our migration story and see how our application BlueCompute, a simple storefront app (GitHub source) was built on Spring Boot and then later migrated to Eclipse MicroProfile.

Microservices app with Spring Boot: REST APIs

 
The REST web services are defined using Controller classes. These classes are responsible for handling different HTTP requests. To identify those classes, the @RestController annotation is used. To specify the route, mapping is done using @RequestMapping. Annotations like @GetMapping, @PostMapping, @PutMapping, @PatchMapping, and @DeleteMapping are used to map HTTP requests. Custom HTTP status codes are specified using @ResponseStatus. Variables coming from the path are captured using @PathVariable and query string parameters are captured using @RequestParam. To consume the JSON body and deserialize it, @RequestBody is used. These are some of the annotations that are used in the reference application. For more details, check out the BlueCompute – Spring implementation (GitHub).

Microservices app with Spring Boot: Dependency Injection

Inversion of Control (IC) is a software engineering principle most commonly used in object-oriented programming. It means that the control of the code is transferred to a framework or container. It can be done using various mechanisms—dependency injection is one among them. In our sample application, Inversion of Control is implemented using dependency injection. 

Dependency Injection is done using autowiring. All the required dependencies are annotated with @Autowired. In our application, autowiring is done byName. This means autowiring is based on the property’s name and Spring will look for the bean based on the name of the property. If the beans are of the same type, then the names can be specified using the @Qualifier annotation.

Microservices app with MicroProfile: JAX-RS

The Java API specification for RESTful web services is used for developing REST APIs and exposing them via annotations.  The path for the application, which is the base URI, is identified by @ApplicationPath. The path for the individual resource is specified using @Path. Annotations like @GET, @PUT, @POST, and @DELETE are used to map HTTP requests. The annotations @Produces and @Consumes are used for MIME media types. Variables coming from the path are captured using @PathParam annotation and query string params are captured using @QueryParam. These are some of the annotations that are used in the reference application. For more details, more check out the BlueCompute – MicroProfile implementation (GitHub).

Microservices app with MicroProfile: CDI

Contexts and Dependency Injection (CDI) is one of the most popular components in Java EE platform that simplifies application code. It provides required scopes to bind the objects to their well-defined contexts. One important feature is dependency injection. It allows developers to inject components into the application in a type-safe manner. In the reference application, scopes like @ApplicationScoped, @RequestScoped are used to bind the objects appropriately; dependency injection is done by injecting the objects using @Inject annotation. 

When we use the scope @ApplicationScoped, the instance is shared across all the interactions of the user within the application:

@ApplicationScoped
public class ItemService {
}

Where as when we use @RequestScoped, the instance is shared only in that particular HTTP request when the user interaction is done in CatalogService:

@RequestScoped
public class CatalogService {
       @Inject
       ItemService itemsRepo;
}

These are some of the annotations that are used in the reference application. For more details, check out the BlueCompute – MicroProfile implementation (GitHub).

Our journey from Spring Boot to MicroProfile

With the Spring Boot/MicroProfile differences understood, now let’s look at how we transformed our application using the standard APIs provided by MicroProfile.

We need the Maven dependency shown below in our pom.xml to build our application using MicroProfile:

<dependency>
    <groupId>org.eclipse.microprofile</groupId>
    <artifactId>microprofile</artifactId>
    <version>1.3</version>
    <scope>provided</scope>
    <type>pom</type>
</dependency>

In the server.xml of WebSphere Liberty, we added the MicroProfile feature:

<featureManager>
      <feature>microprofile-1.3</feature>
</featureManager>

The beauty of the MicroProfile feature is its various APIs that helps us to build microservices from scratch and helps us deliver them on different runtimes. JAX-RS 2.0 and CDI 1.1 are included in the very first release of MicroProfile, as these are the basic APIs any Java EE microservice requires. It is really nice to have them all in one place and make use of them without worrying about dependencies.

Now let’s walk through the details on how the migration is done. From our reference application, consider the Catalog Service in our simple storefront application. The model class Item is as follows:

public class Item {
    private long id;
    private String name;
    private String description;
    private int price;
    private String imgAlt;
    private String img;
    private int stock;
    // snip...
}

We began with the JAX-RS controller. As noted earlier, JAX-RS is used for providing both standard client and server APIs for RESTful communication by MicroProfile applications.

Below is a sample before/after snippet that gives you an idea of how the migration was done. While doing this migration, as a developer, I felt that the JAX-RS annotations were easier to understand compared to the Spring Boot annotations. I also felt that the code is more readable with JAX-RS that is specified by MicroProfile.

BEFORE: Spring Boot
AFTER: MicroProfile

The next step is to define CDI managed classes, with CDI handling all of the type-safe dependency injection. CDI helps us to manage the lifecycle of our objects in our application. Let’s review how we did it in our application.

If we consider the Catalog service in our reference implementation, we have a class called ItemService which contains some functions, e.g., the findAll() method that helps us to get all the items in the inventory.  This class should be persistent and same instance should be used across multiple resources. This can be done by CDI. By using CDI, the same instance of the class is injected into the application and used by it. In Spring Boot implementation of our sample application, we used @Autowired to inject the service class. The annotation @Service shown below makes the class auto-wireable. Whereas in the MicroProfile implementation of our sample application, we used the @ApplicationScoped annotation to achieve CDI and the injection is done using the @Inject annotation.  

BEFORE: Spring Boot
AFTER: MicroProfile

Hurray, that’s it! Our code is ready to run on WebSphere Liberty. 

For more details on how the Catalog Service is built, have a glance here. If you are interested, you can also see how we implemented a bunch of other features that comes with MicroProfile like Config, Fault Tolerance, Health Checks, Metrics, REST Client, Open API, Open Tracing, JSON-B along with JAX-RS and CDI. To run the whole application together, please check out BlueCompute – MicroProfile implementation (GitHub).

What’s next

In today’s world of microservices, developing RESTful APIs is an essential skill. JAX-RS is one of the most impressive specifications we have in Java EE; it helps us to build RESTful APIs of our choice using the annotations to simplify the development. Making the development of REST services easier is important! Similarly, having dependency injection is equally important in your Java EE applications. CDI allows you to manage the contexts and also helps you to inject the services in a type-safe manner. These two amazing features are enough to build a microservice—all you have to do is to use some simple annotations and add some dependency injection.

I found the Open Liberty guides to be a piece of cake—they are incredibly easy to understand and following them made my path easier. These are the ones I followed:

This blog demonstrated how we migrated our reference application from Spring Boot to MicroProfile using JAX-RS and CDI. This is just the beginning; you can do lot more with Eclipse MicroProfile. For example, interesting specifications like Fault Tolerance, REST Client, Health Checks, Metrics, Open API, Open Tracing, and Config are part of Eclipse MicroProfile. We’ll return to these through this blogs series.

Our next installment will cover MicroProfile RestClient & JSON-B. Meanwhile, stay tuned and have a look at our source code available on GitHub. All the individual microservices in our simple storefront application can be run locally using Maven as well. So, it should be simple for you to import them and run them as-is locally. You can also run them on IBM Cloud and IBM Cloud Private.

Cloud Solution Architect

More Hybrid Deployments stories
October 17, 2018

Certified Kubernetes Deployments Made Easy with WebSphere Liberty Cloud Pak

You want to have confidence in your cloud-based deployment of WebSphere Liberty on Kubernetes. Developers want an environment that's ready to go, administrators want an infrastructure that's trusted. Who wants to be in the business of stitching together component layers and then verifying they're compatible with each other? With IBM Cloud Paks, rely on a trusted and tested release with key components verified as a set.

Continue reading

October 11, 2018

Java Microservices with MicroProfile – Rest Client and JSON-B

To help us effectively implement REST, powerful languages like Java provide a vast library of convenient tools to use. Today's blog will highlight two features, MicroProfile's Rest Client 1.0 and JSON-B, and how to build them into your Java EE microservice application to help you achieve the benefits of cloud-based application performance, scalability, and simplicity. 

Continue reading

October 8, 2018

Ready, Set, Go! Migrate Your WebSphere App to Virtual Machines in the Cloud

Based on Kubernetes, IBM Cloud Private makes it easy to stand up an elastic runtime. For workload styles that need to stay in VMs, we’ve added WebSphere Application Server for IBM Cloud Private VM Quickstarter as an option. It’s a rapid way to migrate your traditional WebSphere app to an up-to-date V9 runtime integrated with IBM Cloud Private Core Operational Services.

Continue reading