Core Java

Migrating Monoliths to Quarkus: CDI, Docker & Migration Insights

Migrating a large, mission-critical Java EE monolith to microservices isn’t exactly a “Friday afternoon” task. It’s often messy, political, and requires both technical courage and enterprise diplomacy.

But with modern frameworks like Quarkus, enterprises finally have a realistic path forward—one that doesn’t mean rewriting every line of code or abandoning decades of investment in Java EE.

In this article, I’ll walk through a realistic migration path: breaking down a monolith, modernizing with CDI (Contexts and Dependency Injection), containerizing with Docker, and sharing some hard-won lessons along the way.

Why Quarkus for Monolith Migration?

Before jumping into steps, let’s answer the “why.”

  • Supersonic Subatomic Java: Quarkus is built for fast startup times and low memory footprint, making it ideal for containers and serverless.
  • CDI First-Class Citizen: Quarkus embraces CDI, which makes migrating from Java EE (Jakarta EE) far less painful.
  • MicroProfile Support: Brings in config, health checks, fault tolerance, metrics—everything microservices need.
  • Developer Experience: Hot reload and dev mode (quarkus:dev) speed up iteration dramatically compared to classic Java EE servers.

👉 Translation: Quarkus gives you cloud-native benefits while still speaking the Java EE language you know.

Step 1: Assessing the Monolith

Migration starts with analysis, not code.

  • Identify modules and business domains within the monolith.
  • Classify them: core, shared utilities, legacy nobody-wants-to-touch.
  • Look for natural service boundaries (e.g., billing, customer, notifications).

💡 Lesson learned: Don’t try to split everything at once. Start with one well-defined module that has clear APIs.

Step 2: Extracting Services

Pick a candidate (say, Customer Management).

  • Define a clear API contract (REST or gRPC).
  • Migrate EJBs or managed beans into CDI beans.
  • Replace container-managed transactions with Quarkus-managed CDI scopes.

Example CDI bean migration:

From Java EE EJB:

@Stateless
public class CustomerService {
    public Customer findCustomer(Long id) { ... }
}

To Quarkus CDI:

import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class CustomerService {
    public Customer findCustomer(Long id) { ... }
}

Simple swap—but it frees you from the application server and makes the class container-friendly.

Step 3: Wiring with Quarkus CDI

Quarkus CDI is lightweight but powerful:

@Path("/customers")
public class CustomerResource {

    @Inject
    CustomerService customerService;

    @GET
    @Path("/{id}")
    public Customer getCustomer(@PathParam("id") Long id) {
        return customerService.findCustomer(id);
    }
}

No heavyweight XML descriptors. Just annotations and Quarkus magic.

Step 4: Containerization with Docker

Once services are modularized, it’s time to containerize.

Quarkus makes this easy with its fast startup and small footprint.

Example Dockerfile (native image):

FROM quay.io/quarkus/ubi-quarkus-native-image:22.3-java17 AS build
WORKDIR /project
COPY . .
RUN ./mvnw package -Pnative

FROM quay.io/quarkus/quarkus-micro-image:1.0
WORKDIR /work/
COPY --from=build /project/target/*-runner /work/application
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
  • Startup in milliseconds.
  • Memory usage small enough for tight Kubernetes clusters.
  • Scaling becomes cost-efficient.

Step 5: Infrastructure Integration

Microservices don’t live in isolation. After containerization, integrate with:

  • Config: quarkus-config + MicroProfile Config.
  • Health Checks: quarkus-smallrye-health.
  • Metrics: quarkus-smallrye-metrics.
  • Resilience: quarkus-smallrye-fault-tolerance.

Example health check:

import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Readiness;
import jakarta.enterprise.context.ApplicationScoped;

@Readiness
@ApplicationScoped
public class DatabaseHealthCheck implements HealthCheck {
    public HealthCheckResponse call() {
        return HealthCheckResponse.up("Database is reachable");
    }
}

Step 6: Lessons Learned in the Migration

From real migrations, here are key insights:

  1. Don’t “Big Bang” It – Extract services incrementally. Migrating a monolith in one shot usually ends in frustration.
  2. Watch Your Database – The DB schema often stays monolithic longer than the code. Introduce APIs and eventually move to separate schemas.
  3. Embrace CDI Early – CDI is your friend in Quarkus; embrace it to simplify service wiring.
  4. Invest in CI/CD Pipelines – Microservices only shine if you automate build, test, and deploy.
  5. Cultural Change is Harder than Code – Developers comfortable with app servers may resist. Show quick wins (fast boot, low memory) to win hearts.

Final Thoughts

Migrating from a Java EE monolith to Quarkus-based microservices isn’t just about swapping frameworks—it’s about rethinking architecture.

Quarkus makes the technical side far easier, with CDI, container-native builds, and MicroProfile support. But the real key is taking it step by step, aligning with business priorities, and treating migration as a journey, not a deadline.

If done right, you end up with a system that’s faster, cheaper to run, and ready for the cloud-native era—without throwing away decades of investment in Java.

Useful Links

👉 If you’re sitting on a Java EE monolith, what’s stopping you from trying Quarkus for at least one service? Worst case—you learn something new. Best case—you start your journey to cloud-native Java.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button