[SOLVED] EAR + payara-resources.xml

I have an application that needs to support both native deployments and as a Docker container where the database connection properties are supplied through a config file. And of course, I also need to support development with direct deployment to the IDE’s registered Payara server (and through Docker/Skaffold in the future - things are in flux, hence the duality).

I already have WAR services built as Docker Payara Micro images where WEB-INF/payara-resources.xml registers a jdbc resource (java:app/jdbc/MyPU), and I want to do something similar with an EAR and Payara Full, but it needs work as both a native deployment and Docker image. The only roadblock I’m having is the EAR’s META-INF/payara-resources.xml not recognizing the environment (not system) variables.

my-app.ear/META-INF/payara-resources.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Payara.fish//DTD Payara Server 4 Resource Definitions//EN" "https://raw.githubusercontent.com/payara/Payara-Server-Documentation/master/schemas/payara-resources_1_6.dtd">
<resources>
       
    <jdbc-resource pool-name="MYDB" jndi-name="jdbc/MyPU" enabled="true" ></jdbc-resource>

    <jdbc-connection-pool datasource-classname="com.microsoft.sqlserver.jdbc.SQLServerDataSource"     
                          name="MYDB" 
                          res-type="javax.sql.DataSource"
                          is-connection-validation-required="true"
                          connection-validation-method="table"
                          validation-table-name="sys.tables"
                          fail-all-connections="true">
        <property name="User" value="${ENV=DATABASE_USER}"></property>
        <property name="Password" value="${ENV=DATABASE_PASS}"></property>
        <property name="DatabaseName" value="${ENV=DATABASE_NAME}"></property>
        <property name="ServerName" value="${ENV=DATABASE_SERVER}"></property>
        <property name="PortNumber" value="${ENV=DATABASE_SERVER_PORT}"></property>
        <property name="Encrypt" value="${ENV=DATABASE_SERVER_ENCRYPT}"></property>        
    </jdbc-connection-pool>  
    
</resources>

From the IDE (Netbeans) deploying directly to Payara:

Here is nbactions.xml, which just configures the launch (this works with the Payara Micro services that use the Maven PM plugin). Notice I tried both with Env. and without:

<actions>
    <action>
        <actionName>run</actionName>
        <packagings>
            <packaging>war</packaging>
            <packaging>ear</packaging>
            <packaging>ejb</packaging>
        </packagings>
        <goals>
            <goal>package</goal>
        </goals>
        <properties>
            <netbeans.deploy>true</netbeans.deploy>
            <Env.DATABASE_USER>user</Env.DATABASE_USER>
            <Env.DATABASE_PASS>pass</Env.DATABASE_PASS>
            <Env.DATABASE_NAME>MyDB</Env.DATABASE_NAME>
            <Env.DATABASE_SERVER>server</Env.DATABASE_SERVER>
            <Env.DATABASE_SERVER_PORT>1433</Env.DATABASE_SERVER_PORT>         
            <DATABASE_USER>user</DATABASE_USER>
            <DATABASE_PASS>pass</DATABASE_PASS>
            <DATABASE_NAME>MyDB</DATABASE_NAME>
            <DATABASE_SERVER>server</DATABASE_SERVER>
            <DATABASE_SERVER_PORT>1433</DATABASE_SERVER_PORT>
        </properties>
    </action>
</actions>
cd app; DATABASE_USER=user DATABASE_PASS=pass DATABASE_NAME=MyDB DATABASE_SERVER=server DATABASE_SERVER_PORT=1433 JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 mvn -Dnetbeans.deploy=true -DDATABASE_USER=user -DDATABASE_PASS=pass -DDATABASE_NAME=MyDB -DDATABASE_SERVER=server -DDATABASE_SERVER_PORT=1433 -Dexec.vmArgs= -Dexec.appArgs= --update-snapshots -U -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true -Dmaven.resolver.transport=wagon package

Error:

SEVERE:   RAR5104 : Not a valid type for this method : ${ENV=DATABASE_SERVER_PORT}
WARNING:   RAR5038:Unexpected exception while creating resource for pool { PoolInfo : (name=java:app/MYDB), (applicationName=my-app) }. Exception : javax.resource.ResourceException: Parameter wrong for this method : ${ENV=DATABASE_SERVER_PORT}
WARNING:   RAR5117 : Failed to obtain/create connection from connection pool [ { PoolInfo : (name=java:app/MYDB), (applicationName=my-app) } ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: Parameter wrong for this method : ${ENV=DATABASE_SERVER_PORT}
WARNING:   RAR5114 : Error allocating connection : [Error in allocating a connection. Cause: Parameter wrong for this method : ${ENV=DATABASE_SERVER_PORT}]
SEVERE:   Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.11.payara-p1): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error in allocating a connection. Cause: Parameter wrong for this method : ${ENV=DATABASE_SERVER_PORT}

