Lab Objective
In this lab, you will deploy a Java Spring Boot application on OpenShift using the OpenShift web console.
You will deploy two components:
- A MySQL database.
- A Java Spring PetClinic application.
The Java application will connect to the MySQL database using OpenShift internal service discovery.
This lab is a modern replacement for the older โDeploy a Java application on Kubernetesโ lab. The original lab used Developer Sandbox and an ephemeral MySQL template. This replacement is updated for OpenShift Local and uses current OpenShift resources such as Deployment, Service, Secret, PersistentVolumeClaim, BuildConfig, ImageStream, and Route.
What You Will Learn
You will learn how to:
- Start OpenShift Local.
- Log in to the OpenShift web console.
- Create a new OpenShift project.
- Deploy MySQL using the web console.
- Store database credentials in a Secret.
- Store MySQL data on a PersistentVolumeClaim.
- Expose MySQL internally using a Service.
- Import a Java Spring Boot application from Git.
- Build the Java application using OpenShift Source-to-Image.
- Use the Java builder image.
- Configure the Java application to connect to MySQL.
- Deploy the application using a Kubernetes Deployment.
- Expose the Java application externally using a Route.
- Validate the application from the browser.
- Validate database connectivity from CLI.
- Troubleshoot common build, deployment, and database issues.
- Clean up the lab environment.
Lab Architecture
GitHub Repository
|
v
OpenShift Source-to-Image Build
|
v
Application Image
|
v
Spring PetClinic Deployment
|
v
Spring PetClinic Pod
|
v
Spring PetClinic Service
|
v
Spring PetClinic Route
|
v
Browser
Spring PetClinic Pod
|
| jdbc:mysql://mysql:3306/petclinic
v
MySQL Service
|
v
MySQL Pod
|
v
PersistentVolumeClaim
Code language: JavaScript (javascript)
Resources Created in This Lab
| Resource | Name | Purpose |
|---|---|---|
| Project | lab13-java-mysql | Isolated namespace for the lab |
| Secret | mysql-secret | Stores MySQL credentials |
| PersistentVolumeClaim | mysql-data | Stores MySQL data |
| Deployment | mysql | Runs the MySQL database |
| Service | mysql | Provides internal DNS name for MySQL |
| BuildConfig | spring-petclinic | Defines how OpenShift builds the Java app |
| Build | spring-petclinic-1 | One execution of the app build |
| ImageStream | spring-petclinic | Tracks the built app image |
| Deployment | spring-petclinic | Runs the Java app |
| Service | spring-petclinic | Provides internal access to the Java app |
| Route | spring-petclinic | Provides browser access to the Java app |
Important Concept: Kubernetes vs OpenShift
The original article title says Kubernetes, but this lab uses OpenShift features.
Plain Kubernetes does not provide these OpenShift-specific features by default:
Source-to-Image
BuildConfig
ImageStream
Route
Developer perspective
OpenShift web console import flow
Code language: JavaScript (javascript)
So the technically correct title for this lab is:
Deploy a Java Spring Boot Application with MySQL on OpenShift
Code language: JavaScript (javascript)
OpenShift runs Kubernetes underneath, but this lab specifically teaches the OpenShift developer workflow.
Important Concept: Why MySQL Is Not Exposed with a Route
A MySQL database should normally not be exposed publicly.
The Java application connects to MySQL internally using:
mysql:3306
Code language: CSS (css)
This works because mysql is the name of the OpenShift Service.
The Java application will use this JDBC URL:
jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
The Java app gets an external Route because it is a web application.
The MySQL database does not get a Route because it is an internal database service.
Important Concept: Why We Use Deployment Instead of DeploymentConfig
Older OpenShift labs often used DeploymentConfig.
This lab uses:
Deployment
Deployment is the standard Kubernetes workload resource and is the preferred resource type for modern beginner labs.
When the web console asks for the resource type, select:
Deployment
Do not select:
DeploymentConfig
Part 1: Prerequisites
Required Tools
You need:
- OpenShift Local installed.
- The
crccommand available. - The
occommand available. - Browser access to the OpenShift web console.
- Internet access from OpenShift Local to GitHub and container registries.
- A valid Red Hat pull secret configured for OpenShift Local.
Recommended Local Machine Resources
For this lab, use at least:
| Resource | Recommended |
|---|---|
| CPU | 4 cores or more |
| Memory | 12 GB or more |
| Disk | 35 GB or more |
Java builds can be slow on small laptops. More memory will make this lab smoother.
Part 2: Start OpenShift Local
Open a terminal.
Check the CRC version:
crc version
Set the OpenShift preset:
crc config set preset openshift
Code language: JavaScript (javascript)
Run setup:
crc setup
Start OpenShift Local:
crc start
The cluster may take several minutes to start.
After the cluster starts, view the login credentials:
crc console --credentials
Code language: JavaScript (javascript)
Open the web console:
crc console
Code language: JavaScript (javascript)
Part 3: Configure the oc CLI
Run:
crc oc-env
On Linux or macOS, run:
eval $(crc oc-env)
Code language: JavaScript (javascript)
On Windows PowerShell, use the PowerShell command printed by crc oc-env.
Log in as the developer user:
oc login -u developer https://api.crc.testing:6443
Code language: JavaScript (javascript)
Use the password from:
crc console --credentials
Code language: JavaScript (javascript)
Verify the login:
oc whoami
Expected output:
developer
Check the node:
oc get nodes
Code language: JavaScript (javascript)
Expected output should show one OpenShift Local node in Ready status.
Part 4: Create a New Project
You can create the project from the web console or from CLI.
Option A: Create Project from Web Console
- Open the OpenShift web console.
- Log in as
developer. - Switch to the Developer perspective.
- Click the Project dropdown.
- Click Create Project.
- Enter the project name:
lab13-java-mysql
- Optional display name:
Lab 13 Java MySQL
- Click Create.
Option B: Create Project from CLI
Run:
oc new-project lab13-java-mysql
Code language: JavaScript (javascript)
Verify:
oc project
Expected output:
Using project "lab13-java-mysql"
Code language: JavaScript (javascript)
Part 5: Deploy MySQL from the Web Console
In this section, you will create MySQL using Import YAML in the OpenShift web console.
This creates:
- Secret
- PersistentVolumeClaim
- MySQL Deployment
- MySQL Service
Using YAML here is more reliable for a classroom lab than depending on an old ephemeral database template.
Open Import YAML
In the OpenShift web console:
- Make sure you are in project:
lab13-java-mysql
- Switch to Developer perspective.
- Click +Add.
- Click Import YAML.
- Paste the YAML below.
- Click Create.
YAML: MySQL Database
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/part-of: spring-petclinic-demo
type: Opaque
stringData:
MYSQL_USER: petclinic
MYSQL_PASSWORD: petclinic
MYSQL_PASS: petclinic
MYSQL_ROOT_PASSWORD: petclinic-root
MYSQL_DATABASE: petclinic
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/part-of: spring-petclinic-demo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
app.kubernetes.io/name: mysql
app.kubernetes.io/part-of: spring-petclinic-demo
spec:
replicas: 1
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
app.kubernetes.io/name: mysql
app.kubernetes.io/part-of: spring-petclinic-demo
spec:
terminationGracePeriodSeconds: 30
containers:
- name: mysql
image: registry.redhat.io/rhel9/mysql-80:latest
imagePullPolicy: IfNotPresent
ports:
- name: mysql
containerPort: 3306
protocol: TCP
env:
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_DATABASE
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 3
livenessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 60
periodSeconds: 20
timeoutSeconds: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql/data
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
---
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
app.kubernetes.io/name: mysql
app.kubernetes.io/part-of: spring-petclinic-demo
spec:
type: ClusterIP
selector:
app: mysql
ports:
- name: mysql
protocol: TCP
port: 3306
targetPort: 3306
Code language: JavaScript (javascript)
Part 6: Understand the MySQL YAML
Secret
kind: Secret
metadata:
name: mysql-secret
The Secret stores the database credentials.
Important values:
MYSQL_USER=petclinic
MYSQL_PASSWORD=petclinic
MYSQL_DATABASE=petclinic
MYSQL_ROOT_PASSWORD=petclinic-root
For this lab, the values are simple so students can understand the workflow.
In real production environments, do not commit plain database passwords to Git.
PersistentVolumeClaim
kind: PersistentVolumeClaim
metadata:
name: mysql-data
The PVC stores the MySQL data files.
The MySQL data directory is mounted here:
/var/lib/mysql/data
Code language: JavaScript (javascript)
This means the database data can survive a MySQL pod restart.
Deployment
kind: Deployment
metadata:
name: mysql
The Deployment runs one MySQL pod.
The strategy is:
strategy:
type: Recreate
This is suitable for a single-instance database in a beginner lab because OpenShift stops the old pod before starting a new one.
Service
kind: Service
metadata:
name: mysql
The Service gives the database a stable internal DNS name.
Other pods in the same project can connect to MySQL using:
mysql:3306
Code language: CSS (css)
This is why the Java application will use:
jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
Part 7: Verify MySQL from the Web Console
In the web console:
- Go to Developer perspective.
- Open Topology.
- Confirm that you see a workload named:
mysql
- Click the
mysqlworkload. - Open the Resources tab.
- Confirm that the pod is running.
- Open the Logs tab.
The MySQL pod should start successfully.
Part 8: Verify MySQL from CLI
Set the project:
oc project lab13-java-mysql
Check resources:
oc get deploy,pod,svc,pvc,secret
Code language: JavaScript (javascript)
Expected resources:
deployment.apps/mysql
pod/mysql-xxxxx
service/mysql
persistentvolumeclaim/mysql-data
secret/mysql-secret
Check rollout:
oc rollout status deployment/mysql
Expected output:
deployment "mysql" successfully rolled out
Code language: JavaScript (javascript)
Check the PVC:
oc get pvc mysql-data
Code language: JavaScript (javascript)
Expected status:
Bound
Check MySQL logs:
oc logs deployment/mysql
Part 9: Test MySQL Login
Find the MySQL pod:
MYSQL_POD=$(oc get pod -l app=mysql -o jsonpath='{.items[0].metadata.name}')
echo "$MYSQL_POD"
Code language: PHP (php)
Open a shell inside the MySQL pod:
oc rsh "$MYSQL_POD"
Code language: JavaScript (javascript)
Inside the pod, connect to MySQL:
mysql -u petclinic -ppetclinic petclinic
Run:
SHOW DATABASES;
You should see:
petclinic
Exit MySQL:
exit
Code language: PHP (php)
Exit the pod shell:
exit
Code language: PHP (php)
Part 10: Deploy the Java Spring PetClinic Application from Git
Now you will deploy the Java application from source code.
The application source repository is:
https://github.com/redhat-developer-demos/spring-petclinic
Code language: JavaScript (javascript)
This repository contains a Spring Boot PetClinic application prepared for OpenShift Source-to-Image.
Open Import from Git
In the OpenShift web console:
- Make sure you are in project:
lab13-java-mysql
- Switch to Developer perspective.
- Click +Add.
- Click Import from Git or From Git.
The exact label depends on your OpenShift console version.
Enter Git Repository URL
In the Git repository URL field, enter:
https://github.com/redhat-developer-demos/spring-petclinic
Code language: JavaScript (javascript)
OpenShift will inspect the repository.
You may see an import warning because the repository contains older metadata such as a devfile or Dockerfile. This is expected for this lab.
The correct action is to manually choose the Builder Image strategy.
Part 11: Select the Correct Import Strategy
Click:
Edit Import Strategy
Select:
Builder Image
For the builder image, select:
Java
For the Java version, select:
OpenJDK 11
If OpenJDK 11 is not shown in your environment, use the available Java builder image recommended by your instructor.
For this specific Spring PetClinic sample, Java 11 is the safest choice because the sample repository is older and its Dockerfile also references OpenJDK 11.
Part 12: Configure Application Details
Scroll to the application details section.
Use the following values:
| Field | Value |
|---|---|
| Application name | spring-petclinic-demo |
| Name | spring-petclinic |
| Resource type | Deployment |
Set:
Application name: spring-petclinic-demo
Name: spring-petclinic
Resource type: Deployment
Make sure the selected resource type is:
Deployment
Do not select:
DeploymentConfig
Part 13: Create a Route for the Java Application
Open Advanced options.
Enable:
Create a route to the application
This is needed because Spring PetClinic is a web application.
The Route will allow you to open the application in your browser.
Part 14: Add Environment Variables
In Advanced options, open the Environment variables section.
Add the following environment variables:
| Name | Value |
|---|---|
SPRING_PROFILES_ACTIVE | mysql |
MYSQL_URL | jdbc:mysql://mysql:3306/petclinic |
The final values should be:
SPRING_PROFILES_ACTIVE=mysql
MYSQL_URL=jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
These values tell Spring PetClinic to:
- Use the MySQL Spring profile.
- Connect to MySQL using the OpenShift Service named
mysql. - Use the
petclinicdatabase.
The sample application defaults to this database username and password:
Username: petclinic
Password: petclinic
Code language: HTTP (http)
These values match the MySQL Secret created earlier.
Optional: Add Explicit MySQL User and Password
If your instructor wants students to make credentials explicit, add these two environment variables also:
| Name | Value |
|---|---|
MYSQL_USER | petclinic |
MYSQL_PASS | petclinic |
So the complete environment variable list becomes:
SPRING_PROFILES_ACTIVE=mysql
MYSQL_URL=jdbc:mysql://mysql:3306/petclinic
MYSQL_USER=petclinic
MYSQL_PASS=petclinic
Code language: JavaScript (javascript)
For the beginner lab, either approach works because the application defaults already match the lab database values.
Part 15: Create the Java Application
Review the form.
You should have:
| Setting | Expected Value |
|---|---|
| Project | lab13-java-mysql |
| Git Repository | https://github.com/redhat-developer-demos/spring-petclinic |
| Import Strategy | Builder Image |
| Builder Image | Java |
| Java Version | OpenJDK 11 if available |
| Application name | spring-petclinic-demo |
| Name | spring-petclinic |
| Resource type | Deployment |
| Create route | Enabled |
SPRING_PROFILES_ACTIVE | mysql |
MYSQL_URL | jdbc:mysql://mysql:3306/petclinic |
Click:
Create
OpenShift will now start a Source-to-Image build.
Part 16: Watch the Java Build
After clicking Create, OpenShift redirects you to the Topology view.
You should see:
spring-petclinic
The build may take several minutes because Maven dependencies must be downloaded.
To view build progress from the web console:
- Click the
spring-petclinicworkload. - Open the Resources tab.
- Find the build.
- Open the build details.
- Click Logs.
Typical build stages:
Cloning Git repository
Running Maven build
Creating application artifact
Assembling S2I image
Pushing image to OpenShift internal registry
Starting deployment rollout
Part 17: Watch the Build from CLI
From your terminal, run:
oc project lab13-java-mysql
List BuildConfigs:
oc get bc
Code language: JavaScript (javascript)
Expected output:
spring-petclinic
List builds:
oc get builds
Code language: JavaScript (javascript)
Expected output:
spring-petclinic-1
Follow build logs:
oc logs -f bc/spring-petclinic
Wait until the build completes.
Expected build status:
oc get builds
Code language: JavaScript (javascript)
Expected result:
spring-petclinic-1 Complete
Part 18: Verify the Application Deployment
Check the Deployment:
oc get deployment spring-petclinic
Code language: JavaScript (javascript)
Expected output:
NAME READY UP-TO-DATE AVAILABLE
spring-petclinic 1/1 1 1
Check rollout status:
oc rollout status deployment/spring-petclinic
Expected output:
deployment "spring-petclinic" successfully rolled out
Code language: JavaScript (javascript)
Check pods:
oc get pods
Code language: JavaScript (javascript)
Expected output should include:
mysql-xxxxx 1/1 Running
spring-petclinic-xxxxx 1/1 Running
Check Java app logs:
oc logs deployment/spring-petclinic
You should see Spring Boot startup logs.
Part 19: Verify Service and Route
Check services:
oc get svc
Code language: JavaScript (javascript)
Expected services:
mysql
spring-petclinic
Check routes:
oc get route
Code language: JavaScript (javascript)
Expected route:
spring-petclinic
Store the app URL:
APP_URL="http://$(oc get route spring-petclinic -o jsonpath='{.spec.host}')"
echo "$APP_URL"
Code language: PHP (php)
Test the route:
curl -I "$APP_URL"
Code language: JavaScript (javascript)
Expected result should include an HTTP response.
Example:
HTTP/1.1 200 OK
Code language: HTTP (http)
Open the URL in your browser.
You should see the Spring PetClinic application.
Part 20: Test the Application in Browser
In the Spring PetClinic UI:
- Open the application route.
- Click Find owners.
- Click Find Owner without entering anything.
- You should see the list of sample owners.
- Click Add Owner.
- Add a new owner.
- Save.
- Search again and confirm the new owner appears.
This confirms:
- The Java application is running.
- The app can connect to MySQL.
- The app can write data to MySQL.
- The app can read data from MySQL.
Part 21: Verify Data in MySQL
Find the MySQL pod:
MYSQL_POD=$(oc get pod -l app=mysql -o jsonpath='{.items[0].metadata.name}')
echo "$MYSQL_POD"
Code language: PHP (php)
Run MySQL command directly:
oc exec -it "$MYSQL_POD" -- mysql -u petclinic -ppetclinic petclinic
Code language: JavaScript (javascript)
Inside MySQL, run:
SHOW TABLES;
Expected output should include tables such as:
owners
pets
types
vets
visits
specialties
vet_specialties
Check owners:
SELECT id, first_name, last_name, city FROM owners LIMIT 10;
Exit MySQL:
exit
Code language: PHP (php)
Part 22: Prove MySQL Persistence
In this section, you will restart the MySQL pod and confirm that data is still present.
Scale MySQL down:
oc scale deployment/mysql --replicas=0
Check pods:
oc get pods
Code language: JavaScript (javascript)
Scale MySQL back up:
oc scale deployment/mysql --replicas=1
Wait for rollout:
oc rollout status deployment/mysql
Restart the Java app so it reconnects cleanly:
oc rollout restart deployment/spring-petclinic
oc rollout status deployment/spring-petclinic
Open the application again in your browser.
Check whether the owner data is still present.
If the data is still available, the PVC is working.
Part 23: Understand the Complete Flow
When you completed this lab, OpenShift performed the following:
1. Created a MySQL Secret.
2. Created a MySQL PVC.
3. Started a MySQL Deployment.
4. Created a MySQL Service named mysql.
5. Imported Java source code from GitHub.
6. Used a Java builder image.
7. Created a BuildConfig.
8. Started a Build.
9. Built a runnable image using S2I.
10. Stored the image in an ImageStream.
11. Started a Spring PetClinic Deployment.
12. Created a Spring PetClinic Service.
13. Created a Spring PetClinic Route.
14. Exposed the app in the browser.
15. Connected the Java app to MySQL using internal service discovery.
Code language: JavaScript (javascript)
Part 24: Student Validation Checklist
Students should verify:
| Check | Command | Expected Result |
|---|---|---|
| Current project | oc project | lab13-java-mysql |
| MySQL deployment | oc get deploy mysql | 1/1 ready |
| MySQL service | oc get svc mysql | Service exists |
| MySQL PVC | oc get pvc mysql-data | Bound |
| Java BuildConfig | oc get bc spring-petclinic | Exists |
| Java build | oc get builds | Build Complete |
| ImageStream | oc get is spring-petclinic | Exists |
| Java deployment | oc get deploy spring-petclinic | 1/1 ready |
| Java service | oc get svc spring-petclinic | Service exists |
| Java route | oc get route spring-petclinic | Route exists |
| Browser test | Open route | PetClinic UI opens |
| Database test | Query owners table | Data visible |
Part 25: Full CLI Validation Script
Run this script after completing the lab:
oc project lab13-java-mysql
echo "Checking core resources..."
oc get deploy,pod,svc,route,pvc,secret
echo "Checking MySQL rollout..."
oc rollout status deployment/mysql
echo "Checking Spring PetClinic build resources..."
oc get bc
oc get builds
oc get imagestream
echo "Checking Spring PetClinic rollout..."
oc rollout status deployment/spring-petclinic
echo "Checking application route..."
APP_URL="http://$(oc get route spring-petclinic -o jsonpath='{.spec.host}')"
echo "$APP_URL"
curl -I "$APP_URL"
echo "Checking MySQL pod..."
MYSQL_POD=$(oc get pod -l app=mysql -o jsonpath='{.items[0].metadata.name}')
echo "$MYSQL_POD"
echo "Checking MySQL tables..."
oc exec "$MYSQL_POD" -- mysql -u petclinic -ppetclinic petclinic -e "SHOW TABLES;"
echo "Checking owners table..."
oc exec "$MYSQL_POD" -- mysql -u petclinic -ppetclinic petclinic -e "SELECT id, first_name, last_name FROM owners LIMIT 5;"
Code language: PHP (php)
Expected result:
- MySQL Deployment is ready.
- MySQL PVC is Bound.
- Java build is Complete.
- Java Deployment is ready.
- Route exists.
- Browser or
curlcan reach the app. - MySQL contains PetClinic tables.
- Owners table returns rows.
Part 26: Optional CLI-Only Equivalent
The main lab uses the web console.
For instructor testing, the same Java application can be created from CLI if the Java builder image stream exists in the cluster.
First, create the project:
oc new-project lab13-java-mysql-cli
Code language: JavaScript (javascript)
Apply the MySQL YAML from this lab.
Then create the Java application from Git:
oc new-app java:11~https://github.com/redhat-developer-demos/spring-petclinic --name=spring-petclinic \
-e SPRING_PROFILES_ACTIVE=mysql \
-e MYSQL_URL=jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
Expose it:
oc expose svc/spring-petclinic
Watch build logs:
oc logs -f bc/spring-petclinic
Check rollout:
oc rollout status deployment/spring-petclinic
This CLI section is optional and should be used mainly by instructors.
Part 27: Troubleshooting
Problem 1: MySQL Pod Shows ImagePullBackOff
Symptom
ImagePullBackOff
ErrImagePull
Check
oc get pods
oc describe pod -l app=mysql
Code language: JavaScript (javascript)
Possible Causes
- Red Hat pull secret is missing or invalid.
- The machine is connected to VPN and cannot reach the registry.
- Internet access is blocked.
- Registry access is temporarily unavailable.
Fix
Check CRC status:
crc status
Check pod events:
oc get events --sort-by=.lastTimestamp
Code language: JavaScript (javascript)
If registry access is the issue, ask the instructor to verify the OpenShift Local pull secret and registry access.
Problem 2: MySQL PVC Is Pending
Symptom
oc get pvc mysql-data
Code language: JavaScript (javascript)
Shows:
Pending
Check
oc describe pvc mysql-data
oc get storageclass
Code language: JavaScript (javascript)
Possible Causes
- No default StorageClass.
- OpenShift Local storage is not ready.
- Cluster is still starting.
Fix
Wait a short time and check again:
oc get pvc mysql-data
Code language: JavaScript (javascript)
If it remains Pending, ask the instructor to verify OpenShift Local storage.
Problem 3: Import from Git Shows โImport Is Not Possibleโ
Symptom
The web console shows an import error or warning after entering:
https://github.com/redhat-developer-demos/spring-petclinic
Code language: JavaScript (javascript)
Explanation
This can happen because the repository contains multiple possible build hints, such as a Dockerfile or devfile.
This is expected for this lab.
Fix
Click:
Edit Import Strategy
Then select:
Builder Image
Choose:
Java
Then continue.
Problem 4: Java Build Fails
Check Build Logs
oc logs -f bc/spring-petclinic
Check build status:
oc get builds
Code language: JavaScript (javascript)
Describe the failed build:
oc describe build spring-petclinic-1
Possible Causes
- Maven dependency download failed.
- Network/VPN issue.
- Wrong Java builder image.
- OpenShift Local does not have enough memory.
- GitHub access is blocked.
- The repository import strategy was not changed to Builder Image.
Fix
Use the Java Builder Image strategy.
Prefer OpenJDK 11 for this sample if available.
Try the build again:
oc start-build spring-petclinic
Follow logs:
oc logs -f bc/spring-petclinic
Problem 5: Java Pod Is CrashLoopBackOff
Check
oc get pods
oc logs deployment/spring-petclinic
Code language: JavaScript (javascript)
Common Cause
The application cannot connect to MySQL.
Check whether MySQL is running:
oc get deploy mysql
oc get svc mysql
oc get pods -l app=mysql
Code language: JavaScript (javascript)
Check whether the Java app has the correct environment variables:
oc set env deployment/spring-petclinic --list
Code language: JavaScript (javascript)
Required values:
SPRING_PROFILES_ACTIVE=mysql
MYSQL_URL=jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
If missing, add them:
oc set env deployment/spring-petclinic SPRING_PROFILES_ACTIVE=mysql MYSQL_URL=jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
Restart the app:
oc rollout restart deployment/spring-petclinic
oc rollout status deployment/spring-petclinic
Problem 6: Application Opens but Data Is Missing
Possible Causes
- App started before MySQL was ready.
- App is using H2 instead of MySQL.
SPRING_PROFILES_ACTIVE=mysqlis missing.MYSQL_URLis incorrect.- Database schema was not initialized.
Check Environment
oc set env deployment/spring-petclinic --list
Code language: JavaScript (javascript)
Check logs:
oc logs deployment/spring-petclinic
Restart the application:
oc rollout restart deployment/spring-petclinic
oc rollout status deployment/spring-petclinic
Then check MySQL tables again:
MYSQL_POD=$(oc get pod -l app=mysql -o jsonpath='{.items[0].metadata.name}')
oc exec "$MYSQL_POD" -- mysql -u petclinic -ppetclinic petclinic -e "SHOW TABLES;"
Code language: PHP (php)
Problem 7: Route Does Not Open
Check Route
oc get route spring-petclinic
Code language: JavaScript (javascript)
If no route exists, create one:
oc expose svc/spring-petclinic
Check service:
oc get svc spring-petclinic
Code language: JavaScript (javascript)
Check endpoints:
oc get endpoints spring-petclinic
Code language: JavaScript (javascript)
If endpoints are empty, the Service is not pointing to a running pod.
Check labels:
oc get pods --show-labels
oc describe svc spring-petclinic
Code language: JavaScript (javascript)
Problem 8: BuildConfig Not Found
Symptom
oc get bc spring-petclinic
Code language: JavaScript (javascript)
Returns NotFound.
Possible Causes
- You are in the wrong project.
- The app was not created from Git.
- The name is different.
- The import failed.
Fix
Check current project:
oc project
Switch project:
oc project lab13-java-mysql
List all resources:
oc get all
Code language: JavaScript (javascript)
List BuildConfigs:
oc get bc
Code language: JavaScript (javascript)
Part 28: Cleanup
To remove all lab resources, delete the project.
Cleanup from Web Console
- Switch to the Administrator perspective.
- Go to Home > Projects.
- Select:
lab13-java-mysql
- Click Delete Project.
- Confirm deletion.
Cleanup from CLI
Run:
oc delete project lab13-java-mysql
Code language: JavaScript (javascript)
Verify:
oc get project lab13-java-mysql
Code language: JavaScript (javascript)
Expected result:
Error from server (NotFound): projects.project.openshift.io "lab13-java-mysql" not found
Code language: JavaScript (javascript)
Part 29: Lab Summary
In this lab, you deployed a complete Java and database application on OpenShift.
You created:
| Resource | Purpose |
|---|---|
| Secret | Stored MySQL credentials |
| PersistentVolumeClaim | Stored MySQL data |
| MySQL Deployment | Ran the database |
| MySQL Service | Provided internal database access |
| BuildConfig | Defined the Java source build |
| Build | Built the Java app image |
| ImageStream | Tracked the built image |
| Java Deployment | Ran Spring PetClinic |
| Java Service | Provided internal app access |
| Route | Exposed the app to the browser |
You verified that:
- MySQL runs inside OpenShift.
- MySQL has persistent storage.
- Spring PetClinic builds from Git source code.
- OpenShift S2I creates a runnable application image.
- The Java app connects to MySQL using the internal service name
mysql. - The app is available in the browser through an OpenShift Route.
- Data can be written to and read from MySQL.
Part 30: Review Questions
Question 1
What is the purpose of Source-to-Image?
Answer
Source-to-Image builds a runnable container image by combining application source code with a builder image.
Question 2
What is the purpose of BuildConfig?
Answer
BuildConfig defines how OpenShift builds the application, including the Git repository, build strategy, builder image, triggers, and output image.
Question 3
What is the purpose of ImageStream?
Answer
ImageStream tracks the image built by OpenShift and allows the Deployment to consume that image.
Question 4
Why does MySQL not have a Route?
Answer
MySQL is an internal database service. It should normally be accessed only by applications inside the cluster through a Service.
Question 5
What is the internal hostname for MySQL?
Answer
mysql
Question 6
What JDBC URL does Spring PetClinic use?
Answer
jdbc:mysql://mysql:3306/petclinic
Code language: JavaScript (javascript)
Question 7
Which environment variable tells Spring Boot to use MySQL?
Answer
SPRING_PROFILES_ACTIVE=mysql
Question 8
Which OpenShift resource exposes Spring PetClinic to the browser?
Answer
Route.
Question 9
Which OpenShift resource stores MySQL data?
Answer
PersistentVolumeClaim.
Question 10
Which command shows the Java build logs?
Answer
oc logs -f bc/spring-petclinic
Part 31: Instructor Notes
This lab is designed as a modern replacement for the older Java PetClinic lab.
The original lab used:
- Developer Sandbox.
- MySQL Ephemeral template.
- Simple direct environment variables.
- Minimal CLI validation.
This replacement uses:
- OpenShift Local.
- MySQL Deployment.
- Secret for credentials.
- PVC for storage.
- Service for internal database access.
- S2I Java build from Git.
- Deployment instead of DeploymentConfig.
- Route for browser access.
- CLI validation.
- Troubleshooting.
For production-grade Java/database workloads, students should later learn:
- Database Operators.
- Managed database services.
- Backup and restore.
- Secret rotation.
- TLS database connections.
- Readiness and liveness probes based on real commands.
- Resource tuning.
- Horizontal Pod Autoscaler for stateless app tier.
- NetworkPolicy.
- GitOps-based deployment.
- CI/CD with OpenShift Pipelines.
- Image vulnerability scanning.
Part 32: Instructor Pre-Validation Checklist
Before giving this lab to students, run:
crc status
oc whoami
oc get nodes
oc get storageclass
Code language: JavaScript (javascript)
Create a test project:
oc new-project lab13-validation
Code language: JavaScript (javascript)
Apply the MySQL YAML from this lab.
Validate MySQL:
oc rollout status deployment/mysql
oc get pvc mysql-data
MYSQL_POD=$(oc get pod -l app=mysql -o jsonpath='{.items[0].metadata.name}')
oc exec "$MYSQL_POD" -- mysql -u petclinic -ppetclinic petclinic -e "SHOW DATABASES;"
Code language: PHP (php)
Then validate the Java build through the web console or CLI.
Clean up:
oc delete project lab13-validation
Code language: JavaScript (javascript)
If MySQL starts, the Java build completes, and the route opens successfully, the lab is ready for students.
Final Outcome
You have successfully deployed a Java Spring Boot application with MySQL on OpenShift.
You now understand this complete OpenShift workflow:
MySQL Secret
-> MySQL PVC
-> MySQL Deployment
-> MySQL Service
-> Java Source Code from Git
-> S2I Build
-> BuildConfig
-> ImageStream
-> Java Deployment
-> Java Service
-> Java Route
-> Browser
Code language: JavaScript (javascript)
This is a very important real-world pattern because many enterprise applications need both an application tier and a database tier, and OpenShift provides the tools to build, deploy, expose, and validate that workflow.
Iโm a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I have worked at Cotocus. I share tech blog at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow , and SEO strategies at Wizbrand.
Do you want to learn Quantum Computing?
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at WIZBRAND
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services โ all in one place.
Explore Hospitals
While the guide walks through deploying a Java application on Kubernetes effectively, it would be beneficial to address some day-two operational concerns. Java workloads running in containers often require JVM tuning to work efficiently within CPU and memory constraints. Additionally, discussing health checks, deployment rollback strategies, and monitoring approaches such as metrics collection and tracing would provide readers with a better understanding of how to keep Java applications reliable and observable in production Kubernetes clusters.