使用 ElephantSQL 在 Bluemix 中部署 Liberty 应用程序时找不到有效的 JDBC 驱动程序

Can't find valid JDBC driver when deploying Liberty app in Bluemix with ElephantSQL

我有一个我开发的 WebSphere Liberty 16.0.0.2 网络应用程序,运行 在我的笔记本电脑上本地使用 JPA 使用 Derby DB 来处理数据库。我曾经使用 SQLDB(IBM 于 2016 年 5 月停用)将它部署到 Bluemix 中,并且在自动连接服务时一切正常。由于 SQLDB 不再可用,我在 Bluemix 上唯一能找到的免费 SQL 是 ElephantSQL,但是自动装配似乎不起作用。这是我在部署后得到的错误:

Program error occured: CWWJP0013E: The server cannot locate the java:comp/env/jdbc/TriReplicatorDB data source for the TriReplicatorPersistenceUnit persistence unit because it has encountered the following exception: javax.naming.NamingException: CWNEN1001E: The object referenced by the java:comp/env/jdbc/TriReplicatorDB JNDI name could not be instantiated. If the reference name maps to a JNDI name in the deployment descriptor bindings for the application performing the JNDI lookup, make sure that the JNDI name mapping in the deployment descriptor binding is correct. If the JNDI name mapping is correct, make sure the target resource can be resolved with the specified name relative to the default initial context. [Root exception is com.ibm.wsspi.injectionengine.InjectionException: CWNEN0030E: The server was unable to obtain an object instance for the java:comp/env/jdbc/TriReplicatorDB reference. The exception message was: CWNEN1006E: The server was unable to obtain an object for the jdbc/TriReplicatorDB binding with the javax.sql.DataSource type. The exception message was: java.sql.SQLNonTransientException: DSRA4000E: A valid JDBC driver implementation class was not found for the jdbcDriver jdbcDriver[myDerbyJDBCdriver] using the library com.ibm.ws.classloading.sharedlibrary_79. [/home/vcap/app/wlp/usr/servers/triServer/lib/postgresql-jdbc-9.4.1209.jar]]. 

我上传网络应用的方式是打包服务器并使用cf push命令。这是生成的 server.xml 文件:

<server description="new server">
<!-- Enable features -->
<featureManager>
    <feature>jsp-2.3</feature>
    <feature>concurrent-1.0</feature>
    <feature>jaxrs-2.0</feature>
    <feature>jaxrsClient-2.0</feature>
    <feature>jpa-2.1</feature>
    <feature>appSecurity-2.0</feature>
    <feature>localConnector-1.0</feature>
    <feature>icap:managementConnector-1.0</feature>
    <feature>appstate-1.0</feature>
    <feature>jdbc-4.1</feature>
    <feature>cloudAutowiring-1.0</feature>
</featureManager>
<httpEndpoint httpPort="${port}" id="defaultHttpEndpoint" host="*"/>
<webContainer deferServletLoad="false" trustHostHeaderPort="true" extractHostHeaderPort="true"/>
<applicationMonitor updateTrigger="mbean"/>
<!-- This is the application itself -->
<webApplication contextRoot="/" id="Tri-Replicator" location="Tri-Replicator.war" name="Tri-Replicator">
</webApplication>
<jdbcDriver id="myDerbyJDBCdriver">
    <library name="DerbyLib">
        <fileset dir="C:\projects_c\Tri-Replicator-16\db\db-derby-10.11.1.1-bin\lib" includes="derby.jar"/>
        <fileset dir='${server.config.dir}/lib' includes='postgresql-jdbc-9.4.1209.jar'/>
    </library>
</jdbcDriver>
<!-- Use local Derby DB for local testing on laptop, but when deployed into BlueMix this will automatically be rewired to use SQL DB instance -->
<dataSource id="DerbyConnection" jdbcDriverRef="myDerbyJDBCdriver" jndiName="jdbc/TriReplicatorDB">
    <properties createDatabase="create" databaseName="${cloud.services.ElephantSQL-tri-replicator.connection.name}" user="${cloud.services.ElephantSQL-tri-replicator.connection.user}" password="${cloud.services.ElephantSQL-tri-replicator.connection.password}" serverName="${cloud.services.ElephantSQL-tri-replicator.connection.host}" portNumber="${cloud.services.ElephantSQL-tri-replicator.connection.port}"/>
</dataSource>
<include location='runtime-vars.xml'/>
<httpDispatcher enableWelcomePage='false'/>
<config updateTrigger='mbean'/>
<appstate appName='Tri-Replicator' markerPath='${home}/../.liberty.state'/>

作为替代问题 - 有人可以为 Bluemix 中的 SQL 数据库推荐其他小型免费计划吗? PostgreSQL 和 DB2 不提供免费计划。

报告的异常说明如下:

A valid JDBC driver implementation class was not found 
for the jdbcDriver jdbcDriver[myDerbyJDBCdriver]

此异常表示无法在 postgresql-jdbc-9.4.1209.jar.

中找到连接池数据源 class

WLP 按设计工作,需要在 server.xml 中进行额外配置,因为 WLP 只能找到特定数量的已知数据库 classes 的实现 [1]。我查看了 postgresql-jdbc-9.4.1209.jar 驱动程序,发现实现 class 如下:

org.postgresql.ds.PGPoolingDataSource

您应该使用以下内容更新 server.xml 文件:

javax.sql.DataSource="org.postgresql.ds.PGPoolingDataSource"

[1]https://www.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_dep_configuring_ds.html

要使用 PostgreSQL(这是 ElephantSQL 使用的 JDBC 驱动程序),您需要在 <jdbcDriver> 元素上指定数据源实现 class 名称:

<jdbcDriver id="myDerbyJDBCdriver" javax.sql.DataSource="org.postgresql.ds.PGPoolingDataSource">
  <!-- keep nested stuff the same -->
</jdbcDriver>

您需要为 PostgreSQL 而不是为 Derby 指定 DataSource impl class 的原因是因为 Derby 是 Liberty 的 "known" 数据库,而不是 PostgreSQL。

我会让 Liberty 开发人员知道这一点,以便将来某个时候可以将 PostgreSQL 添加为 "known" 数据库。