In addition, when attempting to run the Docker container I get the following error:

{0} is not a valid data source. If you are using variable replacement then ensure that is available on the DAS
Exception while preparing the app : Invalid resource : jdbc/MyPU__pm
app-stack_app-service.1.6kbdpgk3gfrw@machien    | com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource : jdbc/MyPU__pm

So, it seems as though the environment variables are ignored.

I decided to do away with payara-resources.xml altogether. Instead, all native deployments (including development/Netbeans registered servers) will have their JDBC resources/pools preconfigured.

As for building a docker image, I’m running into a naming issue. Here is my post-boot-commands.asadmin from my project, which is copied into my image.

set-hazelcast-configuration --enabled=false
create-jdbc-connection-pool --datasourceclassname com.microsoft.sqlserver.jdbc.SQLServerXADataSource --restype javax.sql.XADataSource --isconnectionvalidationrequired true --connectionvalidationmethod table --validationtablename sys.tables --failallconnections true --nontransactionalconnections true --transactionisolationlevel read-committed --property TrustServerCertificate=false:User=${ENV=DATABASE_USER}:Password=${ENV=DATABASE_PASS}:DatabaseName=${ENV=DATABASE_NAME}:ServerName=${ENV=DATABASE_SERVER}:PortNumber=${ENV=DATABASE_SERVER_PORT}:Encrypt=${ENV=DATABASE_SERVER_ENCRYPT} MyDB
create-jdbc-resource --connectionpoolid MyDB jdbc/MyDB

Dockerfile:

FROM payara/server-full:5.2022.5-jdk11

EXPOSE 8080 8181

COPY docker/resources/mssql-jdbc-12.4.0.jre11.jar ${PAYARA_DIR}/glassfish/domains/${PAYARA_DOMAIN}/lib/
COPY docker/resources/post-boot-commands.asadmin $POSTBOOT_COMMANDS
COPY my-app-ear/target/*.ear $DEPLOY_DIR

The resulting service log:

my-app-stack_my-app-service.1.8cxw726x3cus@machine    | [#|2023-09-01T13:28:30.523+0000|INFO|Payara 5.2022.5|fish.payara.boot.runtime.BootCommand|_ThreadID=43;_ThreadName=RunLevelControllerThread-1693574909835;_TimeMillis=1693574910523;_LevelValue=800;|
my-app-stack_my-app-service.1.8cxw726x3cus@machine    |   Boot Command set-hazelcast-configuration returned with result SUCCESS : PlainTextActionReporterSUCCESSNo monitoring data to report.
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | |#]
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | 
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | [#|2023-09-01T13:28:30.634+0000|INFO|Payara 5.2022.5|fish.payara.boot.runtime.BootCommand|_ThreadID=43;_ThreadName=RunLevelControllerThread-1693574909835;_TimeMillis=1693574910634;_LevelValue=800;|
my-app-stack_my-app-service.1.8cxw726x3cus@machine    |   Boot Command create-jdbc-connection-pool returned with result SUCCESS : PlainTextActionReporterSUCCESSJDBC connection pool MyDB created successfully.|#]
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | 
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | [#|2023-09-01T13:28:30.695+0000|INFO|Payara 5.2022.5|fish.payara.boot.runtime.BootCommand|_ThreadID=43;_ThreadName=RunLevelControllerThread-1693574909835;_TimeMillis=1693574910695;_LevelValue=800;|
my-app-stack_my-app-service.1.8cxw726x3cus@machine    |   Boot Command create-jdbc-resource returned with result SUCCESS : PlainTextActionReporterSUCCESSJDBC resource jdbc/MyDB created successfully.|#]
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | 

And

my-app-stack_my-app-service.1.8cxw726x3cus@machine    |   Exception while preparing the app : Invalid resource : { ResourceInfo : (jndiName=java:app/jdbc/MyDB__pm), (applicationName=my-app-1.0.44-SNAPSHOT) }
my-app-stack_my-app-service.1.8cxw726x3cus@machine    | com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource : { ResourceInfo : (jndiName=java:app/jdbc/MyDB__pm), (applicationName=my-app-1.0.44-SNAPSHOT) }

Notice that it’s looking for java:app/jdbc/MyDB__pm and not jdbc/MyDB__pm.

I figured it out. It was a error on my part. I had changed the persistence.xml to reference java:app/jdbc/MyDB instead of just jdbc/MyDB in my attempt to make the flow similar to my Micro services.

Also, I was copying mssql-jdbc-12.4.0.jre11.jar to ${PAYARA_DOMAIN} when it should be copied to ${DOMAIN_NAME}.