For microservices-based Java apps, knowing how to create REST APIs is an essential skill. Eclipse MicroProfile makes it easier.
What are microservices and how do they break the existing monoliths into smaller, more easily scaled and managed application services? How does the communication between these microservice apps happen? How do they communicate with the external world? If you are a developer, I bet that I know your answer: REST APIs.
Specifically for microservices applications, Java EE provides the Java API for RESTful Web Services (JAX-RS) framework. With its annotations, HTTP-centric nature, and format independence supporting a wide variety of content types, JAX-RS helps build REST 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 compare the implementation of two different Java microservices frameworks—Spring Boot and Eclipse MicroProfile—using our example storefront application.
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:
Refer to the Microservices reference architecture.
Watch the Deploying Microservices in IBM Cloud Private webinar.
Explore the BlueCompute Reference Application in GitHub.
Deploy BlueCompute on IBM Cloud Private today.
Read "Microservices: A Complete Guide."
You can also explore the Open Liberty guides to become a MicroProfile master.
Spring Boot or MicroProfile for Java microservices apps? Choose the path of least resistance
The Spring Boot and MicroProfile frameworks 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, the Java EE microservices framework.
Microservices app with Spring Boot: REST APIs Example
With the Spring Boot framework, REST APIs are defined using
Controller classes. These classes are responsible for handling different HTTP requests. To identify those classes, the
@RestControllerannotation is used. To specify the route, mapping is done using
@RequestMapping. Annotations like
@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 example Spring Boot application. For more details, check out the BlueCompute – Spring implementation (GitHub).
Microservices app with Spring Boot: Dependency Injection Example
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
Microservices app with MicroProfile: Example Java REST API using JAX-RS
The Java API specification for RESTful frameworks 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
@DELETEare used to map HTTP requests. The annotations
@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 example Java MicroProfile application. For more details, more check out the BlueCompute – MicroProfile implementation(GitHub).
Microservices app with MicroProfile: Context and Dependency Injection (CDI) Example
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 our example application, scopes like
@RequestScoped are used to bind the objects appropriately; dependency injection is done by injecting the objects using
When we use the scope
@ApplicationScoped, the instance is shared across all the interactions of the user within the application:
Where as when we use
@RequestScoped, the instance is shared only in that particular HTTP request when the user interaction is done in
These are some of the annotations that are used in the example 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 Java application using MicroProfile:
server.xml of WebSphere Liberty, we added the MicroProfile feature:
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 example application, consider the Catalog Service in our simple storefront application. The model class
Item is as follows:
We began with the JAX-RS controller. As noted earlier, JAX-RS is used for providing both standard Java 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
The next step is to define Context Dependency Injection 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 example implementation, we have a class called
ItemServicewhich 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 dependency injection can be done by CDI. By using CDI, the same instance of the class is injected into the application and used by it. In the 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 dependency injection using the
BEFORE: Spring Boot
Hurray, that’s it! Our code is ready to run on WebSphere Liberty.
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).
In today’s world of microservices, developing RESTful APIs is an essential skill. JAX-RS is one of the most impressive REST API frameworks 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 example 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.