DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Knowing and Valuing Apache Kafka’s ISR (In-Sync Replicas)
  • Database Integration Tests With Spring Boot and Testcontainers
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • Send Email Using Spring Boot (SMTP Integration)

Trending

  • Knowing and Valuing Apache Kafka’s ISR (In-Sync Replicas)
  • Database Integration Tests With Spring Boot and Testcontainers
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • Send Email Using Spring Boot (SMTP Integration)
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Tutorial: Deploying Java EE Apps on Azure (Part 3)

Tutorial: Deploying Java EE Apps on Azure (Part 3)

In this final blog in a series of posts that explore different options for running Java EE workloads, we will run it on a Kubernetes cluster.

Abhishek Gupta user avatar by
Abhishek Gupta
CORE ·
Aug. 10, 20 · Tutorial
Like (4)
Save
Tweet
Share
7.26K Views

Join the DZone community and get the full member experience.

Join For Free

 This is the final blog in a series of posts that explore different options for running Java EE workloads on Azure. In this part, we will run the Java EE app on a Kubernetes cluster in Azure.

The example used in the blog post is a simple three-tier application that uses Java EE 8 specifications such as JAX-RS, EJB, CDI, JPA, JSF, Bean Validation. We will use the Payara Server to deploy the application and use PostgreSQL as the relational database.

During the tutorial, we will cover:

  • Postgres setup on Azure
  • Setup and configure Azure Kubernetes Service cluster and Azure Container Registry
  • Dockerize the Java EE app
  • Deploy the application to Kubernetes
  • Explore its functionality

Except for minor changes, the application used in this tutorial has been adapted from this project by Reza Rahman

Pre-Requisites

You will need a Microsoft Azure account and the Azure CLI to work through the tutorial.

If you don't have a Microsoft Azure account, go ahead and sign up for a free one!. The Azure CLI is a cross-platform command-line experience for managing Azure resources - please install it using these instructions.

First Things first...

Set your Azure Subscription ID using the Azure CLI which will be used for this tutorial.

To set your Azure subscription ID

export AZURE_SUBSCRIPTION_ID=[to be filled]
az account set --subscription $AZURE_SUBSCRIPTION_ID

Create a resource group that will contain all the services (resources) which you will create as a part of this tutorial. A resource group is like a logical container that holds related resources for an Azure solution. The resource group includes those resources that you want to manage as a group.

To create a resource group

export AZURE_RESOURCE_GROUP_NAME=[to be filled]
export AZURE_LOCATION=[to be filled]
az group create --name $AZURE_RESOURCE_GROUP_NAME --location $AZURE_LOCATION

Install Postgres on Azure

Azure Database for PostgreSQL is a relational database service based on the open-source Postgres database engine. It's a fully managed database-as-a-service offering which is available in two deployment options, as a single server, and as a Hyperscale (Citus) cluster

We will be using the single server option for this tutorial.

We will use the az postgres server create the command to create a Postgres server instance on Azure. First, set up some of the server properties such as the name, admin user, etc.

Java
 




xxxxxxxxxx
1


 
1
export AZURE_POSTGRES_SERVER_NAME=[to be filled]
2
export AZURE_POSTGRES_ADMIN_USER=[to be filled]
3
export AZURE_POSTGRES_ADMIN_PASSWORD=[to be filled]
4
export SKU=B_Gen5_1
5
export STORAGE=5120



For storage and SKU options, please refer to the documentation.

And, then invoke the command to initiate the database instance creation:

Java
 




x


 
1
az postgres server create --resource-group $AZURE_RESOURCE_GROUP_NAME --name $AZURE_POSTGRES_SERVER_NAME  --location $AZURE_LOCATION --admin-user $AZURE_POSTGRES_ADMIN_USER --admin-password $AZURE_POSTGRES_ADMIN_PASSWORD --storage-size $STORAGE --sku-name $SKU



The provisioning process will take a few minutes.

To check the details of the Postgres database instance you just provisioned, invoke az postgres server show command.

Java
 




xxxxxxxxxx
1


 
1
az postgres server show --resource-group $AZURE_RESOURCE_GROUP_NAME --name $AZURE_POSTGRES_SERVER_NAME



You should get a JSON response. Please note down the value for the fullyQualifiedDomainName attribute as you will be using this to connect to the Postgres instance later.

It should be of the format: [AZURE_POSTGRES_DB_NAME].postgres.database.azure.com

Azure Kubernetes Service (AKS) Cluster Setup

