Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      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
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java 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

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • 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 3: Integrate MicroProfile services

June 30, 2021
Mauro Vocale
Related topics:
JavaMicroservices
Related products:
Developer ToolsRed Hat JBoss Enterprise Application PlatformRed Hat OpenShift LocalRed Hat OpenShiftRed Hat OpenShift Container Platform

Share:

    The first article in this series presented a legacy Java application that we want to upgrade to a microservices architecture. In the second article, we upgraded the Java EE environment to Jakarta EE. Now, we will add a powerful collection of microservices functionality, writing very little code of our own. Specifically, we will:

    • Extend the Red Hat JBoss Enterprise Application Platform (JBoss EAP) 7.3 capabilities with JBoss EAP XP 2.
    • Introduce MicroProfile specifications that implement the patterns needed in a distributed architecture.
    • Install several popular monitoring tools:
      • Jaeger: A tracing tool for distributed applications.
      • Prometheus: An analytical tool for application and network metrics.
      • Grafana: A tool for visually displaying metrics captured by Prometheus and Jaeger.

    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

    About Eclipse MicroProfile

    MicroProfile, a project maintained by the Eclipse Foundation, provides highly sophisticated tools that Java programmers can insert into their applications with minimal effort. In this article, we will implement and test the following components:

    • MicroProfile Health: Routinely checks whether instances of your service are accepting requests.
    • MicroProfile Metrics: Collects measurements that help with provisioning and planning.
    • MicroProfile Opentracing: Records the flow of requests between services for troubleshooting.
    • MicroProfile OpenAPI: Allows the creation of OpenAPI v3 documents for RESTful services based on the OpenAPI standard.
    • MicroProfile Config: Standardizes the configuration of parameters for your application.

    Installation and configuration

    This article uses the same GitHub repository as the previous articles in the series. We are working in Red Hat OpenShift.

    Start your upgrade by switching to the git tag that contains the source code used to implement the MicroProfile adoption:

    $ git checkout tags/Microprofile_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

    Next, we'll install Jaeger, Prometheus, and Grafana in an OpenShift environment. We'll also create the cloud-ready weather application.

    Install Jaeger

    Import the Jaeger image from the catalog:

    $ oc import-image distributed-tracing/jaeger-all-in-one-rhel8 --from=registry.redhat.io/distributed-tracing/jaeger-all-in-one-rhel8 --confirm

    Create the Jaeger application:

    $ oc new-app -i jaeger-all-in-one-rhel8

    Expose the route in order to make the Jaeger application available outside of OpenShift:

    $ oc expose svc jaeger-all-in-one-rhel8 --port=16686

    Install the weather application

    Now, we'll create the cloud-ready weather application. First, import the image for JBoss EAP XP 2.0 for OpenJDK 11:

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

    Create the build for the cloud-ready weather app that will be deployed on JBoss EAP XP 2.0:

    $ oc new-build eap-xp2-openjdk11-openshift-rhel8 --binary=true --name=weather-app-eap-cloud-ready

    Change to the directory for the weather-app-eap-cloud-ready project. Start the build of the application on OpenShift:

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

    Create the weather application for JBoss EAP XP 2.0 and configure it:

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

    Install Prometheus

    Next, we create the Prometheus environment that will collect the values provided by the MicroProfile Metrics specification, which we'll integrate shortly. Start by importing the Prometheus image from the catalog:

    $ oc import-image openshift4/ose-prometheus --from=registry.redhat.io/openshift4/ose-prometheus --confirm

    Create the config map with the Prometheus configurations:

    $ oc create configmap prometheus --from-file=k8s/prometheus.yml

    Create the Prometheus application:

    $ oc create -f k8s/ose-prometheus.yaml

    Install Grafana

    Finally, we create the Grafana environment used to collect the values provided by the MicroProfile Metrics specification. Import the Grafana image from the catalog:

    $ oc import-image openshift4/ose-grafana --from=registry.redhat.io/openshift4/ose-grafana --confirm

    Create the config map with the Grafana configurations:

    $ oc create configmap grafana --from-file=k8s/datasource-prometheus.yaml --from-file=k8s/grafana-dashboard.yaml --from-file=k8s/jboss_eap_grafana_dashboard.json

    Create the Grafana application:

    $ oc create -f k8s/ose-grafana.yaml

    Configure JBoss EAP XP

    This section shows how easy it is to implement the MicroProfile specifications using JBoss EAP XP and OpenShift. We'll use the JBoss EAP XP container image at registry.redhat.io/jboss-eap-7/eap-xp2-openjdk11-openshift-rhel8.

    To move from JBoss EAP to JBoss EAP XP, you need to update the Maven pom.xml file as follows:

    ...
    <properties>
        ...
        <version.microprofile.bom>2.0.0.GA</version.microprofile.bom>
        ...
    </properties>
    ...
    <dependencyManagement>
        ...
        <!-- importing the microprofile BOM adds MicroProfile specs -->
        <dependency>
            <groupId>org.jboss.bom</groupId>
               <artifactId>jboss-eap-xp-microprofile</artifactId>
               <version>${version.microprofile.bom}</version>
               <type>pom</type>
               <scope>import</scope>
         </dependency>
         ...
    </dependencyManagement>
    ...

    You can use the following command to get the route to the application, then use it to test the application:

    $ oc get route weather-app-eap-cloud-ready --template='{{ .spec.host }}'

    Copy the output of this command into your browser. You should be able to connect to the weather application and check the weather in the selected cities.

    Activate the MicroProfile services

    As stated at the beginning of this article, I have chosen five tools from the MicroProfile project for our application. We'll install and use each of them in the following sections.

    MicroProfile Health

    The MicroProfile Health specification defines a runtime mechanism for validating the availability and status of a MicroProfile implementation. To implement MicroProfile Health, set this dependency in the Maven pom.xml file:

    <!-- Import the MicroProfile Health API, we use provided scope as the API is included in JBoss EAP XP -->
    <dependency>
        <groupId>org.eclipse.microprofile.health</groupId>
        <artifactId>microprofile-health-api</artifactId>
        <scope>provided</scope>
    </dependency>

    Readiness checks

    Next, we'll create two classes to implement health checks for the application. Start with a readiness check (com.redhat.example.weather.DatabaseHealthCheck), which verifies that the application is ready to service the customers’ requests:

    import org.eclipse.microprofile.health.HealthCheck;
    import org.eclipse.microprofile.health.HealthCheckResponse;
    import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
    import org.eclipse.microprofile.health.Readiness;
    
    @Readiness
    @ApplicationScoped
    public class DatabaseHealthCheck implements HealthCheck {
    
        @Override
        public HealthCheckResponse call() {
    
            HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named("Database connection health check");
            String hostName = (System.getenv("WEATHER_POSTGRESQL_SERVICE_HOST") != null) ? System.getenv("WEATHER_POSTGRESQL_SERVICE_HOST") : "localhost";
            Integer port = (System.getenv("WEATHER_POSTGRESQL_SERVICE_PORT") != null) ? Integer.parseInt(System.getenv("WEATHER_POSTGRESQL_SERVICE_PORT")) : 5432;
    
            try {
                pingServer(hostName, port);
                responseBuilder.up();
            } catch (IOException e) {
    
                responseBuilder.down()
                        .withData("error", e.getMessage());
            }
    
            return responseBuilder.build();
        }
    
        private void pingServer(String dbhost, int port) throws IOException {
                Socket socket = new Socket(dbhost, port);
                socket.close();
        }
    
    }

    Liveness checks

    The second class (com.redhat.example.weather.DatabaseConnectionHealthCheck) implements a liveness check, which verifies whether the application is still able to serve the requests:

    import org.eclipse.microprofile.health.HealthCheck;
    import org.eclipse.microprofile.health.HealthCheckResponse;
    import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
    import org.eclipse.microprofile.health.Liveness;
    
    @Liveness
    @ApplicationScoped
    public class DatabaseConnectionHealthCheck implements HealthCheck {
    
        @Resource
        private DataSource datasource;
    
        @Override
        public HealthCheckResponse call() {
    
            HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named("Database sql connection health check");
            try (var connection = datasource.getConnection()) {
                boolean isValid = connection.isValid(5);
    
                DatabaseMetaData metaData = connection.getMetaData();
    
                responseBuilder = responseBuilder
                            .withData("databaseProductName", metaData.getDatabaseProductName())
                            .withData("databaseProductVersion", metaData.getDatabaseProductVersion())
                            .withData("driverName", metaData.getDriverName())
                            .withData("driverVersion", metaData.getDriverVersion())
                            .withData("isValid", isValid);
    
                return responseBuilder.state(isValid).build();
    
    
            } catch(SQLException  e) {
                responseBuilder = responseBuilder
                       .withData("exceptionMessage", e.getMessage());
                return responseBuilder.down().build();
            }
        }
        
    }

    Note that we've used the @Liveness and @Readiness annotations on the class to enable the health checks.

    Viewing the application's health status

    To view the health status, click on the health route in the OpenShift web console or get the value using the following command:

    $ oc get route health --template='{{ .spec.host }}'

    Append the path health to the command output. You can also verify the status of your application using the following paths after your health route:

    • /health/live: To check whether the application is up and running.
    • /health/ready: To check whether the application is ready to serve requests.

    You should obtain results like those in Figure 1 (click to enlarge).

    The health check shows that the database is up and running.
    Figure 1: Results of a health check.

    Automatic restarts

    With health checks in place, you can instruct OpenShift and Kubernetes to automatically observe your application and restart the pod when a failure is reported by the checks implemented through the MicroProfile Health specification. I set up automatic restarts using the DeploymentConfig file (k8s/weather-app-eap-cloud-ready.yaml under the src folder), where I defined the liveness and readiness probes and set the application path that implements the checks:

    apiVersion: apps.openshift.io/v1
    kind: DeploymentConfig
    ...
    spec:
      replicas: 1
      ...
        spec:
          containers:
            - resources: {}
              readinessProbe:
                httpGet:
                  path: /health/ready
                  port: 9990
                  scheme: HTTP
                initialDelaySeconds: 25
                timeoutSeconds: 1
                periodSeconds: 10
                successThreshold: 1
                failureThreshold: 3
              name: weather-app-eap-cloud-ready
              livenessProbe:
                httpGet:
                  path: /health/live
                  port: 9990
                  scheme: HTTP
                initialDelaySeconds: 25
                timeoutSeconds: 1
                periodSeconds: 10
                successThreshold: 1
                failureThreshold: 3

    MicroProfile Metrics

    MicroProfile Metrics allows applications to log metrics during execution, which you can use to monitor essential system parameters. You can implement this service without touching your code. Just add the following dependencies to your Maven pom.xml file:

    <!-- Import the MicroProfile Metrics API, we use provided scope as the API is included in JBoss EAP XP -->
    <dependency>
        <groupId>org.eclipse.microprofile.metrics</groupId>
        <artifactId>microprofile-metrics-api</artifactId>
        <scope>provided</scope>
    </dependency>

    To add more information that helps to test the metrics capabilities, I updated my com.redhat.example.weather.WeatherService class as follows:

    ...
    import org.eclipse.microprofile.metrics.MetricUnits;
    import org.eclipse.microprofile.metrics.annotation.Counted;
    import org.eclipse.microprofile.metrics.annotation.Metered;
    import org.eclipse.microprofile.metrics.annotation.Timed;
    
    @RequestScoped
    @Path("weather")
    public class WeatherService {
        ...
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        @Counted(name = "requestCount", description = "How many weather forecast have been performed.")
        @Timed(name = "checksTimer", absolute = true, description = "A measure of how long it takes to perform the getList method.", unit = MetricUnits.MILLISECONDS)
        @Metered(name = "getList", absolute = true)
        public Country getList() {
            return em.find(Country.class,selectedCountry.getCode());
        }
    }

    Accessing metrics

    To get access to the metrics being generated, click on the metric route in the OpenShift web console or get the value using the following command:

    $ oc get route metric --template='{{ .spec.host }}'

    Then, append the path metrics. The MicroProfile Metrics specification defines three different scopes of metrics that you can check by appending the following paths after your metric route:

    • /metrics/base: Metrics that all MicroProfile vendors must provide.
    • /metrics/vendor: Vendor-specific metrics.
    • /metrics/application: Application-specific metrics.

    The metrics look something like what's shown in Figure 2.

    The raw metrics collected by MicroProfile Metrics.
    Figure 2: Raw metrics collected by MicroProfile Metrics.

    Visualizing metrics with Prometheus and Grafana

    To provide a more comprehensible display of the metrics exposed by your application in OpenShift, you can integrate them into Prometheus and Grafana.

    Prometheus is an open source, community-driven project that collects metrics from targets by scraping the metrics HTTP endpoints. We installed and configured it in the previous steps using the prometheus.yml and ose-prometheus.yaml files under the k8s directory. Click on the ose-prometheus route in the OpenShift web console or get the value using the following command:

    $ oc get route ose-prometheus --template='{{ .spec.host }}'

    Visiting the URL opens the Prometheus web console. Enter application_getList_total there and click on the Execute button. This will show you the number of invocations of the getList method used by the application. You should see something like Figure 3.

    Prometheus provides structure to the raw metrics.
    Figure 3: Display of a metric in Prometheus.

    Grafana is an open source tool that composes dashboards with statistics from Prometheus to aid in the observability of applications, systems, and networks. I installed and configured Grafana in the previous steps using the datasource-prometheus.yaml, grafana-dashboard.yaml, jboss_eap_grafana_dashboard.json, and ose-grafana.yaml files. These files create the Grafana application, connect it with Prometheus, and pre-load a dashboard with some metrics. To view the dashboard, click on the ose-grafana route in the OpenShift web console or get the value using the following command:

    $ oc get route ose-grafana --template='{{ .spec.host }}'

    Visting the URL opens the Grafana web console. Enter admin in the username and password fields and skip the page offering to set the new password. Then click on Dashboards—>Manage in the left-side menu. This displays a pre-loaded Red Hat JBoss 7.3 Cloud Ready dashboard that shows the following metrics:

    • Application getList method execution time
    • JBoss Cloud Ready total requests
    • JVM Memory heap
    • Active data source connections

    The display looks like Figure 4.

    Grafana shows metrics collected by MicroProfile Metrics and filtered through Prometheus.
    Figure 4: Dashboard shown by Grafana.

    MicroProfile OpenTracing

    Distributed tracing allows you to trace the flow of a request across service boundaries. This is particularly important in a microservices environment, where a request typically flows through multiple services. Here again, standards make it easy to enable the service, and I didn’t need to touch my code to obtain it. To make my application traceable, I only added the following dependency to the Maven pom.xml file:

    <!-- Import the MicroProfile OpenTracing API, we use provided scope as the API is included in the server -->
    <dependency>
        <groupId>org.eclipse.microprofile.opentracing</groupId>
        <artifactId>microprofile-opentracing-api</artifactId>
        <scope>provided</scope>
    </dependency>

    Visualizing distributed tracing with Jaeger

    To add detailed information about the request, I integrated Jaeger into OpenShift. Jaeger is an open source, end-to-end distributed tracing tool that helps monitor and troubleshoot transactions in complex distributed systems. We installed and configured the tool in the previous steps using the Jaeger image from the Red Hat Container Catalog (registry.redhat.io/distributed-tracing/jaeger-all-in-one-rhel8). To use the service, click on the jaeger-all-in-one-rhel8 route in the OpenShift web console or get the value using the following command:

    $ oc get route jaeger-all-in-one-rhel8 --template='{{ .spec.host }}'

    Visting the URL opens the Jaeger web console. Select weather-app-eap-cloud-ready from the Operation drop-down list box, then GET:com.redhat.example.weather.WeatherService.getList. Click the Find Traces button to visualize the results of the trace. You should see something like Figure 5.

    Jaeger console enables to visualize the performance of the application
    Figure 5: Traces produced by OpenTracing and Jaeger.

    MicroProfile OpenAPI

    The MicroProfile OpenAPI specification provides a set of Java interfaces and programming models that allow Java developers to natively produce OpenAPI v3 documents from Java API for RESTful Web Services (JAX-RS) applications. To implement that specification and obtain documentation for my APIs, I didn’t touch my code. I only added the following dependency to the Maven pom.xml file:

    <!-- Import the MicroProfile OpenAPI, we use provided scope as the API is included in the server -->
    <dependency>
        <groupId>org.eclipse.microprofile.openapi</groupId>
        <artifactId>microprofile-openapi-api</artifactId>
        <scope>provided</scope>
    </dependency>

    Viewing the OpenAPI structure of your APIs

    To use the service, click on the weather-app-eap-cloud-ready route in the OpenShift web console or get the value using the following command:

    $ oc get route weather-app-eap-cloud-ready --template='{{ .spec.host }}'

    Then, append the path openapi to download the YAML file that contains the OpenAPI structure of your APIs. You should see something like Figure 6. If you want to visualize the data in JSON format, append the path openapi?format=JSON to the weather-app-eap-cloud-ready route.

    MicroProfile OpenAPI lets you view documentation of your APIs through a web interface.
    Figure 6: Documentation of an API.

    Visualize and test API data

    I extended the specification with a user interface that can help you visualize and test the API's data. As usual, you need only to add the following dependency to the Maven pom.xml file:

    <dependency>
        <groupId>org.microprofile-ext.openapi-ext</groupId>
        <artifactId>openapi-ui</artifactId>
        <version>1.1.4</version>
        <scope>runtime</scope>
    </dependency>

    The dependency is not directly related to MicroProfile specifications, so it’s not provided by the Maven bill of materials (BOM) and JBoss EAP XP. To test the service, append the path api/openapi-ui to the weather-app-eap-cloud-ready route. The resulting URL (shown in Figure 7) displays the Swagger UI. You can use it to test my APIs, which you will probably agree could use improvement.

    The Swagger UI lets you navigate through the schema of your APIs.
    Figure 7: An API viewed through the Swagger UI.

    MicroProfile Config

    MicroProfile Config defines a simple and flexible system for application configuration. To demonstrate how easy it is to use, I configured the OpenAPI UI described in the previous section using the values provided by the Config specification. As usual, I didn’t touch my source code, but only added the following dependency to the Maven pom.xml file:

    <!-- Import the MicroProfile Config API, we use provided scope as the API is included in the server -->
    <dependency>
        <groupId>org.eclipse.microprofile.config</groupId>
        <artifactId>microprofile-config-api</artifactId>
        <scope>provided</scope>
    </dependency>

    Then, under the src/main/resources/META-INF directory, I created a microprofile-config.properties file that contains the values I didn’t want to put statically into my source code:

    openapi.ui.copyrightBy=Mauro Vocale
    openapi.ui.title=Weather Application OpenAPI specifications
    openapi.ui.swaggerHeaderVisibility=visible
    openapi.ui.exploreFormVisibility=visible

    You can see the first value, for example, in the footer section of the OpenAPI UI.

    Conclusion to Part 3

    In this article, we've enriched our "traditional" Java application with a set of features that prepare it for being used in distributed scenarios such as OpenShift, on-premises, or in a cloud environment. We only needed to make minimal updates to the source code. The final result was obtained through the declaration of the dependencies that are provided, at runtime, from JBoss EAP XP and OpenShift.

    The final container image (JBoss EAP XP plus the application) is similar to the one that we built with Jakarta EE and JBoss EAP 7.3 in the previous article. You can get summary information about the application from the OpenShift web console, as shown in Figure 8.

    Information about the container image for the application.
    Figure 8: Weather app in the OpenShift web console.

    Figure 9 shows that our memory utilization is higher than that of the traditional application, as I mentioned in the conclusion to Part 2.

    Image size of the Jakarta EE and MicroProfile application.
    Figure 9: Summary and size information after upgrading to use MicroProfile.

    Figure 10 shows increased memory use, as well. We'll fix this issue in the next and final article in this series, where we will optimize the image's runtime environment.

    The original version of our application uses 811.2 MB of memory whereareas the upgraded version uses 1,007 MB
    Figure 10: Comparing memory footprints between the original and upgraded application.

    Next up: Optimize the runtime environment.

    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

    • Generate automated Grafana metrics dashboards for MicroProfile apps

    • Using OpenTracing with Jaeger to collect Application Metrics in Kubernetes

    • You (probably) need liveness and readiness probes

    Recent Posts

    • More Essential AI tutorials for Node.js Developers

    • How to run a fraud detection AI model on RHEL CVMs

    • How we use software provenance at Red Hat

    • Alternatives to creating bootc images from scratch

    • How to update OpenStack Services on OpenShift

    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

    Red Hat legal and privacy links

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

    Report a website issue