当前位置: 首页 > 知识库问答 >
问题:

在 CICS 上的 WAS 自由上应用程序启动时Hibernate连接到 DB2

南门洋
2023-03-14

我们在 WebSphere 自由上运行一个简单的 Web 应用程序,它使用Hibernate作为持久性提供程序(作为 WAR 文件中的库包含在内)。

当应用程序启动时,Hibernate被初始化,它将打开到DB2的连接并发出一些SQL语句。但是,当在CICS上运行并使用JDBC Type 2驱动程序数据源时,这将失败。将记录以下消息(为了可读性,需要一些额外的换行符):

WARN  org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator -
    HHH000342: Could not obtain connection to query metadata : [jcc][50053][12310][4.19.56]
    T2zOS exception: [jcc][T2zos]T2zosCicsApi.checkApiStatus:
       Thread is not CICS-DB2 compatible: CICS_REGION_BUT_API_DISALLOWED ERRORCODE=-4228, SQLSTATE=null
...
ERROR org.hibernate.hql.spi.id.IdTableHelper - Unable obtain JDBC Connection
com.ibm.db2.jcc.am.SqlException: [jcc][50053][12310][4.19.56] T2zOS exception: [jcc][T2zos]T2zosCicsApi.checkApiStatus:
       Thread is not CICS-DB2 compatible: CICS_REGION_BUT_API_DISALLOWED ERRORCODE=-4228, SQLSTATE=null
    at com.ibm.db2.jcc.am.kd.a(Unknown Source) ~[db2jcc4.jar:?]
    ...
    at com.ibm.db2.jcc.t2zos.T2zosConnection.a(Unknown Source) ~[db2jcc4.jar:?]
    ...
    at com.ibm.db2.jcc.DB2SimpleDataSource.getConnection(Unknown Source) ~[db2jcc4.jar:?]
    at com.ibm.cics.wlp.jdbc.internal.CICSDataSource.getConnection(CICSDataSource.java:176) ~[?:?]
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[our-app.war:5.1.0.Final]
    at org.hibernate.internal.SessionFactoryImpl$3.obtainConnection(SessionFactoryImpl.java:643) ~[our-app.war:5.1.0.Final]
    at org.hibernate.hql.spi.id.IdTableHelper.executeIdTableCreationStatements(IdTableHelper.java:67) [our-app.war:5.1.0.Final]
    at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:125) [our-app.war:5.1.0.Final]
    at org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy.finishPreparation(GlobalTemporaryTableBulkIdStrategy.java:42) [our-app.war:5.1.0.Final]
    at org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl.prepare(AbstractMultiTableBulkIdStrategyImpl.java:88) [our-app.war:5.1.0.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:451) [our-app.war:5.1.0.Final]

我目前的理解是,当在CICS上运行并使用JDBCType2驱动程序时,只有一些线程能够打开DB2连接。这将是应用程序线程(处理HTTP请求的线程)以及为CICSExecutorService提供服务的工作线程。

目前的解决方案是:

  1. 通过将hibernate.temp.use_jdbc_metadata_defaults属性设置为false
  2. 来禁用在 中查找JDBC元数据
  3. Runnable中包装IdTableHelper#的执行,并将其提交给CICSExecutorService

您认为这种解决方案足以满足生产需求吗?或者也许你使用一些不同的方法?

使用的版本:

  • CICS Transaction Server for z/OS 5.3.0
  • WebSphere Application Server 8.5.5.8
  • Hibernate5.1.0

更新:澄清一下,一旦我们的应用程序启动,它可以毫无问题地查询DB2(当服务于HTTP请求时)。问题只与启动有关。


共有2个答案

云和硕
2023-03-14
匿名用户

以下解决方案已经过测试,工作正常。

这个想法是使用< code > CICSExecutorService # runas CICS 来执行SQL/DDL语句。以下扩展是通过< code > hibernate . hql . bulk _ id _ strategy 属性注册的。

package org.hibernate.hql.spi.id.global;

import java.util.concurrent.*;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.springframework.util.ClassUtils;
import com.ibm.cics.server.*;

public class CicsAwareGlobalTemporaryTableBulkIdStrategy extends GlobalTemporaryTableBulkIdStrategy {

    @Override
    protected void finishPreparation(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata, PreparationContextImpl context) {
        execute(() -> super.finishPreparation(jdbcServices, connectionAccess, metadata, context));
    }

