Skip to main contentModernization   Playbook

Refactoring Java EE Applications

A phased approach to refactoring a Monolith in to Micro Services

Modernizing the backend JEE code


In this phase the JEE6 EJB code is modernized to use MicroProfile and is then able to run on the latest open source version of Liberty (OpenLiberty)

Move the backend monolith to OpenLiberty

Step 5

Restructure the repository

In order to use the capabilities provided by the OpenLiberty development mode and to make the modernization easier, the structure of the GitHub repository was changed from multiple modules to a single module.

OpenLiberty development mode provides the developer with a framework for:

  • Hot code replacements
  • Debugging incl. debugging in containers
  • IDE support like errors, warnings, auto-complete, and much more

The changes to the repository had the following steps:

  • Create a new Open Liberty project and copy the source code from all sub-projects in it
  • Merge all pom.xml files
  • Take over the configuration files (server.xml, persistence.xml, etc.)
  • Update the paths in the Dockerfile

The project structure on the left hand side shows the original multi-modules structure, the right side the simplified new structure.


If you wish to review the repositories structure and pom files, here are the links to the before repostory and after repository

Replace EJBs with CDI

To simplify the code, EJBs (Enterprise Java Beans) have been replaced with CDI (Contexts and Dependency Injection) since all code runs in the same context now. For example this was the original EJB code:

public class ProductSearchServiceImpl implements ProductSearchService {
public class CategoryResource {
@EJB ProductSearchService productSearch;
productSearch = (ProductSearchService) new InitialContext().lookup("java:app/CustomerOrderServices/ProductSearchServiceImpl!org.pwte.example.service.ProductSearchService");

This is the converted code using CDI:

public class ProductSearchServiceImpl implements ProductSearchService {
public class CategoryResource {
ProductSearchServiceImpl productSearch;

In order to handle transactions, you can use @Transactional which is part of the Java/Jakarta EE standard Java Transaction API (JTA). In the easiest case you simply use the annotation on your method.

public void updateLineItem(String productId, String newPrice) {

If you need more control, you can also manage the transactions manually:

protected EntityManager em;
UserTransaction utx;
public void updateLineItem(String productId, String newPrice) {

Update server.xml

In order to server.xml file was updated to change the features loaded by Liberty on startup. The older JEE6 features were removed and replaced by jakartaee-8.0andmicroprofile-3.3`. The final server.xml file can be found in the project repository.


Update the pom files

After combining the pom.xml files in the previous step, it is necessary to now add some dependencies for jakartaee-8.0 and microprofile-3.3 as shown below. The final pom.xml file is in the project repository


Update the Dockerfile

OpenLiberty uses the openliberty/open-liberty Docker images and has some minor differences from WebSphere Liberty regarding how features are loaded (OpenLiberty has it’s own command in addition to The final Dockerfile can be found in the project repository

FROM adoptopenjdk/maven-openjdk11 as BUILD
COPY . /usr/src/app/src
WORKDIR /usr/src/app/src/CustomerOrderServicesProject
RUN mvn clean package
FROM open-liberty:kernel-slim-java11-openj9
USER root
COPY --chown=1001:0 ./liberty/server.xml /config
COPY --chown=1001:0 ./liberty/server.env /config

Run this solution

Use the following steps to run this solution locally on Docker

$ git clone && cd application-modernization-javaee-quarkus
$ ROOT_FOLDER=$(pwd)
$ sh ${ROOT_FOLDER}/scripts-docker/
$ sh ${ROOT_FOLDER}/scripts-docker/


This application has been refactored in a series of steps from the original WebSphere ND v8.5.5 version to run as Micro Services on Red Hat OpenShift.