You need the az aks create command to stand up a Kubernetes cluster on Azure

To keep things simple, the below command creates a single node cluster. Feel free to change the specification as per your requirements.

Java
 




xxxxxxxxxx
1


 
1
export AKS_CLUSTER_NAME=[to be filled]
2

          
3
az aks create --resource-group $AZURE_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --node-count 1 --node-vm-size Standard_B2s --node-osdisk-size 30 --generate-ssh-keys



Get the AKS cluster credentials using az aks get-credentials - as a result, kubectl will now point to your new cluster. You can confirm the same

Java
 




xxxxxxxxxx
1


 
1
az aks get-credentials --resource-group $AZURE_RESOURCE_GROUP --name $AKS_CLUSTER_NAME
2
kubectl get nodes


If you are interested in learning Kubernetes and Containers using Azure, simply create a free account and get going! A good starting point is to use the quickstarts, tutorials and code samples in the documentation to familiarize yourself with the service. I also highly recommend checking out the 50 days Kubernetes Learning Path. Advanced users might want to refer to Kubernetes best practices or the watch some of the videos for demos, top features and technical sessions.

Allow AKS to Access the Postgres Database

The Postgres database is not accessible to external services by default. We can use the az postgres server firewall-rule create command to create a firewall rule to explicitly allow Azure services to access the Postgres instance. This will allow the JavaEE application deployed in AKS to communicate with Postgres.

Java
 




xxxxxxxxxx
1


 
1
export FIREWALL_RULE_NAME=AllowJavaEECafeAppOnAKS
2

          
3
az postgres server firewall-rule create --resource-group $AZURE_RESOURCE_GROUP_NAME --server-name $AZURE_POSTGRES_SERVER_NAME --start-ip-address=0.0.0.0 --end-ip-address=0.0.0.0 --name $FIREWALL_RULE_NAME


Note: This setting allows network connections from all IPs within the Azure network. For production use, try to configure the most restrictive firewall rules possible

Setup Azure Container Registry

Azure Container Registry is a managed, private Docker registry service to store and manage your private Docker container images (it based on the open-source Docker Registry 2.0). You can use Azure container registries with your existing container development and deployment pipelines or use Azure Container Registry Tasks to build container images in Azure. You can either build on-demand or fully automate builds with triggers such as source code commits and base image updates.

Let's create a registry to store the Docker image for the JavaEE application. We will use the az acr create command

Java
 




xxxxxxxxxx
1


 
1
export ACR_NAME=[to-be-filled]
2
az acr create --resource-group $AZURE_RESOURCE_GROUP_NAME --name $ACR_NAME --sku Basic --admin-enabled true


We are using the Basic SKU. Valid value is: Basic, Classic, Premium, Standard.

You can log in to the registry once it's created and check the login server

az acr login --name $ACR_NAME
az acr show --name $ACR_NAME --query loginServer --output table

You will use the ACR login server name soon. Its value follows the format: [ACR_NAME].azurecr.io

Configure Azure Container Registry to Work With Azure Kubernetes Service

To access images stored in Azure Container Registry, you must grant the Azure Kubernetes Service service principal the correct rights to pull images from ACR.

Get the appId of the service principal which is associated with your AKS cluster.

Java
 




xxxxxxxxxx
1


 
1
AKS_SERVICE_PRINCIPAL_APPID=$(az aks show --name $AKS_CLUSTER_NAME --resource-group $AZURE_RESOURCE_GROUP --query servicePrincipalProfile.clientId -o tsv)



Find the resource ID for Azure Container Registry.

Java
 




xxxxxxxxxx
1


 
1
ACR_RESOURCE_ID=$(az acr show --resource-group $AZURE_RESOURCE_GROUP --name $ACR_NAME --query "id" --output tsv)



Grant acrpull permissions to AKS service principal.

Java
 




xxxxxxxxxx
1


 
1
az role assignment create --assignee $AKS_SERVICE_PRINCIPAL_APPID --scope $ACR_RESOURCE_ID --role acrpull



Our AKS cluster along with ACR is ready to use!

Setup and Prepare Application Image

Clone the git repository

Java
 




xxxxxxxxxx
1


 
1
git clone https://github.com/abhirockzz/javaee-on-azure-kubernetes
2
cd javaee-on-azure-kubernetes



You need to enter the Postgres connectivity information to the <url> attribute of the <data-source section in web.xml.

You can find the web.xml file under javaee-on-azure-iaas/src/main/webapp/WEB-INF