    @Override
    public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
        execute(() -> super.release(jdbcServices, connectionAccess));
    }

    private void execute(Runnable runnable) {
        if (isCics() && IsCICS.getApiStatus() == IsCICS.CICS_REGION_BUT_API_DISALLOWED) {
            RunnableFuture<Void> task = new FutureTask<>(runnable, null);
            CICSExecutorService.runAsCICS(task);
            try {
                task.get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException("Failed to execute in a CICS API-enabled thread. " + e.getMessage(), e);
            }
        } else {
            runnable.run();
        }
    }

    private boolean isCics() {
        return ClassUtils.isPresent("com.ibm.cics.server.CICSExecutorService", null);
    }
}

请注意,较新的JCICS API版本有一个用于<code>runAsCics</code>方法的覆盖层,该方法接受<code>Callable</code>,这可能有助于将<code>execute</code>方法的CICS分支简化为如下所示:

CICSExecutorService.runAsCICS(() -> { runnable.run(); return null; }).get();

尝试了几种替代方案:

  1. 仅包装连接获取操作(org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl#getConnection)不起作用,因为连接在主线程中使用时已经关闭。
  2. 包装整个应用程序启动(org.springframework.web.context.ContextLoaderListener#contextInitialized)导致类加载问题。

编辑:最终使用了自定义Hibernate的<code>MultiTableBulkIdStrategy</code>实现,该实现在启动时不运行任何SQL/DDL(请参阅GitHub上的项目页面)。

薛钧
2023-03-14

CICS TS v5.3对Liberty中JPA特性的支持最近在一次服务更新(2016年7月)中可用。在此更新之前,试图在应用程序中运行JPA会导致与您描述的问题非常相似的问题。

尽管您正在运行Hibernate状态,并且您位于启用了 CICS 的线程上,但它没有 API 环境(这将允许类型 2 JDBC 调用成功)。新的检测逻辑是专门(但不是专门)开发的,用于 DB2 JDBC 类型 2 驱动程序和 JPA。此更新是在最近的服务更新中提供的,可能会解决您看到的问题。

尝试申请: http://www-01.ibm.com/support/docview.wss?crawler=1

描述说,它是为了支持“标准模式自由”,但它包含了上面概述的其他开发

 类似资料:
  • 我构建了一个侦听JMS.queue的简单MDB应用程序,并将其部署在IBM WARS 8.5.5上(使用IBM MQ作为JMS代理),当尝试启动它时,我收到以下错误(对不起,西里尔符号,尝试仔细翻译): 我的消息驱动ejb-mdb模块MDBListener.java: ejb-mdb模块ejb-jar.xml: ejb-mdb模块ibm-ejb-jar-bnd.xml:

  • 我在管理控制台(服务器>服务器类型>自由配置文件服务器)中看到了创建自由服务器的能力。然而,我无法得到任何工作,因为它似乎没有完全启用在WAS本身。 有人能告诉我如何安装Liberty,以便在WAS ND管理控制台中管理它吗?

  • 我在我的kubernetes集群上部署了RabbitMQ服务器,我能够从浏览器访问管理用户界面。但是我的Spring启动应用程序无法连接到端口5672,我收到连接拒绝错误。如果我将我的application.yml属性从kuberntes主机替换为localhost并在我的机器上运行docker映像,同样的代码也可以工作。我不确定我做错了什么? 有人试过这种设置吗?请帮帮忙。谢谢!

  • 编辑:根据Jim Rush的建议,我现在使用rc.local而不是init.d direclty来运行永远启动启动。 你知道为什么这不起作用吗?我在覆盆子皮B+上运行覆盆子。我已经运行了/etc/init.d kuuyi start和forever kicks并启动了该应用程序。只是启动机器后就不会发生了。 在这方面的任何帮助都是非常感谢的,我在这方面就像乳制品日后的旧奶酪布一样筋疲力尽。

  • 我有一个Play 2 Web应用程序,我使用Docker将其部署到弹性豆茎。在这个Web应用程序中,我启动了一个Akka集群。启动过程包括将自动缩放组中的所有节点添加为种子节点(包括其本身)。在第一次部署到EB时,我指定部署到VPC(我只选择一个可用性区域)。 当我运行应用程序并启动群集时,我收到以下消息: 关联错误[akka.tcp://cluster@localhost: 2551]- 其中1

  • 当我试图在Tomcat8上运行该项目时,遇到了一个非常奇怪的错误: INFO o.s.web.context.contextLoader-根WebApplicationContext:初始化已启动。信息O.S.W.C.S.AnnotationConfigWebApplicationContext-刷新根WebApplicationContext:启动日期[Mon Jun 29 10:59:34 C