Configuring a datasource with PostgreSQL and JBoss/WildFly

TL;DR: On WildFly 41, configure PostgreSQL (16/17) by installing the official JDBC driver module with dependencies on jakarta.transaction.api and jakarta.api. Define the driver and datasource dynamically via JBoss CLI using either clear text or Elytron credential stores. In Red Hat OpenShift and cloud-native Kubernetes environments, use the WildFly Operator or provision lightweight server images via Galleon feature-packs (postgresql-datasource layer), mapping database hostnames to internal Kubernetes Services and securing credentials with Secrets.

PostgreSQL remains one of the premier open-source relational databases in enterprise architectures. Connecting modern WildFly 41 (and JBoss EAP) deployments to PostgreSQL requires configuring high-performance connection pools, verifying driver dependencies under Jakarta EE, and adapting network configurations for containerized environments such as Red Hat OpenShift.

In this tutorial, you will learn how to provision a test PostgreSQL database, install the latest JDBC driver, configure production connection pools with JBoss CLI, integrate with Hibernate 6, and deploy to OpenShift using cloud-native configuration best practices.


1. Starting a PostgreSQL Instance

For local development and testing, run the current version of PostgreSQL using Docker or Podman:

podman run --name postgres-dev -d \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=mypassword123 \
  -e POSTGRES_DB=appdb \
  -p 5432:5432 postgres:17-alpine

Verify that PostgreSQL is ready to accept client connections:

podman exec -it postgres-dev pg_isready -U postgres

2. Installing the PostgreSQL JDBC Driver Module on WildFly 41

The official PostgreSQL JDBC driver is actively maintained on Maven Central. Download the current release (version 42.7.x or newer):

curl -O https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.4/postgresql-42.7.4.jar
Notice on Jakarta EE Dependencies: In WildFly 41, the legacy javax.api and javax.transaction.api modules are superseded by standard Jakarta specifications. When generating the driver module, declare dependencies on jakarta.api and jakarta.transaction.api.

Launch the JBoss CLI and connect to your running server instance:

$JBOSS_HOME/bin/jboss-cli.sh --connect

Step A: Register the JBoss Module

Add the core module under the org.postgres namespace:

module add --name=org.postgres \
  --resources=/path/to/postgresql-42.7.4.jar \
  --dependencies=jakarta.api,jakarta.transaction.api

Step B: Register the JDBC Driver in the Datasources Subsystem

Declare the driver definition referencing the newly installed module:

/subsystem=datasources/jdbc-driver=postgresql:add(\
  driver-name="postgresql",\
  driver-module-name="org.postgres",\
  driver-class-name="org.postgresql.Driver",\
  driver-xa-datasource-class-name="org.postgresql.xa.PGXADataSource")

3. Creating and Testing the Datasource

Now, define the connection pool pointing to your PostgreSQL instance. In local standalone mode, target port 5432:

data-source add \
  --name=PostgresPool \
  --jndi-name=java:jboss/datasources/PostgresDS \
  --driver-name=postgresql \
  --connection-url=jdbc:postgresql://localhost:5432/appdb \
  --user-name=postgres \
  --password=mypassword123 \
  --min-pool-size=10 \
  --max-pool-size=50 \
  --pool-prefill=true \
  --validate-on-match=true \
  --background-validation=false \
  --check-valid-connection-sql="SELECT 1"

Validating the Connection Pool

Execute an on-demand test from CLI to ensure credentials and network bindings are functional:

/subsystem=datasources/data-source=PostgresPool:test-connection-in-pool

Expected output:

{
    "outcome" => "success",
    "result" => [true]
}

Resulting standalone.xml Definition

The CLI commands above generate the following XML schema under the datasources subsystem:

<subsystem xmlns="urn:jboss:domain:datasources:7.2">
    <datasources>
        <datasource jndi-name="java:jboss/datasources/PostgresDS" pool-name="PostgresPool" enabled="true" use-java-context="true">
            <connection-url>jdbc:postgresql://localhost:5432/appdb</connection-url>
            <driver>postgresql</driver>
            <pool>
                <min-pool-size>10</min-pool-size>
                <max-pool-size>50</max-pool-size>
                <prefill>true</prefill>
            </pool>
            <security>
                <user-name>postgres</user-name>
                <password>mypassword123</password>
            </security>
            <validation>
                <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
                <validate-on-match>true</validate-on-match>
            </validation>
        </datasource>
        <drivers>
            <driver name="postgresql" module="org.postgres">
                <driver-class>org.postgresql.Driver</driver-class>
                <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
            </driver>
        </drivers>
    </datasources>
</subsystem>

4. PostgreSQL in a Red Hat OpenShift Context

Running WildFly 41 on Red Hat OpenShift requires adapting datasource configurations for container orchestration, Kubernetes Service discovery, and Secret management.

A. Service Discovery & Pod Networking

In OpenShift, databases are rarely accessed over localhost. They run inside independent Pods exposed via a Kubernetes Service (e.g., postgresql-service). Your connection URL should target the cluster DNS name:

jdbc:postgresql://postgresql-service.my-project.svc.cluster.local:5432/appdb

B. Provisioning with Galleon Feature-Packs (Cloud-Native Build)

Rather than manually installing JARs into container images at runtime, the modern cloud-native approach builds lightweight WildFly images using the WildFly Maven Plugin and Galleon layers:

