Struts still holds its place as an intuitive Java web framework, and pairing it with H2 Database gives you a powerful yet lightweight solution. In this tutorial, we’ll stick strictly to configuring H2 for Struts using Docker for local development and Kubernetes for production while keeping your code clean, secure, and consistent.
1. Add Dependencies in pom.xml
First, include the essential libraries needed for Struts and H2 connectivity:
<dependencies>
<!-- Struts framework -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts.version}</version>
</dependency>
<!-- H2 Database JDBC driver -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<!-- Kubernetes client for production config -->
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
<version>${fabric8.version}</version>
</dependency>
</dependencies>
This setup ensures your Struts app can talk to H2 via JDBC and that you have optional Kubernetes support for production builds.
2. Run H2 Using Docker for Development
H2 can run in server mode using Docker:
docker run -d \
--name h2-dev \
-p 9092:9092 \
-e H2_OPTIONS=-ifNotExists \
oscarfonts/h2
This spins up an H2 server on port
9092. It’s ready for local testing and development.
3. Create Development Configuration: h2-dev.properties
Create this file under
src/main/resources
:
db.driver=org.h2.Driver
db.url=jdbc:h2:tcp://localhost:9092/~/devdb;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE
db.user=sa
db.password=
db.validationQuery=SELECT 1
Notice the
AUTO_SERVER=TRUE
flag lets multiple connections access the same database file simultaneously.
Load it in your Struts DAO or helper:
Properties props = new Properties();
props.load(getClass().getResourceAsStream("/h2-dev.properties"));
Class.forName(props.getProperty("db.driver"));
try (Connection conn = DriverManager.getConnection(
props.getProperty("db.url"),
props.getProperty("db.user"),
props.getProperty("db.password"));
Statement stmt = conn.createStatement()) {
stmt.executeQuery(props.getProperty("db.validationQuery"));
}
Now your Struts application is connected to H2 in development.
4. Prepare Kubernetes Config for Production
For production, externalize path and settings via ConfigMaps and Secrets:
kubectl create configmap h2-config \
--from-literal=DB_DRIVER=org.h2.Driver \
--from-literal=DB_URL=jdbc:h2:tcp://h2-svc:9092/proddb;FILE_LOCK=FS \
--from-literal=DB_VALIDATION_QUERY=SELECT 1
kubectl create secret generic h2-secret \
--from-literal=DB_USER=sa \
--from-literal=DB_PASSWORD=
These environment variables allow you to avoid pushing database details into code.
5. Add Production Configuration: h2-prod.properties
Place this in your packaged resources:
db.driver=${DB_DRIVER}
db.url=${DB_URL}
db.user=${DB_USER}
db.password=${DB_PASSWORD}
db.validationQuery=${DB_VALIDATION_QUERY}
Spring boot or Struts reads these environment variables automatically—no code changes needed.
6. Kubernetes Deployment Snippet
In your Deployment manifest, specify:
env:
- name: DB_DRIVER
valueFrom:
configMapKeyRef:
name: h2-config
key: DB_DRIVER
- name: DB_URL
valueFrom:
configMapKeyRef:
name: h2-config
key: DB_URL
- name: DB_VALIDATION_QUERY
valueFrom:
configMapKeyRef:
name: h2-config
key: DB_VALIDATION_QUERY
- name: DB_USER
valueFrom:
secretKeyRef:
name: h2-secret
key: DB_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: h2-secret
key: DB_PASSWORD
Mount a PersistentVolumeClaim to store the
.mv.db
file, so your data survives pod restarts.
7. Example Struts Health Check Action
Try this quick health-check action:
public class DbHealthAction extends ActionSupport {
public String execute() {
String file = System.getenv("DB_URL") != null ? "/h2-prod.properties" : "/h2-dev.properties";
Properties p = new Properties();
p.load(getClass().getResourceAsStream(file));
Class.forName(p.getProperty("db.driver"));
try (Connection conn = DriverManager.getConnection(
p.getProperty("db.url"),
p.getProperty("db.user"),
p.getProperty("db.password"));
Statement stmt = conn.createStatement()) {
stmt.executeQuery(p.getProperty("db.validationQuery"));
addActionMessage("Connected to H2 successfully!");
return SUCCESS;
} catch (Exception e) {
addActionError("Connection failed: " + e.getMessage());
return ERROR;
}
}
}
This works the same way in both local and production builds—thanks to property switching.
Why This Works
- Fast local iteration: H2 in Docker means no heavy installations.
- Clean production config: Kubernetes manages environment values securely.
- One codebase: No conditionals, just different
.properties
files.
- Data persistence: Use mounting in Docker dev and PVC in Kubernetes prod.
image quote pre code