JEE7/JAX-RS 如何以编程方式创建 JDBC 连接池

JEE7/JAX-RS How to programatically create a JDBC connectionpool

我目前正在开发 REST 服务来替换现有的解决方案。我正在使用普通 Payara/JEE7/JAX-RS。我没有使用 Spring,也无意使用。

我面临的问题是我们希望尽可能多地重用原始配置(通过 puppet 控制配置文件在集群中的多个节点上部署)。 通常在 Glassfish/Payara 中,您会有一个 domain.xml 文件,其中包含如下内容:

<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"/>

此外,您的存档中还有一个 persistence.xml 文件,如下所示:

<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>

我需要用编程解决方案替换这两个配置文件,以便我可以读取现有的遗留配置文件并(如果需要)在服务器启动时创建连接池和持久性单元。

你知道如何实现吗?

实际上您不需要手动编辑每个 domain.xml。只需像这样创建 glassfish-resources.xml 文件:

<?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>

然后要么使用

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

在每个节点上一次或将其放在 war 的 WEB-INF/ 下(注意,在这种情况下 jndi-name 应该是 java:app/jdbc/pgsql 因为你不可以访问全局:在此上下文中的范围)。

请注意,您的 persistence.xml 应该在类路径中任何 jar 的 META-INF/ 下。

如果你不喜欢这样,你可以使用

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

动态创建 EntityManager:

createEntityManager(java.util.Map properties).

顺便说一句,使用 Payara,您可以在集群中与 JCache 共享配置。

由于目标是拥有一个 运行 单一应用程序的 dockerized 服务器,我可以很好地使用嵌入式服务器。 使用嵌入式服务器,我的问题的解决方案大致如下:

对于服务器项目,创建Maven依赖:

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

像这样启动你的服务器:

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

将您的连接池添加到已启动的实例:

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

添加对应的jdbc资源:

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

(在现实世界中,您会从一些外部配置文件中获取数据)

现在部署您的应用程序:

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

(通常您会从某个部署目录读取您的应用程序)

在应用程序本身中,您可以像这样引用配置的池:

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

完成。

glassfish-resources.xml 也是可能的,但有一个问题:我的配置文件是外部的,由一些应用程序共享(因此文件格式不是我的)并由外部工具在部署时创建.我需要将文件 XSLT 到 glassfish-resources.xml 文件和 运行 执行 "asadmin" 调用的脚本。

运行 嵌入式服务器是一个全 java 解决方案,我可以轻松地在 CI 服务器上构建,我的应用程序的测试套件可以启动相同的嵌入式服务器构建以运行 一些集成测试。