Use Java EE JCache with Open Liberty or WebSphere Liberty on an Azure Kubernetes Service (AKS) cluster
This article describes how to use Java EE JCache in a containerized application deployed to AKS.
In this guide, you'll:
- Create the infrastructure to run your Java, Java EE, Jakarta EE, or MicroProfile application on the Open Liberty or WebSphere Liberty runtime.
- Use Java EE JCache backed by Azure Cache for Redis as session cache.
- Build the application Docker image using Open Liberty or WebSphere Liberty container images.
- Deploy the containerized application to an AKS cluster using the Open Liberty Operator.
This article is intended to help you quickly get to deployment. Before going to production, you should explore Tuning Liberty.
If you're interested in providing feedback or working closely on your migration scenarios with the engineering team developing WebSphere on Azure solutions, fill out this short survey on WebSphere migration and include your contact information. The team of program managers, architects, and engineers will promptly get in touch with you to initiate close collaboration.
Prerequisites
- An Azure subscription. If you don't have an Azure subscription, create a free account before you begin.
- Prepare a local machine with Unix-like operating system installed - for example, Ubuntu, macOS, or Windows Subsystem for Linux.
- Install the Azure CLI to run Azure CLI commands.
- Sign in with Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. See Sign into Azure with Azure CLI for other sign-in options.
- When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see Use and manage extensions with the Azure CLI.
- Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
- Install a Java SE implementation version 17 or later - for example, Microsoft build of OpenJDK.
- Install Maven 3.5.0 or higher.
- Install Docker for your OS.
- Ensure that Git is installed.
- Be sure you've been assigned either
Owner
role orContributor
andUser Access Administrator
roles for the subscription. You can verify your assignments by following steps in List role assignments for a user or group.
Create the infrastructure
The steps in this section guide you to create the application infrastructure on Azure. After completing these steps, you'll have an Azure Container Registry, an Azure Kubernetes Service cluster, and an Azure Cache for Redis instance for running the sample application.
Create a resource group
An Azure resource group is a logical group in which Azure resources are deployed and managed.
Create a resource group called java-liberty-project using the az group create command in the eastus location. This resource group is used later for creating the Azure Container Registry (ACR) instance and the AKS cluster.
export RESOURCE_GROUP_NAME=java-liberty-project
az group create --name $RESOURCE_GROUP_NAME --location eastus
Create an ACR instance
Use the az acr create command to create the ACR instance. The following example creates an ACR instance named youruniqueacrname. Make sure youruniqueacrname is unique within Azure.
export REGISTRY_NAME=youruniqueacrname
az acr create \
--resource-group $RESOURCE_GROUP_NAME \
--name $REGISTRY_NAME \
--sku Basic
After a short time, you should see a JSON output that contains:
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"resourceGroup": "java-liberty-project",
Alternatively, you can create an Azure container registry instance by following the steps in Quickstart: Create an Azure container registry using the Azure portal.
Connect to the ACR instance
You'll need to sign in to the ACR instance before you can push an image to it. Run the following commands to verify the connection:
export LOGIN_SERVER=$(az acr show \
--name $REGISTRY_NAME \
--resource-group $RESOURCE_GROUP_NAME \
--query 'loginServer' \
--output tsv)
az acr login \
--name $REGISTRY_NAME \
--resource-group $RESOURCE_GROUP_NAME
Note
The use of username and password credentials to grant access to a container registry is discouraged. If your particular usage requirements suggest credential based access is the best approach, you can obtain the username and password using az acr credential show
and use these values with docker login
.
You should see Login Succeeded
at the end of command output if you've signed into the ACR instance successfully.
If you see a problem signing in to the Azure container registry, see Troubleshoot registry login.
Create an AKS cluster
Use the az aks create command to create an AKS cluster and grant it image pull permission from the ACR instance. The following example creates a cluster named myAKSCluster with one node. This command takes several minutes to complete.
export CLUSTER_NAME=myAKSCluster
az aks create \
--resource-group $RESOURCE_GROUP_NAME \
--name $CLUSTER_NAME \
--node-count 1 \
--generate-ssh-keys \
--enable-managed-identity \
--attach-acr $REGISTRY_NAME
After a few minutes, the command completes and returns JSON-formatted information about the cluster, including the following lines:
"nodeResourceGroup": "MC_java-liberty-project_myAKSCluster_eastus",
"privateFqdn": null,
"provisioningState": "Succeeded",
"resourceGroup": "java-liberty-project",
Connect to the AKS cluster
To manage a Kubernetes cluster, you use kubectl, the Kubernetes command-line client. To install kubectl
locally, use the az aks install-cli command:
az aks install-cli
To configure kubectl
to connect to your Kubernetes cluster, use the az aks get-credentials command. This command downloads credentials and configures the Kubernetes CLI to use them.
az aks get-credentials \
--resource-group $RESOURCE_GROUP_NAME \
--name $CLUSTER_NAME \
--overwrite-existing
To verify the connection to your cluster, use the kubectl get command to return a list of the cluster nodes.
kubectl get nodes
The following example output shows the single node created in the previous steps. Make sure that the status of the node is Ready.
NAME STATUS ROLES AGE VERSION
aks-nodepool1-xxxxxxxx-yyyyyyyyyy Ready agent 76s v1.18.10
Install Open Liberty Operator
After creating and connecting to the cluster, install the Open Liberty Operator by running the following commands.
# Install cert-manager Operator
CERT_MANAGER_VERSION=v1.11.2
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml
# Install Open Liberty Operator
export OPERATOR_VERSION=1.3.3
mkdir -p overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/olo-all-namespaces.yaml -q -P ./overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/cluster-roles.yaml -q -P ./overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/kustomization.yaml -q -P ./overlays/watch-all-namespaces
mkdir base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/kustomization.yaml -q -P ./base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/open-liberty-crd.yaml -q -P ./base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/open-liberty-operator.yaml -q -P ./base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/open-liberty-roles.yaml -q -P ./base
kubectl create namespace open-liberty
kubectl apply --server-side -k overlays/watch-all-namespaces
Create an Azure Cache for Redis instance
Azure Cache for Redis backs the persistence of the HttpSession
for a Java application running within an Open Liberty or WebSphere Liberty server. Follow the steps in this section to create an Azure Cache for Redis instance and note down its connection information. We'll use this information later.
Follow the steps in Quickstart: Use Azure Cache for Redis in Java up to, but not including Understanding the Java sample.
Note
In step 7 of section Create an Azure Cache for Redis, select Access Keys Authentication for the Authentication option on the Advanced pane for this guide. For optimal security, we recommend that you use Microsoft Entra ID with managed identities to authorize requests against your cache, if possible. Authorization by using Microsoft Entra ID and managed identities provides superior security and ease of use over shared access key authorization. For more information about using managed identities with your cache, see Use Microsoft Entra ID for cache authentication.
Copy Host name and Primary access key for your Azure Cache for Redis instance, and then run the following commands to add environment variables:
export REDISCACHEHOSTNAME=<YOUR_HOST_NAME> export REDISCACHEKEY=<YOUR_PRIMARY_ACCESS_KEY>
Build the application
Follow the steps in this section to build and containerize the sample application. These steps use Maven, liberty-maven-plugin
, and az acr build. To learn more about the liberty-maven-plugin
, see Building a web application with Maven.
Check out the application
Use the following commands to clone the sample code for this guide. The sample is in the open-liberty-on-aks repository on GitHub. There are a few samples in the repository. This article uses java-app-jcache.
git clone https://github.com/Azure-Samples/open-liberty-on-aks.git
cd open-liberty-on-aks
git checkout 20240909
cd java-app-jcache
If you see a message about being in "detached HEAD" state, this message is safe to ignore. It just means you have checked out a tag.
The application has the following file structure:
java-app-jcache/
├── pom.xml
└── src
└── main
├── aks
│ └── openlibertyapplication.yaml
├── docker
│ ├── Dockerfile
│ └── Dockerfile-wlp
├── java
├── liberty
│ └── config
│ └── server.xml
├── redisson
│ └── redisson-config.yaml
├── resources
└── webapp
The java, resources, and webapp directories contain the source code of the sample application.
In the aks directory, the deployment file openlibertyapplication.yaml is used to deploy the application image.
In the docker directory, we place two Dockerfiles. Dockerfile is used to build image with Open Liberty and Dockerfile-wlp is used to build image with WebSphere Liberty.
In the liberty/config directory, the server.xml file is used to configure session cache for the Open Liberty and WebSphere Liberty cluster.
In the redisson directory, the redisson-config.yaml file is used to configure the connection of the Azure Cache for Redis instance.
Containerize the application
To deploy and run your Liberty application on the AKS cluster, use the following steps to containerize your application as a Docker image. You can use Open Liberty container images or WebSphere Liberty container images.
Verify the current working directory is java-app-jcache in your local clone.
Run
mvn clean package
to package the application.Run
mvn -Predisson validate
to copy the Redisson configuration file to the specified location. This step inserts the values of the environment variablesREDISCACHEHOSTNAME
andREDISCACHEKEY
into the redisson-config.yaml file, which is referenced by the server.xml file.Run
mvn liberty:dev
to test the application. If the test is successful, you should seeThe defaultServer server is ready to run a smarter planet.
in the command output. You should see output similar to the following if the Redis connection is successful.[INFO] [err] [Default Executor-thread-5] INFO org.redisson.Version - Redisson 3.23.4 [INFO] [err] [redisson-netty-2-7] INFO org.redisson.connection.pool.MasterPubSubConnectionPool - 1 connections initialized for redacted.redis.cache.windows.net/20.25.90.239:6380 [INFO] [err] [redisson-netty-2-20] INFO org.redisson.connection.pool.MasterConnectionPool - 24 connections initialized for redacted.redis.cache.windows.net/20.25.90.239:6380
You can visit
http://localhost:9080/
to see the application running, but the proof of Redis working is the output listed in the preceding step.Use Ctrl+C to stop the application.
Use the following commands to retrieve values for properties
artifactId
andversion
defined in the pom.xml file.export artifactId=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.artifactId}' --non-recursive exec:exec) export version=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
Run
cd target
to change directory to the build of the sample.Run one of the following commands to build the application image and push it to the ACR instance.
Use the following command to build with an Open Liberty base image if you prefer to use Open Liberty as a lightweight open source Java™ runtime:
# Build and tag application image. This causes the ACR instance to pull the necessary Open Liberty base images. az acr build -t ${artifactId}:${version} -r $REGISTRY_NAME --resource-group $RESOURCE_GROUP_NAME .
Use the following command to build with a WebSphere Liberty base image if you prefer to use a commercial version of Open Liberty:
# Build and tag application image. This causes the ACR instance to pull the necessary WebSphere Liberty base images. az acr build -t ${artifactId}:${version} -r $REGISTRY_NAME --resource-group $RESOURCE_GROUP_NAME --file=Dockerfile-wlp .
Deploy the application
Follow the steps in this section to deploy the containerized sample application on the AKS cluster.
Verify the current working directory is java-app-jcache/target in your local clone.
Use the following commands to create a secret with Redisson configuration information. With this secret, the application can connect to the created Azure Cache for Redis instance.
export REDISSON_CONFIG_SECRET_NAME=redisson-config-secret kubectl create secret generic ${REDISSON_CONFIG_SECRET_NAME} --from-file=$(pwd)/liberty/wlp/usr/servers/defaultServer/redisson-config.yaml
Use the following commands to deploy your Liberty application with three replicas to the AKS cluster. The command output is also shown inline.
# Set number of application replicas export REPLICAS=3 # Create OpenLibertyApplication "javaee-cafe-jcache-cluster" envsubst < openlibertyapplication.yaml | kubectl create -f - openlibertyapplication.openliberty.io/javaee-cafe-jcache-cluster created # Check if OpenLibertyApplication instance is created kubectl get openlibertyapplication ${artifactId}-cluster NAME IMAGE EXPOSED RECONCILED AGE javaee-cafe-jcache-cluster youruniqueacrname.azurecr.io/javaee-cafe-jcache:1.0.0 True 59s # Check if deployment created by Operator is ready kubectl get deployment ${artifactId}-cluster --watch NAME READY UP-TO-DATE AVAILABLE AGE javaee-cafe-jcache-cluster 0/3 3 0 20s
Wait until you see
3/3
under theREADY
column and3
under theAVAILABLE
column, then use Ctrl+C to stop thekubectl
watch process.
Test the application
When the application runs, a Kubernetes load balancer service exposes the application front end to the internet. This process can take a while to complete.
To monitor progress, use the kubectl get service command with the --watch
argument.
kubectl get service ${artifactId}-cluster --watch
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
javaee-cafe-jcache-cluster LoadBalancer 10.0.50.29 20.84.16.169 80:31732/TCP 68s
Once the EXTERNAL-IP address changes from pending to an actual public IP address, use Ctrl+C to stop the kubectl
watch process.
Open a web browser to the external IP address of your service (20.84.16.169
for the above example) to see the application home page. If the page isn't loaded correctly, that's because the app is starting. You can wait for a while and refresh the page later. You should see the pod name of your application replicas displayed at the top-left of the page (javaee-cafe-jcache-cluster-77d54bccd4-5xnzx
for this case).
In the form New coffee in session, set values for fields Name and Price, and then select Submit. After a few seconds, you'll see Submit count: 1 displayed at the left bottom of the page.
To demonstrate that the session cache is persisted across all replicas of the application, run the following command to delete the current replica with pod name javaee-cafe-jcache-cluster-<pod id from your running app>
:
kubectl delete pod javaee-cafe-jcache-cluster-77d54bccd4-5xnzx
pod "javaee-cafe-jcache-cluster-77d54bccd4-5xnzx" deleted
Then, refresh the application home page. You'll see the same data displayed in the section New coffee in session but a different pod name displayed at the top-left of the page.
Finally, use the following steps to demonstrate that the session data is persisted in the Azure Cache for Redis instance. You can issue commands to your Azure Cache for Redis instance using the Redis Console.
Find your Azure Cache for Redis instance from the Azure portal.
Select Console to open Redis console.
Run the following commands to view the session data:
scan 0 count 1000 match '*' hgetall "com.ibm.ws.session.attr.default_host%2F"
Search for cafe.model.entity.Coffee[id=1, name=Coffee 3, price=30.0] from the web page, which is the coffee you created and persisted in the Azure Cache for Redis instance.
Clean up resources
To avoid Azure charges, you should clean up unnecessary resources. When the cluster is no longer needed, use the az group delete command to remove the resource group, container service, container registry, and all related resources.
az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait
To delete the Azure Cache for Redis instance, find its resource group name and run the following command:
az group delete --name <AZURE_CACHE_FOR_REDIS_RESOURCE_GROUP_NAME> --yes --no-wait
Next steps
You can learn more from references used in this guide:
- Configuring Liberty session persistence with JCache
- JCache support of Redisson
- Open Liberty Server Configuration
To explore options to run WebSphere products on Azure, see What are solutions to run the WebSphere family of products on Azure?