1

I'm currently developing a REST service to replace an existing solution. I'm using plain Payara/JEE7/JAX-RS. I am not using Spring and I do not intent to.

The problem I'm facing is that we want to reuse as much of the original configuration as possible (deployment on multiple nodes in a cluster with puppet controlling the configuration files). Usually in Glassfish/Payara, you'd have a domain.xml file that has some content like this:

<jdbc-connection-pool driver-classname="" pool-resize-quantity="10" datasource-classname="org.postgresql.ds.PGSimpleDataSource" max-pool-size="20" res-type="javax.sql.DataSource" steady-pool-size="10" description="" name="pgsqlPool">
  <property name="User" value="some_user"/>
  <property name="DatabaseName" value="myDatabase"/>
  <property name="LogLevel" value="0"/>
  <property name="Password" value="some_password"/>
 <!-- bla --->
</jdbc-connection-pool>
<jdbc-resource pool-name="pgsqlPool" description="" jndi-name="jdbc/pgsql"/>

Additionally you'd have a persistence.xml file in your archive like this:

<persistence-unit name="myDatabase">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/pgsql</jta-data-source>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
        <!-- bla -->
    </properties>
</persistence-unit>

I need to replace both of these configuration files by a programmatic solution so I can read from the existing legacy configuration files and (if needed) create the connection pools and persistence units on the server's startup.

Do you have any idea how to accomplish that?

Brixomatic
  • 381
  • 4
  • 16

2 Answers2

0

Actually you do not need to edit each domain.xml by hands. Just create glassfish-resources.xml file like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool driver-classname="" pool-resize-quantity="10" datasource-classname="org.postgresql.ds.PGSimpleDataSource" max-pool-size="20" res-type="javax.sql.DataSource" steady-pool-size="10" description="" name="pgsqlPool">
  <property name="User" value="some_user"/>
  <property name="DatabaseName" value="myDatabase"/>
  <property name="LogLevel" value="0"/>
  <property name="Password" value="some_password"/>
 <!-- bla --->
</jdbc-connection-pool>
<jdbc-resource pool-name="pgsqlPool" description="" jndi-name="jdbc/pgsql"/>
</resources>

Then either use

$PAYARA_HOME/bin/asadmin add-resources glassfish-resources.xml 

on each node once or put it under WEB-INF/ of your war (note, in this case jndi-name SHOULD be java:app/jdbc/pgsql because you do not have access to global: scope at this context).

Note that your persistence.xml should be under META-INF/ of any jar in your classpath.

If you do not like this, you may use

@PersistenceUnit(unitName = "MyDatabase")
EmtityManagerFactory emf;

to create EntityManager on fly:

createEntityManager(java.util.Map properties).

By the way, using Payara you can share configuration with JCache across you cluster.

S. Kadakov
  • 861
  • 1
  • 6
  • 15
  • Thanks for the information, even though it doesn't really answer my question. However, the asadmin script could be run as part of an installation script so that might come handy as a "workaround". Adding something as part of the war file is not viable, as the same application should be deployed with different settings (database addresses) on different nodes without building the war file for each node. – Brixomatic Sep 08 '16 at 12:26
  • Also you could consider to run asadmin first time your application starts via Runtime.exec(...). You can find asadmin using `com.sun.aas.installRoot' property. – S. Kadakov Sep 08 '16 at 13:28
0

Since the goal is to have a dockerized server that runs a single application, I can very well use an embedded server. Using an embedded sever, the solution to my problem looks roughly like this:

For the server project, create a Maven dependency:

<dependencies>
    <dependency>
        <groupId>fish.payara.extras</groupId>
        <artifactId>payara-embedded-all</artifactId>
        <version>4.1.1.163.0.1</version>
    </dependency>
</dependencies>

Start your server like this:

final BootstrapProperties bootstrapProperties = new BootstrapProperties();
final GlassFishRuntime runtime = GlassFishRuntime.bootstrap();
final GlassFishProperties glassfishProperties = new GlassFishProperties();
final GlassFish glassfish = runtime.newGlassFish(glassfishProperties);
glassfish.start();

Add your connection pools to the started instance:

final CommandResult createPoolCommandResult = commandRunner.run("create-jdbc-connection-pool",
    "--datasourceclassname=org.postgresql.ds.PGConnectionPoolDataSource", "--restype=javax.sql.ConnectionPoolDataSource", //
    "--property=DatabaseName=mydb"//
        + ":ServerName=127.0.0.1"//
        + ":PortNumber=5432"//
        + ":User=myUser"//
        + ":Password=myPassword"//
        //other properties
    , "Mydb"); //the pool name

Add a corresponding jdbc resource:

final CommandResult createResourceCommandResult = commandRunner.run("create-jdbc-resource", "--connectionpoolid=Mydb", "jdbc__Mydb");

(In the real world you would get the data from some external configuration file)

Now deploy your application:

glassfish.getDeployer().deploy(new File(pathToWarFile));

(Usually you would read your applications from some deployment directory)

In the application itself you can just refer to the configured pools like this:

@PersistenceContext(unitName = "mydb")
EntityManager mydbEm;

Done.

A glassfish-resources.xml would have been possible too, but with a catch: My configuration file is external, shared by some applications (so the file format is not mine) and created by external tools on deployment. I would need to XSLT the file to a glassfish-resources.xml file and run a script that does the "asadmin" calls.

Running an embedded server is an all-java solution that I can easily build on a CI server and my application's test suite could spin up the same embedded server build to run some integration tests.

Brixomatic
  • 381
  • 4
  • 16