概述
jca依赖jta,也就是javax.resource-api依赖javax.transation-api。
javax.resource
javax.resource.cci
javax.resource.spi
javax.resource.spi.endpoint
javax.resource.spi.security
javax.resource.spi.work
J2EE提供JCA(Java Connector Architecture)规范来标准化对EIS(Enterprise Information System)的访问。这个规范被分为几个不同的部分:
SPI(Service provider interfaces)是连接器提供者(connector provider)必须实现的接口。 这些接口组成了一个能被部署在J2EE应用服务器上的资源适配器(resource adapter)。 在这种情况下,由服务器来管理连接池(connection pooling)、事务和安全(托管模式(managed mode))。 应用服务器还负责管理客户端应用程序之外所拥有的配置。连接器(connector)同样能在脱离应用服务器的情况下使用;在这种情况下,应用程序必须直接对它进行配置(非托管模式(non-managed mode))。
CCI (Common Client Interface)是应用程序用来与连接器交互并与EIS通信的接口。同样还为本地事务划界提供了API。
Spring对CCI的支持,目的是为了提供以典型的Spring方式来访问CCI连接器的类,并有效地使用Spring的通用资源和事务管理工具。
连接器的客户端不必总是使用CCI。 某些连接器暴露它们自己的API,只提供JCA资源适配器(resource adapter) 以使用J2EE容器的某些系统契约(system contracts)(连接池(connection pooling),全局事务(global transactions),安全(security))。 Spring并没有为这类连接器特有(connector-specific)的API提供特殊的支持。
基本概念
Enterprise Information System (EIS)
企业信息系统。 指 JCA 用来连接的另一端。 EIS 一般可为 ERP 系统, Database, Transaction Process(TP)系统。 基本就是指能让 client 通过 local 或者 remote 的接口调用暴露的服务的系统。
Application Component
一般为 Web 程序, 如 Servlet, JSP, EJB 等。 它通过 JNDI 的方式获取 JCA 暴露出来的引用, 然后调用其业务方法。
Application Server
指 J2EE application server。 它是 JCA 组件的运行时环境。 另外也包含 Application Componnet 运行时的容器, 如 Servlet 容器, EJB 容器。
Resource Adapter
JCA 的核心组件。 表现为一个 .rar 文件, 一般为 EIS 的提供商提供。 如果你的系统需要与别的系统做集成, 你有很可能就需要编写 Resource Adapater。
它部署在 Java EE server 中, 与 Java EE server 运行在同一个 JVM 下。它按照一定的规范负责 EIS 和 Java EE server 的交互。
基本架构
那么什么是 Java Connector Architecture 呢? 它是集成 Java EE server 和 EIS 的一种标准架构,用来负责 Java EE server 和 EIS 的交互。 它的实现分两部分, 一部分是 EIS vendor 提供的 Resource Adapter 实现(表现为一个 .rar 文件),另一部分是 Java EE server 里的实现,使得其允许 Resource Adapter 的载入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nn1G34Gl-1664267163485)(http://dl.iteye.com/upload/attachment/0075/7690/c2585a7e-ff60-3878-b35c-b0ace7ffe4a9.png)]
上面这副图描述了 JCA 的架构。 Application Component 通过 Container-Component Contract 部署并运行在 Application Server 里, 如 Servlet 运行在 Servlet 容器, EJB 运行在 EJB 容器等。 Application Component 通过 Client API 调用 Resource Adapter, Client API 可以是 JCA 的 common client api (CCI), 或者是自定义的接口。 Resource Adapter 负责和 EIS 的物理连接, 并且通过 System Contracts 部署和运行在 Application Server 里。 System Contracts 包含如 Connection Management Contract, Transaction Managedment Contract, Security Contract, Work Management 等, 部分在 Application Server 实现, 部分在 Resource Adapter 里实现。
接口详解
入口点是ResourceAdapter,这个接口代表了资源管理器的实例,方法定义了实例的生命期回调方法,其中start方法的参数实现了BootstrapContext接口,可以把应用服务器的服务能力作为上下文传入。
通过配置信息,可以获得Outbound信息入口接口ManagedConnectionFactory,通过这个接口的方法,可以获得被管理的连接ManagedConnection。我们要理解在JavaEE的世界里,几乎任何资源都是被管理的,或者可以看成是逻辑意义上的资源。通过JNDI获取到的接口实现类,在不同应用场景中,后台程序已经做了很多工作:有可能加入了丰富功能,也有可能是只是一个空的代理引用,等需要时再去访问真正的对象,达到节约占用资源的目的。通过ManagedConnection接口,应用可以进一步获得实现业务接口的对象,从而和外部信息系统进行交互。
对于Inbound来说,开发人员通过描述文件或者Activation注解定义,编写MDB来接受外部系统传入的消息。这里就引出一个很有趣的话题,我们学习JavaEE技术,特别是用到EJB时,规范有一个要求是不能创建线程,因为这样会让线程资源很难被容器全面管理。但一个常见的需求就是打开一个端口来接收外部的消息或者调用请求。一般实现方式会创建线程来完成端口侦听和接收消息,这样就违反了JavaEE规范要求。那么面对这样的需求该怎么做?这时WorkManager就发挥了它的作用。
WorkManager调度Work,而Work扩展了Runnable接口,这样可以把需要执行独立线程的代码逻辑封装到Work的实现类中,提交给WorkManager去调度执行。一般来说应用服务器会维护线程池来合理分配可用的线程资源,进行高效调度管理。这样类似于打开一个端口去接收消息的需求就可以被满足,绝大多数JMS实现的资源适配器就是这样做的。
说了这么多,可能大家觉得也不过如此,以上的需求不用JCA似乎也能实现,为什么要搞得很复杂来使用JCA呢?这样就引出JavaEE核心思想–事务性。
给企业开发应用,事务是一个极其重要的商业因素。我们知道财务会计核心准则之一就是有借必有贷,借贷必相等,这句话就充分体现了事务思想。企业的业务,流程,事件处理,都是有一定的管理规定的,每个涉及商业逻辑的业务系统,都会充分考虑满足业务事务一致性的需求。除了刚才说的财务系统以外,其他的企业软件系统也需要对事务有良好的支持,比如请假被批准了,同时可用年假记录数额也需要减少。整个系统内完成这个业务事务之后,还是处于一个“平衡”的状态,可以说企业应用的绝大多数软件都需要事务支持。
基于JavaEE开发的应用,一般来说也需要支持事务,同时和外部系统配合来支持完成一项事务过程。我们知道数据库,JMS服务器等都是支持事务的,和它们的连接中会带有事务上下文信息,这样就可以通过一定的契约(接口),来进行事务信息的传递。在JavaEE的设计思路中,可以通过声明式编程和对象功能加强来屏蔽一定程度的事务处理复杂性,这部分知识在讲述EJB核心思想的书籍里都有论述。简单来说是对象通过容器内部传递上下文(Context)信息来屏蔽一部分业务开发人员处理事务细节的繁杂编程工作。
这个上下文同时还可以传递安全相关信息,也就是JavaEE的安全相关的内容。JCA同样对连接管理的安全性进行了规范定义,从而可以方便的对应用服务器和外部系统的安全身份,授权信息进行管理和映射。在JCA1.6以后,对Inbound的事务和安全的定义也完善了。
既然这么好,那我们把JCA完全用在Java业务软件中如何?等等,JCA也有一些在技术选型上需要考量的地方。
首先是事务支持,我们知道事务可以说和系统可扩展性是冤家对头。事务过程中必然带有状态,而远程调用服务/可扩展的设计原则之一就是无状态的,这个矛盾无法避免。那么在不需要事务支持或者要求不高的业务范畴,比如论坛,博客等,我们可以选择取消事务支持来提高系统效率。其实这一点也是JavaEE技术在互联网领域面临尴尬的原因之一。
其次,JCA的关注点主要在连接管理上,规范并没有定义拿到连接后如何获取业务对象引用,以及业务对象接口的宽泛程度等内容。所以对于复杂的业务系统来说,资源适配器中绝大多数配置项都是私有的,无法全部规范化, 引入JCA对实际应用帮助有限。
第三,连接池是高性能业务系统的核心组件之一,数据库连接池的管理是运维工作的主要内容。但连接池功能众多,配置繁杂,每个应用服务器实现都不一致,而这部分内容并没有在规范中定义。所以应用在不同服务器间迁移变得很困难,光连接池配置就需要做很多工作。
那么什么场景适合使用呢?如果使用兼容JavaEE的应用服务器来开发,比如JBossAS(WildFly,Redhat JBoss EAP),Weblogic,Glassfish,Webshpere等,那么已经用上JCA。此外对需要支持分布式事务的软件系统,进行二次开发,JCA都是良好的技术选择。典型例子有各种MQ/JMS具备事务能力的系统,和Tuxedo连接的WTC资源适配器等。
还有一个更重要因素,就是JCA规范是系统间集成技术经验的一种体现,任何开发者基于JavaEE开发,需要和外部系统交互,在设计/编码/上线运营/系统成熟后会发现和目前JCA定义的体系架构会非常相似。学习JCA规范就能够快速掌握这套架构模型,这就是知识凝聚的力量。
CCI包
与连接有关的接口,描述一个工厂类连接和一个应用程序类连接。
javax.resource.cci.ConnectionFactory
javax.resource.cci.Connection
javax.resource.cci.ConnectionSpec
javax.resource.cci.LocalTransaction
与交互有关的接口,能使组件驱动一个与EIS实例的交互。
javax.resource.cci.Interaction
javax.resource.cci.InteractionSpec
与数据表现有关的接口,用来描述与EIS实例交互中涉及到的数据结构。
javax.resource.cci.RecordFactory
javax.resource.cci.Record
javax.resource.cci.MappedRecord
javax.resource.cci.IndexedRecord
javax.resource.cci.IndexedRecord
javax.resource.cci.ResultSet
java.sql.ResultSetMetaData
与元数据有关的接口,提供了一个资源适配器与EIS连接的基本的元信息。 javax.resource.cci.ConnectionMetaData
javax.resource.cci.ResourceAdapterMetaData
InBound和OutBound
JCA包含的组件很多,这些组件接口会被不同的角色实现或者使用,这些不同的角色包括应用、应用服务器(JavaEE容器)、适配器实现(比如MySQL的JDBC)等。
Java EE server 和 EIS 的交互有两种,一种叫 Outbound, 指由 application 通过 Java EE Server 发起的请求,通过 Resource Adapter 调用 EIS 服务; 另一种叫 Inbound, 指由 EIS 发出的请求, 通过 Resource Adapter 触发 Application 方法,通常为 Message Driven Bean。
Outbound resource adapter
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bgVtEEGG-1664267163488)(http://dl.iteye.com/upload/attachment/0075/8244/60201cff-7fd5-36bd-b877-bf711f565d72.png)]
Application 通过 JNDI 获取 ConnectionFactory 的引用, 然后创建 Connection, Connection 是 EIS 的 Connection Handler, 定义了 EIS specfic 方法。 ConnectionFactory 和 Connection 可以是 CCI 的接口,也可以是自定义的接口。如果是自定义的接口, ConnectionFactory 需要继承 java.io.Serializable 和 javax.resource.Referenceable 接口,以便注册进 JNDI。 ManagedConnectionFactory 用来创建 ManagedConnection, ManagedConnection 代表和 EIS 的物理连接,同时在连接关闭或者出现错误的时候通过 Connection Event Listener 通知 ConnectionManager 。 ConnectionManager 在 Application Server 里实现, 用来 allocate connection, 同时处理所有 ManagedConnection 的连接池,事务和安全。 ConnectionEventListener 使得 Connection Manager 知道每个 ManagedConnection 的状态。
我们的应用会使用到下面两个组件:
ConnectionFactory:
Connection:连接到EIS的连接,包含了连接所需的元数据信息;
ResourceAdapter 包含下面两个组件:
ManagedConnectionFactory:用来创建ManagedConnection的工厂;
ManagedConnection:一个ManagedConnection代表一个连接到目标EIS的物理连接。ManagedConnection可以在像连接关闭或者出错的时候通知应用服务器。
应用服务器包含下面两个组件:
ConnectionManager:ConnectionManager管理所有的ManagedConnection的池化,事务和安全;
ConnectionEventListener:ConnectionEventListener可以让ConnectionManager了解到每一个ManagedConnection的状态;
Inbound resource adapter
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oJUZT5Hx-1664267163490)(http://dl.iteye.com/upload/attachment/0075/8251/69e0cf62-2706-3a92-8bc4-d74c0976d9fc.png)]
ActivationSpec 是一个 JavaBean, 包含相应 EIS 的配置信息。ResourceAdapter 提供 inbound 交互的激活点, ResourceAdapter.endpointActivation 方法在一个 MessageEndpoint 被激活时调用, MessageEndPoint 在 application server 端实现。典型实现是 Message driven bean(MDB), 一个 MDB 被部署的时候, 会调用到 ResourceAdapter.endpointActivation 方法。 MessageEndpointFactory 用来创建 MessageEndpoint。 Resource Adapter Specific 的代码用来处理和 EIS 的交互, 并且通过 MessageEndpointFactory 发送消息。
对于ResourceAdapter是进数据,也就是数据用应用出,进入ResourceAdapter,然后进入到EIS。
我们的使用会用到如下的组件:
ActivationSpec:ActivationSpec 是一个 JavaBean, 包含相应 EIS 的配置信息。
ResourceAdapter包含如下的组件:
ResourceAdapter:ResourceAdapter进入应用的数据提供activation point;
ResourceAdapter Instance:处理与EIS的通信,通过持有的MessageEndpointFactory对象发送消息给EIS
应用服务器包括:
MessageEndpointFactory:注册到ResourceAdapter实例中,用来创建MessageEndpoint实例;
MessageEndpoint:MessageEndpoint实例中包含了从EIS过来的真正的消息。