<plugin>
    <groupId>org.wildfly.plugins</groupId>
    <artifactId>wildfly-maven-plugin</artifactId>
    <version>5.0.1.Final</version>
    <configuration>
        <feature-packs>
            <feature-pack>
                <location>org.wildfly:wildfly-galleon-pack:41.0.0.Final</location>
            </feature-pack>
            <!-- Include PostgreSQL driver Galleon feature pack -->
            <feature-pack>
                <location>org.wildfly:wildfly-datasources-galleon-pack:7.0.0.Final</location>
            </feature-pack>
        </feature-packs>
        <layers>
            <layer>cloud-server</layer>
            <layer>postgresql-datasource</layer>
        </layers>
    </configuration>
</plugin>

C. Injecting Environment Variables via OpenShift Secrets

When using the postgresql-datasource Galleon layer or the official WildFly OpenShift images, datasources are configured automatically at container startup through standard environment variables:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wildfly-app
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: wildfly
          image: image-registry.openshift-image-registry.svc:5000/my-project/wildfly-app:latest
          env:
            - name: POSTGRESQL_DATASOURCE
              value: "PostgresDS"
            - name: POSTGRESQL_DATABASE
              value: "appdb"
            - name: POSTGRESQL_SERVICE_HOST
              value: "postgresql-service"
            - name: POSTGRESQL_SERVICE_PORT
              value: "5432"
            - name: POSTGRESQL_USER
              valueFrom:
                secretKeyRef:
                  name: postgres-credentials
                  key: database-user
            - name: POSTGRESQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-credentials
                  key: database-password

This approach eliminates hardcoded database passwords from deployment descriptors and simplifies secret rotation via OpenShift's native RBAC.


5. Hibernate 6 & Jakarta Persistence Configuration

In WildFly 41 (aligned with Jakarta EE 10/11), the persistence engine is powered by Hibernate ORM 6.x. The legacy version-specific dialects (such as PostgreSQL95Dialect or PostgreSQL10Dialect) are deprecated.

For modern PostgreSQL installations (versions 11 through 17), specify the unified dialect in your persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence 
                                 https://jakarta.ee/xml/ns/persistence/persistence_3_1.xsd"
             version="3.1">

    <persistence-unit name="ProductionPU" transaction-type="JTA">
        <description>Enterprise PostgreSQL Persistence Unit</description>
        <jta-data-source>java:jboss/datasources/PostgresDS</jta-data-source>

        <properties>
            <!-- Unified Hibernate 6 Dialect -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            
            <!-- Schema Generation Strategy (validate in production) -->
            <property name="jakarta.persistence.schema-generation.database.action" value="validate"/>
            
            <!-- Performance Diagnostics -->
            <property name="hibernate.show_sql" value="false"/>
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.jdbc.batch_size" value="30"/>
            <property name="hibernate.order_inserts" value="true"/>
            <property name="hibernate.order_updates" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
Tip: In Hibernate 6, the dialect automatically inspects the database connection metadata on startup and adjusts SQL generation to match your exact PostgreSQL version (supporting JSONB indexing, window functions, and native partition syntax).

6. Troubleshooting & Production Tuning

A. SCRAM-SHA-256 vs. Ident Authentication Failures

If you encounter authentication exceptions such as:

Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "postgres"

Modern PostgreSQL releases (14+) default to SCRAM-SHA-256 password encryption rather than MD5. Verify authentication settings inside your database's pg_hba.conf file:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     scram-sha-256
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             0.0.0.0/0               scram-sha-256

Ensure that passwords configured via CLI or OpenShift Secrets match the encrypted SCRAM credential stored within PostgreSQL.

B. Sizing the WildFly Connection Pool vs. PostgreSQL max_connections

A frequent production issue in container clusters occurs when aggregate connection pool allocations exceed PostgreSQL's concurrency ceiling. The formula to keep in mind is:

$$\text{Total Connections} = (\text{OpenShift Pod Replicas}) \times (\text{max-pool-size}) + \text{Superuser Reserves}$$

If your WildFly deployment scales to 4 pods on OpenShift and each pod defines max-pool-size=30, you will require at least $4 \times 30 = 120$ connections. Update your postgresql.conf accordingly:

max_connections = 150
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 512MB

Summary & Best Practices

  • Use Jakarta EE Module Names: In WildFly 41, link modules against jakarta.transaction.api and jakarta.api instead of legacy javax namespaces.
  • Rely on the Unified Dialect: Specify org.hibernate.dialect.PostgreSQLDialect for modern PostgreSQL (11 through 17).
  • Automate with Galleon on OpenShift: Leverage wildfly-datasources-galleon-pack to package drivers at build time rather than manual post-boot scripting.
  • Secure Credentials: Isolate sensitive database passwords using OpenShift Secrets or WildFly Elytron credential stores.

Recommended Articles

Create and Configure DataSource with WildFly Application Server Using CLI

Learn how to create a DataSource for PostgreSQL in WildFly using CLI. Includes configuring and injecting it into a Java application.

Secure WildFly Datasource Passwords with Credential Stores and PicketBox

Learn how to protect sensitive data like PostgreSQL datasource passwords in WildFly using Elytron Credential Store or PicketBox encryption.

Configure Connection Properties in JBoss/WildFly Datasource - Expert Guide

Learn how to configure connection properties in JBoss/WildFly Datasource. #Java #WildFly #Datasource #ConnectionProperties

Datasource Configuration Cheatsheet for JBoss AS 7, JBoss EAP 6 and WildFly

Quick reference to valid Datasource configurations for JBoss AS 7, JBoss EAP 6 and WildFly. Includes examples for PostgreSQL, MySQL, Derby, Oracle, Microsoft SQLServer, IBM DB2.