#1
Struts is as reliable as ever, and integrating ClickHouse makes your Java web app analytics powerhouse-ready. Here’s how to set it up—locally with Docker, and securely in production using Kubernetes—without complicating your Struts codebase.

1. Add Dependencies to pom.xml

Start by bringing in the essentials:
<dependencies>
  <dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>${struts.version}</version>
  </dependency>

  <dependency>
    <groupId>com.clickhouse</groupId>
    <artifactId>clickhouse-jdbc</artifactId>
    <version>${clickhouse.jdbc.version}</version>
  </dependency>

  <dependency>
    <groupId>io.fabric8</groupId>
    <artifactId>kubernetes-client</artifactId>
    <version>${fabric8.version}</version>
  </dependency>
</dependencies>
That gives you Struts for web logic, the ClickHouse JDBC driver for database access, and the Kubernetes client for managing production environment variables.

2. Run ClickHouse Locally with Docker

Docker makes local setup a breeze:
docker run -d \
  --name clickhouse-server \
  -p 9000:9000 \
  -p 8123:8123 \
  clickhouse/clickhouse-server:latest
This spins up a ClickHouse container exposing ports for both native (9000) and HTTP (8123) protocols.

3. Create Dev Configuration: clickhouse-dev.properties

In src/main/resources, add:
db.driver=com.clickhouse.jdbc.ClickHouseDriver
db.url=jdbc:clickhouse://localhost:8123/default
db.user=
db.password=
db.validationQuery=SELECT 1
Load it in your Struts helper/DAO:
Properties props = new Properties();
props.load(getClass().getResourceAsStream("/clickhouse-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"));
}
This ensures development connectivity to ClickHouse running in Docker.

4. Set Up Kubernetes Config for Production

In production, externalize configs with ConfigMaps and Secrets:
kubectl create configmap clickhouse-config \
  --from-literal=DB_DRIVER=com.clickhouse.jdbc.ClickHouseDriver \
  --from-literal=DB_URL=jdbc:clickhouse://clickhouse-svc:8123/proddb \
  --from-literal=DB_VALIDATION_QUERY=SELECT 1

kubectl create secret generic clickhouse-secret \
  --from-literal=DB_USER=produser \
  --from-literal=DB_PASSWORD=prodpass
This lets you securely inject production credentials and endpoint settings at runtime.

5. Create Production Configuration File: clickhouse-prod.properties

Include this with your app:
db.driver=${DB_DRIVER}
db.url=${DB_URL}
db.user=${DB_USER}
db.password=${DB_PASSWORD}
db.validationQuery=${DB_VALIDATION_QUERY}
At startup, Struts will pick up environment variables supplied by Kubernetes.

6. Configuration in Kubernetes Deployment

Ensure your pod spec includes these environment variables:
env:
  - name: DB_DRIVER
    valueFrom:
      configMapKeyRef:
        name: clickhouse-config
        key: DB_DRIVER
  - name: DB_URL
    valueFrom:
      configMapKeyRef:
        name: clickhouse-config
        key: DB_URL
  - name: DB_VALIDATION_QUERY
    valueFrom:
      configMapKeyRef:
        name: clickhouse-config
        key: DB_VALIDATION_QUERY
  - name: DB_USER
    valueFrom:
      secretKeyRef:
        name: clickhouse-secret
        key: DB_USER
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: clickhouse-secret
        key: DB_PASSWORD
No code changes required—only config files differ.

7. Struts Action to Verify Connection

Try this Struts action to test the setup:
public class DbCheckAction extends ActionSupport {
  public String execute() {
    Properties p = new Properties();
    String file = System.getenv("DB_URL") != null
      ? "/clickhouse-prod.properties"
      : "/clickhouse-dev.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 ClickHouse successfully!");
      return SUCCESS;
    } catch (Exception e) {
      addActionError("Connection failed: " + e.getMessage());
      return ERROR;
    }
  }
}
Clean, readable, and works across both environments.

Why This Works

  • Quick local setup via Docker.
  • Production-grade config using Kubernetes ConfigMaps and Secrets.
  • No branching logic in code—just different .properties files.
  • Consistent environment structure reduces configuration errors.

image quote pre code