J2EE 连接器架构(J2EE Connector Architecture, JCA)简介(二)

 

通用客户机接口

概览

CCI 是应用组件使用的标准客户机 API。设计它是为了为 EIS 访问提供基础 API,EAI 和工具供应商们在此基础上构建更高级的功能。CCI 分为五部分,我们将在接下来的章节中讨论每个部分。CCI 的五部分是:

  • 与连接相关的接口
  • 与交互相关的接口
  • 与数据表示相关的接口
  • 与元数据相关的接口
  • 异常和警告

CCI 不需要资源适配器提供支持。事实上,资源适配器也许会定义它自己的不同于 CCI 的客户机 API。

与连接相关的接口

CCI 使用其 ConnectionFactory 接口来获取到 EIS 的连接句柄。ConnectionFactory 提供两个 getConnection() 方法:一个无参数的方法和一个将 ConnectionSpec 实例作为参数的方法。第二个 getConnection() 方法在必须和连接请求一起提供特定于该请求的信息时使用。

ConnectionFactory 也提供方法,返回关于资源适配器的元数据信息(getResourceAdapterMetaData()),返回记录工厂(getRecordFactory())。

ConnectionSpec 是一个空接口,可能会扩展该接口来添加任何所需属性。两个标准属性 UserNamePassword 是由 JCA 定义的,但可能支持也可能不支持额外的属性。当对 ConnectionManager 调用 allocateConnection() 时,资源适配器会将 ConnectionSpec 的属性映射到 ConnectionRequestInfo 的属性上。


连接方法

Connection 接口是一个用于访问 EIS 的应用程序级的连接句柄。它提供下列方法来管理应用程序和 EIS 间的连接:

  • close() 方法允许应用程序关闭连接句柄,正如连接管理契约所要求的。

  • getLocalTransaction() 方法允许应用组件使用本地事务。

  • createInteraction() 方法返回一个 Interaction 对象,该对象用于访问 EIS 功能。

  • getResultSetInfo() 方法返回关于由 EIS 支持的结果集功能的信息。

  • getMetaData() 函数返回关于该连接的元数据。

与交互相关的接口

Interaction 实例允许应用组件执行 EIS 功能。它有两个 execute() 方法:一个方法接受一个 InteractionSpec 和一个输入 Record,并返回一个输出 Record,另一个方法接受一个 InteractionSpec、一个输入 Record 和一个输出 Record。此方法执行如 InteractionSpec 定义的相应的 EIS 功能,并更新输出 Record

Interaction 必须维护跟创建它的 Connection 之间的关联,并且 getConnection() 必须返回该 Connection

Interaction 上的 close() 方法应释放所有由 Interaction 维护的资源,但不应关闭 Connection


标准交互属性和值

InteractionSpec 接口为 EIS 专用函数提供属性。它定义下列标准属性:

  • FunctionName 是一个表示 EIS 函数名称的字符串。

  • InteractionVerb 是一个整型,它指定与 EIS 交互的模式。InteractionVerb 允许的值为:

    • SYNC_SEND:输入记录被发送到 EIS,不返回任何结果。

    • SYNC_SEND_RECEIVE:输入记录被发送到 EIS,并返回一条结果。

    • SYNC_RECEIVE:从 EIS 同步获取到一条结果。


  • ExecutionTimeout 是等待 EIS 执行该函数的毫秒数。

与数据表示相关的接口

Record 接口为输入或输出到 EIS 的数据提供 Java 表示。Record 有两个标准属性:RecordNameRecordShortDescription。 表示 EIS 记录数据的额外属性必须由实现程序定义。

另外,还提供了三个扩展 Record 的接口。MappedRecord 接口提供对键值映射集合记录元素的访问。IndexedRecord 接口提供对排好序的集合记录元素的访问。ResultSet 接口基于 JDBC ResultSet 并提供相似的功能用于访问 EIS 数据。

RecordFactory 接口提供方法来创建 MappedRecordIndexedRecord 实例。RecordFactory 也许支持其中一类记录,也许两类都支持,也许全不支持。如果全不支持,随后,ConnectionFactorygetRecordFactory() 方法会抛出一个异常。


与元数据相关的接口