The format is as follows:

XML
 




xxxxxxxxxx
1


 
1
jdbc:postgresql://[POSTGRES_FQDN]:5432/postgres?user=[AZURE_POSTGRES_ADMIN_USER]@[AZURE_POSTGRES_SERVER_NAME]&amp;password=[AZURE_POSTGRES_ADMIN_PASSWORD]&amp;sslmode=require



Here are the list placeholders which form a part of the JDBC URL:

  • POSTGRES_FQDN with value of fullyQualifiedDomainName
  • AZURE_POSTGRES_ADMIN_USER with the admin user name used to provision PG
  • AZURE_POSTGRES_SERVER_NAME with server name used to provision PG
  • AZURE_POSTGRES_ADMIN_PASSWORD with admin password used to provision PG

Set the required values.

Java
 




xxxxxxxxxx
1


 
1
    export POSTGRES_FQDN=[to be filled]
2
    export AZURE_POSTGRES_ADMIN_USER=[to be filled]
3
    export AZURE_POSTGRES_SERVER_NAME=[to be filled]
4
    export AZURE_POSTGRES_ADMIN_PASSWORD=[to be filled]



Simply use these commands to replace them.

Java
 




xxxxxxxxxx
1


 
1
    export FILE_NAME=javaee-on-azure-iaas/src/main/webapp/WEB-INF/web.xml
2

          
3
    sed -i 's/POSTGRES_FQDN/'"$POSTGRES_FQDN"'/g' $FILE_NAME
4
    sed -i 's/AZURE_POSTGRES_SERVER_NAME/'"$AZURE_POSTGRES_SERVER_NAME"'/g' $FILE_NAME
5
    sed -i 's/AZURE_POSTGRES_ADMIN_USER/'"$AZURE_POSTGRES_ADMIN_USER"'/g' $FILE_NAME
6
    sed -i 's/AZURE_POSTGRES_ADMIN_PASSWORD/'"$AZURE_POSTGRES_ADMIN_PASSWORD"'/g' $FILE_NAME



Here is an e.g. of what the <data-source> section will look like:

Java
 




xxxxxxxxxx
1


 
1
    <data-source>
2
        <name>java:global/JavaEECafeDB</name>
3
        <class-name>org.postgresql.ds.PGPoolingDataSource</class-name>
4
        <url>jdbc:postgresql://foobar-pg.postgres.database.azure.com:5432/postgres?user=foobar@foobar-pg&amp;password=foobarbaz&amp;sslmode=require</url>
5
    </data-source>



The application is now configured. Let's build it!

mvn clean install

You should have the WAR file available. To confirm

ls -lrt target | grep javaee-cafe.war

Build and Push the Image to Azure Container Registry

Our application artifact (WAR file) is ready. We can now build the Docker image and push it out to Azure Container Registry. Here is a quick look at the Dockerfile used for this

Java
 




xxxxxxxxxx
1


 
1
FROM payara/server-full
2
COPY target/javaee-cafe.war $DEPLOY_DIR
3
RUN wget https://jdbc.postgresql.org/download/postgresql-42.2.8.jar
4
RUN cp /opt/payara/postgresql-42.2.8.jar ${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}/lib && rm /opt/payara/postgresql-42.2.8.jar
5
EXPOSE 8080



It builds on top of the base image for payara/server-full, copies the WAR file to a folder from where it can be automatically detected and deployed, downloads the Postgres JDBC driver and places it in the appropriate location for the Payara application server. That's it!

Dockerfile
 




xxxxxxxxxx
1


 
1
export DOCKER_IMAGE=javaee-cafe
2
docker build -t $DOCKER_IMAGE .
3
docker tag $DOCKER_IMAGE $ACR_NAME.azurecr.io/$DOCKER_IMAGE



To push the image

docker push $ACR_NAME.azurecr.io/$DOCKER_IMAGE

For e.g. if the ACR_NAME (name of the Azure Container Registry) is javaeecafe-acr, the resulting Docker image will be javaeecafe-acr.azurecr.io/javaee-cafe

Use az acr repository list command to check the image.

az acr repository list --name $ACR_NAME --output table

Deploy the Application to Azure Kubernetes Service

Before deploying the application, please update the Kubernetes manifest file javaee-cafe.yaml with the name of the Docker image. To be specific, update the spec.containers.image with the name of the Azure Container Registry which you specified above

It is assumed that the name of the Docker image is javaee-azure, if not please update that as well.

Java
 




