Using OS system variable for @DataSourceDefinition password failed in Wildfly 18

Tags: , , , ,



I want to externalize password for Java @DataSourceDefinition using OS system variable ${appuserpwd}. The below is my @DataSourceDefinition

@DataSourceDefinition(
    name = "java:app/jdbc/mydb", 
    className = "com.mysql.cj.jdbc.MysqlConnectionPoolDataSource", 
    portNumber = 3306, 
    serverName = "localhost", 
    databaseName = "mydb", 
    user = "appuser", 
    password = "${appuserpwd}", 
    isolationLevel = Connection.TRANSACTION_READ_COMMITTED, 
    properties = {})

I am using Wildfly 18. In subsystem ee, I already turn on these properties:

Annotation Property Replacement:  ON
JBoss Descriptor Property Replacement:  ON
Spec Descriptor Property Replacement:  ON

I always get an Exception error as below:

Caused by: java.sql.SQLException: Access denied for user 'appuser'@'localhost' (using password: YES)

It means Wildfly failed to translate ${appuserpwd} to the real password from OS system environment named appuserpwd.

I have tried ${env.appuserpwd} for @DataSourceDefinition password but I got the same message.

If I replace ${appuserpwd} by the appuser real password -> The app works OK, no issues.

Any helps? Thanks!

Answer

There was a Java EE 7 spec proposal to support password aliasing, but it never made it into the specification. So there is no way to replace variables in a standard and portable (working on each Java EE compliant server) way.

Fortunately, the different application servers offer their own solution to achieve this.

For Wildfly you have to first enable annotation property replacement inside your standalone.xml:

<subsystem xmlns="urn:jboss:domain:ee:5.0">
    <annotation-property-replacement>true</annotation-property-replacement>
</subsystem>

Now you can start replacing variables (syntax is ${ENV_VARIABLE:default}):

@DataSourceDefinition(
    name = "java:app/jdbc/pqsql",
    className = "org.postgresql.xa.PGXADataSource",
    user = "${DB_USER:postgres}",
    password = "${DB_PASSWORD:password}",
    serverName = "${DB_SERVERNAME:localhost}",
    portNumber = 5432,
    databaseName = "${DB_DATABASENAME:testdatabase}")

You can find further information here.

UPDATE: I tried this with a recent Wildfly version (20.0.0.Final) and it seems there is a bug when replacing annotation variables. As a fallback you can use the traditional way of specifying the datasource using the Jboss CLI and use environment variables as expected:

# First create the new module for the JDBC driver
/subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql, driver-module-name=org.postgresql, driver-class-name=org.postgresql.Driver, driver-datasource-class-name=org.postgresql.ds.PGPoolingDataSource)
 
# Create a data source
/subsystem=datasources/data-source=PostgresDS:add(jndi-name=java:jboss/datasources/postgres, driver-name=postgresql, connection-url=jdbc:postgresl://localhost:5432/postgres, user-name=postgres, password=postgres)


Source: stackoverflow