ManagedConnectionMetaData 接口相似,ConnectionMetaData 接口提供关于 EIS 名称、EIS 版本及用户名的信息。

ResourceAdapterMetaData 接口提供关于适配器名称、版本、供应商、描述以及资源适配器支持的 JCA 版本的信息。它也提供决定资源适配器下列功能的方法:是否使用 InteractionSpec;支持哪个 execute() 方法变量;本地事务是否能根据应用组件进行划分。


异常和警告

ResourceException 是系统契约和 CCI 的异常层次的根。它提供一个字符串来描述错误、错误代码和对另一个异常的引用,这也许是引起 ResourceException 的低层次问题。

ResourceWarning 提供关于警告的信息,这些警告由 EIS 作为一个 Interaction 的结果返回。这些 ResourceWarning 构成一个链;调用 Interaction 上的 getWarnings() 获得第一条警告,通过该警告访问链的余下的部分。

 

样例资源适配器

本节概览

在本节中,将介绍 JCA 资源适配器的一个简单实现。样例资源适配器在 helloworldra.rar 文件中。Java 类文件在这个 RAR 文件的 helloworldra.jar 文件中。所有类的源码也在 helloworldra.jar 中。

您也许能从它的名字里猜到,这个资源适配器可以实现无所不在的 “Hello World” 功能。同样地,它并不真的连接到一个企业系统,它的功能局限于仅返回一个包含这句十分常见的消息的字符串。尽管资源适配器并不实现事务契约或安全性契约,但它的确实现 CCI;它使用一个 Interaction、一个 InteractionSpec、一个 RecordFactory 和多个 IndexedRecord

关于样例资源适配器最重要最有趣的部分将在接下来的探讨中提炼和解释。除了类和接口,我们还探讨部署描述符的源代码。从这个简单实现中,您将能够得到一些关于需要编写的类以及这些类之间的关系的体会。除了学习下面两个部分,您还应该花一些时间复习完整的源代码,您可以在 参考资料 中找到该代码。

HelloWorldConnectionFactoryImpl

HelloWorldConnectionFactoryImpl 类实现 CCI ConnectionFactory 接口,并提供应用组件使用的连接工厂,从而创建到 EIS 的连接。下面是创建 HelloWorldConnectionFactoryImpl 实例的代码,以及返回连接的客户机方法、记录工厂和元数据。

创建连接工厂实例
HelloWorldConnectionFactoryImpl 类的构造方法需要传入 ConnectionManagerManagedConnectionFactory,从而在 getConnection() 方法中使用,如下所示:

...
public HelloWorldConnectionFactoryImpl(
   ManagedConnectionFactory mcf,
   ConnectionManager cm) {

   super();
   this.mcf = mcf;
   this.cm = cm;
}
...

获取连接
HelloWorldConnectionFactoryImpl 类既不支持 ConnectionRequestInfo 也不支持 ConnectionSpec,所以两个 getConnection() 方法做相同的事:它们调用 ConnectionManagerallocateConnection() 方法,针对 ConnectionRequestInfo 传入 ManagedConnectionFactorynull,如下所示:

...
public Connection getConnection() throws ResourceException {

   return (Connection) cm.allocateConnection(mcf, null);
}

public Connection getConnection(ConnectionSpec connectionSpec) 
  throws ResourceException {

   return getConnection();
}
...

记录工厂和元数据方法
getRecordFactory()getMetaData() 方法仅仅为各自的接口返回实现类,如下所示:

...
public RecordFactory getRecordFactory() throws ResourceException {

   return new HelloWorldRecordFactoryImpl();
}

public ResourceAdapterMetaData getMetaData() throws ResourceException {

   return new HelloWorldResourceAdapterMetaDataImpl();
}
...

HelloWorldConnectionImpl

HelloWorldConnectionImpl 类实现 CCI Connection 接口,并为应用组件访问 EIS 提供连接句柄。下面是创建、验证和关闭连接的方法、为客户机提供 Interaction 和元数据的方法以及通知该类不支持本地事务和结果集的代码。

创建连接
HelloWorldConnectionImpl 类的构造函数需要传入 ManagedConnection,以在 close() 中使用。在实例化的过程中设置了一个标记来指示有效连接,即,非关闭的连接。换言之,在恰当的地方通过检查此标记来决定能否执行所请求的动作。

...
public HelloWorldConnectionImpl(ManagedConnection mc) {

   super();
   this.mc = mc;
   valid = true;
	}
...

使连接失效
invalidate() 方法设置 ManagedConnectionnull 的引用。并将标志设置为表示连接不再有效。

...
void invalidate() {

   mc = null;
   valid = false;
}
...

关闭连接
close() 方法根据所需委派其对 ManagedConnection 的调用。

...
public void close() throws ResourceException {

   if (valid) {
      ((HelloWorldManagedConnectionImpl) mc).close();
   }
}
...

交互和元数据方法
createInteraction()getMetaData() 方法仅仅为各自的接口返回实现类。

...
public Interaction createInteraction() throws ResourceException {

   if (valid) {
      return new HelloWorldInteractionImpl(this);
   } else {
      throw new ResourceException(CLOSED_ERROR);
   }
}

public ConnectionMetaData getMetaData() throws ResourceException {

   if (valid) {
      return new HelloWorldConnectionMetaDataImpl();
   } else {
      throw new ResourceException(CLOSED_ERROR);
   }
}
...

抛出 NotSupportedException
由于此资源适配器既不支持本地事务也不支持结果集,所以 getLocalTransaction() 方法和 getResultSetInfo() 方法都抛出 NotSupportedException

...
public LocalTransaction getLocalTransaction() throws ResourceException {

   throw new NotSupportedException(TRANSACTIONS_NOT_SUPPORTED);
}

public ResultSetInfo getResultSetInfo() throws ResourceException {

   throw new NotSupportedException(RESULT_SETS_NOT_SUPPORTED);
}
...

HelloWorldManagedConnectionFactoryImpl

HelloWorldManagedConnectionFactoryImpl 类实现了 ManagedConnectionFactory 接口,在下面的代码中,您将看到如何创建一个连接工厂、如何创建一个受管的连接以及类如何响应请求来匹配受管的连接。

创建一个连接工厂以及一个受管的连接
createConnectionFactory()createManagedConnection() 方法分别简单地返回实现类。由于此资源适配器并未实现安全性契约,createManagedConnection() 并不使用 Subject 或者 ConnectionRequestInfo 参数来创建 ManagedConnnection

...
public Object createConnectionFactory(ConnectionManager cm)
   throws ResourceException {

   return new HelloWorldConnectionFactoryImpl(this, cm);
}

public ManagedConnection createManagedConnection(
   Subject subject,
   ConnectionRequestInfo cxRequestInfo)
   throws ResourceException {

   return new HelloWorldManagedConnectionImpl();
}
...

匹配受管的连接
此资源适配器实现的简单性使每一个 ManagedConnection 之间难以区分。因此,matchManagedConnections() 方法仅仅返回输入的 Set 中的第一个 ManagedConnection,如下所示:

...
public ManagedConnection matchManagedConnections(
   Set connectionSet,
   Subject subject,
   ConnectionRequestInfo cxRequestInfo)
   throws ResourceException {

   ManagedConnection match = null;
   Iterator iterator = connectionSet.iterator();
   if (iterator.hasNext()) {
      match = (ManagedConnection) iterator.next();
   }

   return match;
}
...

HelloWorldManagedConnectionImpl

HelloWorldManagedConnectionImpl 类实现 ManagedConnection 接口。在下面的代码中,您将看到 getConnection()close()cleanup() 以及 destroy() 方法如何协作来创建、关闭并清理一个连接,正如这些方法所暗示的,此资源适配器不支持事务。

创建一个连接
getConnection() 方法首先验证一个现存的连接句柄,如果句柄存在,就创建一个新的连接句柄,将其存储至一个实例变量中。然后返回一个到该实例变量的引用。这在连接句柄和 ManagedConnection 之间维护了一个一对一的关系。一个资源适配器可能具有多个连接句柄同一个 ManagedConnection 相关联,但是并不需要这么做。

...
public Object getConnection(
   Subject subject,
   ConnectionRequestInfo cxRequestInfo)
   throws ResourceException {

   if (connection != null) {
      connection.invalidate();
   }
   connection = new HelloWorldConnectionImpl(this);
   return connection;
}
...

关闭连接
close() 方法通知已经发生 ConnectionEventListener 关闭操作,然后验证连接句柄。

...
public void close() {

   Enumeration list = listeners.elements();
   ConnectionEvent event =
      new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED);
   while (list.hasMoreElements()) {
      ((ConnectionEventListener) list.nextElement()).connectionClosed(event);
   }
   connection.invalidate();
}
...

清理并销毁一个连接
cleanup()destroy() 方法都可使连接句柄失效。为了将该连接从应用服务器的连接池移除,destroy() 方法也将 ManagedConnection 实例变量设置成 null

...
public void cleanup() throws ResourceException {

   connection.invalidate();
}

public void destroy() throws ResourceException {

   connection.invalidate();
   connection = null;
   listeners = null;
}
...

抛出一个 NotSupportedException
由于此资源适配器并不支持事务,getXAResource()getLocalTransaction() 方法都抛出 NotSupportedException

...
public XAResource getXAResource() throws ResourceException {

   throw new NotSupportedException(TRANSACTIONS_NOT_SUPPORTED_ERROR);
}

public LocalTransaction getLocalTransaction() throws ResourceException {

   throw new NotSupportedException(TRANSACTIONS_NOT_SUPPORTED_ERROR);
}
...

HelloWorldInteractionImpl

HelloWorldInteractionImpl 类实现了 CCI Interaction 接口。在本节中,您将看到该类的一些更重要的元素是如何协作,从而创建、执行以及关闭一个 Interaction 的。

创建 Interaction
由于 JCA 需要一个 Interaction 维护跟创建它的连接句柄的关联,构造函数需要传入一个 Connection。 在实例化的过程中设置了一个标志来指示有效 Interaction,即,非关闭的。换言之,在恰当的地方通过检查此标志来决定能否执行所请求的动作。

...
public HelloWorldInteractionImpl(Connection connection) {

   super();
   this.connection = connection;
   valid = true;
}
...

执行一个 Interaction
HelloWorldInteractionImpl 类只支持带有一个 InteractionSpec、一个输入记录以及一个输出记录的 execute() 方法(其他的 execute() 方法抛出 NotSupportedException)。该方法确保:

  • Interaction 是有效的
  • 传入了正确的 InteractionSpec 实现实例
  • 提供了正确的输入记录类型
  • 提供了正确的输出记录类型

execute() 方法
如果所有的条件正确,"Hello World!" 就处于输出记录中。如果某一条件有误,就会抛出一个异常。

...
public boolean execute(InteractionSpec ispec, Record input, Record output)
   throws ResourceException {

   if (valid) {
      if (((HelloWorldInteractionSpecImpl) ispec)
         .getFunctionName()
         .equals(HelloWorldInteractionSpec.SAY_HELLO_FUNCTION)) {
         if (input.getRecordName().equals(HelloWorldIndexedRecord.INPUT)) {
            if 
            (output.getRecordName().equals(HelloWorldIndexedRecord.OUTPUT)) {
               ((HelloWorldIndexedRecord) output).clear();
               ((HelloWorldIndexedRecord) output).add(
                   OUTPUT_RECORD_FIELD_01);
            } else {
               throw new ResourceException(INVALID_OUTPUT_ERROR);
            }
         } else {
            throw new ResourceException(INVALID_INPUT_ERROR);
         }

      } else {
         throw new ResourceException(INVALID_FUNCTION_ERROR);
      }
   } else {
      throw new ResourceException(CLOSED_ERROR);
   }
   return true;
}
...

关闭 Interaction
close() 清除了连接句柄并将 Interaction 标为无效。

...
public void close() throws ResourceException {

   connection = null;
   valid = false;
}
...

HelloWorldInteractionSpec

为了对使用此资源适配器的应用组件隐藏尽可能多的实现细节,HelloWorldInteractionSpec 接口扩展了 InteractionSpecInteractionSpec 接口允许我们提供应用组件所必须有的全部信息。在下一部分中,我们会介绍此接口的实现类。

...
public interface HelloWorldInteractionSpec extends InteractionSpec {

   public static final String SAY_HELLO_FUNCTION = "sayHello";

   public String getFunctionName();
   public void setFunctionName(String functionName);
}

HelloWorldInteractionSpecImpl

HelloWorldInteractionSpecImpl 实现了 HelloWorldInteractionSpec 接口。它有一个属性:FunctionName,有一个 getter 和 setter 方法来访问该属性。JCA 规范指出 InteractionSpec 实现中的属性必须是受限制的。此实现提供了受限的属性。

...
public String getFunctionName() {

   return functionName;
}

public void setFunctionName(String functionName) {

   String oldFunctionName = functionName;
   this.functionName = functionName;
   firePropertyChange("FunctionName", oldFunctionName, functionName);
}
...

HelloWorldIndexedRecord

正如 HelloWorldInteractionSpecHelloWorldIndexedRecord 接口用于对应用组件隐藏实现细节。

...
public interface HelloWorldIndexedRecord extends IndexedRecord {

   public static final String INPUT = "input";
   public static final String OUTPUT = "output";
   public static final int MESSAGE_FIELD = 0;
}


HelloWorldIndexedRecordImpl

HelloWorldIndexedRecordImpl 类实现 HelloWorldIndexedRecord 接口。它具有两个属性:NameShortDescription,以及访问这些属性的 getter 和 setter 方法。由于此类必须实现 List 接口,它维护了一个 ArrayList 作为实例变量并通过调用 ArrayList 的相应方法实现所有的 List 方法。

...
public class HelloWorldIndexedRecordImpl implements HelloWorldIndexedRecord {

   private ArrayList list = new ArrayList();
   private String name;
   private String description;
...

HelloWorldRecordFactoryImpl

HelloWorldRecordFactoryImpl 类实现 RecordFactory 接口。它不支持创建 MappedRecord

createIndexedRecord() 方法确保请求的记录名称是有效的,然后创建该记录并返回它。如果记录名是无效的,就抛出一个异常。

...
public IndexedRecord createIndexedRecord(String recordName)
   throws ResourceException {

   HelloWorldIndexedRecordImpl record = null;

   if ((recordName.equals(HelloWorldIndexedRecord.INPUT))
      || (recordName.equals(HelloWorldIndexedRecord.OUTPUT))) {
      record = new HelloWorldIndexedRecordImpl();
      record.setRecordName(recordName);
   }
   if (record == null) {
      throw new ResourceException(INVALID_RECORD_NAME);
   } else {
      return record;
   }
}
...


部署描述符

部署描述符提供了下列 JCA 组件的全名:

  • ManagedConnectionFactory 实现类
  • ConnectionFactory 接口
  • ConnectionFactory 实现类
  • Connection 接口
  • Connection 实现类

它也表示既不支持事务也不支持重新认证。如果支持事务和安全性契约,部署描述符将包含额外的一些元素。

< !DOCTYPE connector PUBLIC '-//Sun Microsystems, Inc.//
  DTD Connector 1.0//EN' 'http://java.sun.com/dtd/connector_1_0.dtd'>

<connector>
   <display-name>Hello World Sample</display-name>
   <vendor-name>Willy Farrell</vendor-name>
   <spec-version>1.0</spec-version>
   <eis-type>Hello World</eis-type>
   <version>1.0</version>
   <resourceadapter>
      <managedconnectionfactory-class>
      com.ibm.ssya.helloworldra.HelloWorldManagedConnectionFactoryImpl
      </managedconnectionfactory-class>
      <connectionfactory-interface>
      javax.resource.cci.ConnectionFactory
      </connectionfactory-interface>
      <connectionfactory-impl-class>
      com.ibm.ssya.helloworldra.HelloWorldConnectionFactoryImpl
      </connectionfactory-impl-class>
      <connection-interface>
      javax.resource.cci.Connection
      </connection-interface>
      <connection-impl-class>
      com.ibm.ssya.helloworldra.HelloWorldConnectionImpl
      </connection-impl-class>
      <transaction-support>
      NoTransaction
      </transaction-support>
      <reauthentication-support>
      false
      </reauthentication-support>
   </resourceadapter>
</connector>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值