xxxxxxxxxx
1


 
1
spec:
2
  containers:
3
    - name: javaee-cafe
4
      image: <replace_me>.azurecr.io/javaee-azure



For e.g.

Java
 




xxxxxxxxxx
1


 
1
spec:
2
  containers:
3
    - name: javaee-cafe
4
      image: javaeecafe-acr.azurecr.io/javaee-azure



To deploy the application:

kubectl apply -f javaee-cafe.yml

This should spin up a Pod. Wait for it to transition to Running state.

kubectl get pods -l=app=javaee-cafe -w

Once the Pod is Running, confirm that the application has been deployed successfully

kubectl logs -f <replace_with_pod_name>

The application deployment should be in progress and finally, you should see the logs similar to the one below (with the Successfully autodeployed message)

Java
 




xxxxxxxxxx
1


 
1
[AutoDeploy] Successfully autodeployed : /foo/bar/payara5/glassfish/domains/domain1/autodeploy/javaee-cafe.war.]]



Explore the Application

We use a LoadBalancer Service type to ensure that our Java EE app is accessible outside of the cluster. The creation of a Kubernetes LoadBalancer Service in Azure does exactly what it's supposed to i.e. provision an Azure Load Balancer behind the scenes.

Java
 




xxxxxxxxxx
1
11


 
1
apiVersion: v1
2
kind: Service
3
metadata:
4
  name: javaee-cafe
5
spec:
6
  type: LoadBalancer
7
  ports:
8
    - port: 80
9
      targetPort: 8080
10
  selector:
11
    app: javaee-cafe



We can get the load balancer IP by using.

kubectl get svc javaee-cafe

where javaee-cafe is the name of the Service

The value of the EXTERNAL-IP is the load balancer IP and will be used to access the application

Access the JSF Front-End

Use your browser to access http://[LOAD_BALANCER_IP]/javaee-cafe. You can use the UI to create, delete, and see coffees.

Use the REST API

The application also exposes a REST API for creating, deleting, and listing coffees.

export JAVAEE_AKS_REST=http://[LOAD_BALANCER_IP]/javaee-cafe/rest/coffees

e.g.

export JAVAEE_AKS_REST=http://23.101.24.139/javaee-cafe/rest/coffees

Create coffees

Java
 




xxxxxxxxxx
1


 
1
curl -X POST $JAVAEE_AKS_REST -d '{"name":"cappuccino","price":"10"}' -H "Content-Type: application/json"
2
curl -X POST $JAVAEE_AKS_REST -d '{"name":"caffe-latte","price":"15"}' -H "Content-Type: application/json"



Get all coffees.

curl -H "Accept: application/json" $JAVAEE_AKS_REST

You should see a JSON response listing both the coffee options you just added

Get a coffee by ID.

curl -H "Accept: application/json" $JAVAEE_AKS_REST/1

Delete a coffee by ID.

curl -X DELETE $JAVAEE_AKS_REST/1
curl -H "Accept: application/json" $JAVAEE_AKS_REST

Notice that cappuccino is now deleted.

Scale

Right now, we have one instance of our application since we had set spec.replicas to 1 in the Kubernetes manifest. We can scale our application horizontally and Kubernetes will ensure that it spins up and maintains the required number of Pods. To add another instance

kubectl scale deployment javaee-cafe --replicas=2

To confirm that another Pod has been spun up:

kubectl get pods -l=app=javaee-cafe -w

You can continue accessing the application in the same manner and now the requests will be transparently load-balanced amongst your app instances by the Load Balancer.

Clean up Resources

Once you are done exploring the application, you can delete the resources. Since we used a resource group, it's as easy as executing a single command.

Please be aware that this will delete all the resources in the group which includes the ones you created as part of the tutorial as well as any other service instances you might have if you used an already existing resource group

az group delete --name $AZURE_RESOURCE_GROUP_NAME

Summary

You learned how to leverage Docker containers to package your Java EE application and deploy it on a Kubernetes cluster in Azure along with a managed database offering for long term persistence.

That brings us to the end of this series exploring some of the common ways of deploying Java EE workloads to Azure. I hope you found it useful!

azure Java (programming language) Docker (software) Java EE Kubernetes application app

Opinions expressed by DZone contributors are their own.

Trending

  • Knowing and Valuing Apache Kafka’s ISR (In-Sync Replicas)
  • Database Integration Tests With Spring Boot and Testcontainers
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • Send Email Using Spring Boot (SMTP Integration)

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: