Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Making Java programs cloud-ready, Part 4: Optimize the runtime environment

July 2, 2021
Mauro Vocale
Related topics:
JavaKubernetesMicroservices
Related products:
Developer ToolsRed Hat JBoss Enterprise Application PlatformRed Hat OpenShift LocalRed Hat OpenShift Container Platform

Share:

    This is the final article in a series where we are updating a monolithic Java EE application to function as a microservice and run in a distributed cloud environment such as Red Hat OpenShift. In the first article, we set up the legacy Java application and defined our goals. Then, we upgraded the Java environment to Jakarta EE. In the last article, we used MicroProfile to prepare the application for use in a distributed environment.

    Read the whole series:

    • Part 1: An incremental approach using Jakarta EE and MicroProfile

    • Part 2: Upgrade the legacy Java application to Jakarta EE

    • Part 3: Integrate MicroProfile services

    • Part 4: Optimize the runtime environment

    We now have all the functionality we planned to add to our cloud-ready Java application. However, the resulting image is substantially larger than our initial image. This is not optimal because we'll need to transfer the image over the network and run it on a platform-as-a-service (PaaS) in the cloud. Resources such as memory, CPU, and RAM use factor into the costs charged by a PaaS provider. In this final article, we'll optimize the runtime to reduce the image's size and memory footprint. The benefits of optimizing the runtime include:

    • Better cloud-resource utilization.
    • Decreasing startup and scale-up time.
    • Minimizing the attack surface.

    Runtime optimization with JBoss EAP, JBoss EAP XP, and Galleon

    We'll use Red Hat JBoss Enterprise Application Platform (JBoss EAP) and JBoss EAP XP to decrease the size of our application image while also increasing container security. First, we'll develop a runtime image that eliminates development tools (such as Maven artifacts) that were present in the original Source-to-Image (S2I) environment. Then, we'll use Galleon to trim the application features and provide customization for JBoss EAP and its image’s footprint.

    Note that we'll use the same GitHub repository we've used for the previous articles in the series. To start, switch to the git tag that contains the source code used to implement the Galleon version:

    $ git checkout tags/Galleon_Runtime_version

    Now, delete the previous version of the application to start with a clean environment:

    $ oc delete all --selector app=weather-app-eap-cloud-ready 
    $ oc delete is weather-app-eap-cloud-ready
    $ oc delete bc weather-app-eap-cloud-ready

    Import the image for the JBoss EAP XP 2.0 OpenJDK 11 runtime:

    $ oc import-image jboss-eap-7/eap-xp2-openjdk11-runtime-openshift-rhel8 --from=registry.redhat.io/jboss-eap-7/eap-xp2-openjdk11-runtime-openshift-rhel8 --confirm

    Update the buildConfig

    Now let's focus on the buildConfig.yaml file under the k8s directory. In that file, I defined a chained build with two buildConfig objects: weather-app-eap-cloud-ready-build-artifacts and weather-app-eap-cloud-ready. The first one is the S2I builder image that contains a complete JBoss EAP server with tooling needed during the S2I build. The second one has the runtime image that contains dependencies needed to run JBoss EAP. The first build creates the JBoss EAP XP instance and the application to be deployed, whereas the second build excludes the development tools not needed in the production environment. Figure 1 summarizes the components of the development process and their relationships.

    Diagram with the steps needed to obtain a runtime image.
    Figure 1: Components of builds for our containerized application.

    Here is a snapshot of the chained build:

    kind: ImageStream
    apiVersion: image.openshift.io/v1
    metadata:
      name: weather-app-eap-cloud-ready-build-artifacts
      labels:
        application: weather-app-eap-cloud-ready-build-artifacts
    ---
    kind: ImageStream
    apiVersion: image.openshift.io/v1
    metadata:
      name: weather-app-eap-cloud-ready
      labels:
        application: weather-app-eap-cloud-ready
    ---
    kind: BuildConfig
    apiVersion: build.openshift.io/v1
    metadata:
      name: weather-app-eap-cloud-ready-build-artifacts
      namespace: redhat-jboss-eap-cloud-ready-demo
      labels:
        build: weather-app-eap-cloud-ready-build-artifacts
    spec:
      output:
        to:
          kind: ImageStreamTag
          name: 'weather-app-eap-cloud-ready-build-artifacts:latest'
      resources: {}
      strategy:
        type: Source
        sourceStrategy:
          from:
            kind: ImageStreamTag
            namespace: redhat-jboss-eap-cloud-ready-demo
            name: 'eap-xp2-openjdk11-openshift-rhel8:latest'
      source:
        type: Binary
        binary: {}
    ---
    kind: BuildConfig
    apiVersion: build.openshift.io/v1
    metadata:
      labels:
        application: weather-app-eap-cloud-ready
      name: weather-app-eap-cloud-ready
    spec:
      output:
        to:
          kind: ImageStreamTag
          name: weather-app-eap-cloud-ready:latest
      source:
        dockerfile: |-
          FROM eap-xp2-openjdk11-runtime-openshift-rhel8
          COPY /server $JBOSS_HOME
          USER root
          RUN chown -R jboss:root $JBOSS_HOME && chmod -R ug+rwX $JBOSS_HOME
          USER jboss
          CMD $JBOSS_HOME/bin/openshift-launch.sh
        images:
        - from:
            kind: ImageStreamTag
            name: weather-app-eap-cloud-ready-build-artifacts:latest
          paths:
          - sourcePath: "/s2i-output/server/"
            destinationDir: "."
      strategy:
        dockerStrategy:
          imageOptimizationPolicy: SkipLayers
          from:
            kind: ImageStreamTag
            name: eap-xp2-openjdk11-runtime-openshift-rhel8:latest
            namespace: redhat-jboss-eap-cloud-ready-demo
        type: Docker
      triggers:
      - imageChange: {}
        type: ImageChange

    Configure JBoss EAP XP using Galleon

    We'll also need to configure JBoss EAP XP to run it using the runtime image. To configure this mode, I set the following environment variables in the environment file under the .s2i directory:

    #GALLEON_PROVISION_DEFAULT_FAT_SERVER=true
    GALLEON_PROVISION_LAYERS=jaxrs-server,microprofile-platform
    S2I_COPY_SERVER=true

    The final image will contain a server, a packaged application, and the runtime required to launch JBoss EAP. As shown in the YAML snippet, there are two properties related to the Galleon framework. The first one creates a full-featured JBoss EAP XP subsystem:

    GALLEON_PROVISION_DEFAULT_FAT_SERVER=true

    But our target is not only to have a slim and more secure container image that omits unnecessary tools. We also want to improve the use of cloud resources by removing unused subsystems from JBoss EAP XP. For this reason, I commented out the GALLEON_PROVISION_DEFAULT_FAT_SERVER property. To include only the necessary subsystems, I also set the GALLEON_PROVISION_LAYERS property with the names of the subsystems needed to run my application. The jaxrs-server subsystem provides support for JAX-RS and JPA, while the microprofile-platform subsystem includes the MicroProfile capabilities we added in Part 3.

    I also set the property S2I_COPY_SERVER to copy the result of the first build, named weather-app-eap-cloud-ready-build-artifacts in the buildConfig.yaml, into the final runtime image as described in the weather-app-eap-cloud-ready build, which is always set in the buildConfig.yaml file. Without this property, you can't complete this step.

    Create the new runtime image

    Now it’s time to create the ImageStreams and the chained buildConfig to make the runtime image with JBoss EAP XP 2 and the application:

    $ oc create -f k8s/buildConfig.yaml

    Then, start the build of the application on OpenShift:

    $ oc start-build weather-app-eap-cloud-ready-build-artifacts --from-dir=. --wait

    I suggest that you check when the second build finishes with this command:

    $ oc get build weather-app-eap-cloud-ready-1 --watch

    After the status moves from Pending to Complete, you can create the weather application for JBoss EAP XP 2 and configure it:

    $ oc create -f k8s/weather-app-eap-cloud-ready.yaml

    You can then test your application, using the steps I have described in the previous articles, to verify that it is still working.

    Reviewing the outcomes

    Now it’s time to check the return on investment for the operations we've just performed. Figure 2 shows the new container image size.

    The size of the final, optmized image is only 294.6 MB.
    Figure 2: Summary and size information after our upgrade to remove unneeded components.

    Figure 3 shows the new memory footprint.

    The final, optmized image uses only 718.9 MB of memory.
    Figure 3: Memory use after our upgrade to remove unneeded components.

    Consider these outcomes:

    • Container image size: The previous application image, with Jakarta EE and MicroProfile features plus all of JBoss EAP XP and RHEL 8 UBI, takes up 455 MB. The final image, obtained through the optimizations we carried out in this article, is 294 MB, a savings of 35%.
    • Memory footprint: The previous application release, with Jakarta EE and MicroProfile features, plus all of JBoss EAP XP and RHEL 8 UBI, requires 1,000 MB of memory. The final release, obtained through optimization, requires 718 MB of memory, a savings of 28%.

    Conclusion to Part 4

    This series has gone through the steps to modernize a legacy Java EE application using Jakarta EE and Eclipse MicroProfile. The resulting final application includes features and services that are beneficial for microservice applications running in the cloud. By repeating the processes shown in the series, you can break your monolithic Java applications into small and independent modules without needing to heavily change your source code. The resulting runtime environment is:

    • Optimized for the cloud and containers
    • Lightweight, with a flexible architecture
    • More productive for developers
    • Flexible in management, configuration, and administration
    • Oriented to supporting and standardizing microservices development
    • Based entirely on open source tools and standards

    Don’t stop evolving all of your applications! Continuous improvement is the key to the success of your architecture.

    More about modernization: Application modernization patterns with Apache Kafka, Debezium, and Kubernetes.

    Last updated: January 12, 2024

    Related Posts

    • How to make Java programs cloud-ready: An incremental approach using Jakarta EE and MicroProfile

    • Making Java programs cloud-ready, Part 2: Upgrade the legacy Java application to Jakarta EE

    • Making Java programs cloud-ready, Part 3: Integrate MicroProfile services

    • Hello World for JBoss EAP Runtime via CodeReady Studio

    Recent Posts

    • Why some agentic AI developers are moving code from Python to Rust

    • Confidential VMs: The core of confidential containers

    • Benchmarking with GuideLLM in air-gapped OpenShift clusters

    • Run Qwen3-Next on vLLM with Red Hat AI: A step-by-step guide

    • How to implement observability with Python and Llama Stack

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue