读书人

解读《施用Jencks实现Hibernate与Jack

发布时间: 2012-10-25 10:58:58 作者: rapoo

解读《使用Jencks实现Hibernate与Jackrabbit的分布式事务》
前言

?

本文是针对《使用Jencks实现Hibernate与Jackrabbit的分布式事务》(以下简称《JHJ》)一文的理论分析。若只关心实现,请忽略此文点击这里跳转到实现的参考示例。

?

本文先简单介绍JTA和JCA的一些概念作为理论基础,之后再分析Jencks如何实现Hibernate与Jackrabbit的分布式事务的。

有关JTA

JTA全称为Java Transaction API,顾名思义JTA定义了一组统一的事务编程的接口,这些接口如下:

?

XAResource

?

XAResource接口是对实现了X/Open CAE规范的资源管理器 (Resource Manager,数据库就是典型的资源管理器) 的抽象,它由资源适配器 (Resource Apdater) 提供实现。XAResource是支持事务控制的核心。

Transaction

Transaction接口是一个事务实例的抽象,通过它可以控制事务内多个资源的提交或者回滚。二阶段提交过程也是由Transaction接口的实现者来完成的。

?

TransactionManager

?

托管模式?(managed mode)?下,TransactionManager接口是被应用服务器调用,以控制事务的边界的。

?

UserTransaction

非托管模式?(non-managed mode)?下,应用程序可以通过UserTransaction接口控制事务的边界

?

托管模式下的事务提交场景


解读《施用Jencks实现Hibernate与Jackrabbit的分布式事务》
?

?


?上图为JCA的架构图,中间涉及元素说明如下:

?

Enterprise Information System

简称EIS,在JTA中它又被称为资源管理器。典型的EIS有数据库,事务处理系统(Transaction Processing System),ERP系统。

?

Resource Adapter

资源适配器(Resource Adaper)是JCA的关键。要想把不同的EIS整合(或者连接)到J2EE运行环境中,就必须为每个EIS提供资源适配器,它会将将EIS适配为一个具备统一编程接口的资源 (Resource) 。这个统一编程接口就是上图中的System Contracts和Client API。下面的UML类图将完美诠释资源适配器。

?


解读《施用Jencks实现Hibernate与Jackrabbit的分布式事务》
?

Application Server

应用服务器 (Application Server) 通过System Contracts来管理对EIS的安全、事务、连接等。典型的应用服务器有JBoss、JOnAS、Geronimo、GlassFish等。

?

Application Component?

应用组件 (Application Component) ,它封装了应用业务逻辑,像对资源的访问和修改。典型的应用组件就是EJB。

?

更多细节请参见:

    Sun Microsystems Inc.J2EE Connector Architecture 1.5 。

?

实现分析

回到用《JHJ》的问题上来,上面关于JTA与JCA到底能够提供哪些帮助呢?总结一下有两点:

?

    我们需要两个资源适配器能够分别将Hibernate(实质是数据库)和Jackrabbit进行适配,以便将XAResource绑定到事务管理器中;
    我们需要一个事务管理器的实现来事务的托管。
事务管理器

众所周知,应用服务器是提供事务管理器实现的,但这不意味着我们只能选择应用服务器,不然就没有必要写《JHJ》和此文了。这里我选择了Jencks,它是一个轻量级的JCA容器,能够很容易与Spring进行集成,并由Spring的JtaTransactionManager将事务管理的职责委派给Jencks。

?

?

<!-- Jackrabbit --><bean id="repository"/></property><property name="connectionManager"><bean parent="connectionManager" /></property></bean><!-- Database --><bean id="dataSource" ref="jdbcManagedConnectionFactory" /><property name="connectionManager"><bean parent="connectionManager" /></property></bean>?ConnectionManagerFactoryBean将ConnectionManager与TransactionManager关联上;
<!-- 链接管理器 --><bean id="connectionManager" abstract="true"><property name="transactionManager"><ref local="delegateTransactionManager" /></property><property name="transaction" value="xa" /></bean>
?ManagerConnectionFactory创建的连接工厂都注入了ConnectionManager,为是让ConnectionManager来管理连接的分配,并enlistReource。
// DataSourceMCF.javapublic Object createConnectionFactory(ConnectionManager connectionManager) throws ResourceException {return new DataSource(this, connectionManager);}// JCAManagedConnectionFactory.javapublic Object createConnectionFactory(ConnectionManager cm)throws ResourceException {createRepository();JCARepositoryHandle handle = new JCARepositoryHandle(this, cm);log("Created repository handle (" + handle + ")");return handle;}

?

?

// DataSource.javapublic Connection getConnection() throws SQLException {try {return (Connection) cm.allocateConnection(mcf, containerRequestInfo);} catch (ResourceException e) {...}}// JCARepositoryHandle.javaprivate Session login(JCAConnectionRequestInfo cri)throws LoginException, NoSuchWorkspaceException, RepositoryException {try {return (Session) cm.allocateConnection(mcf, cri);} catch (ResourceException e) {...}}

?

?

?

// GenericConnectionManager.javapublic Object allocateConnection(ManagedConnectionFactory managedConnectionFactory, ConnectionRequestInfo connectionRequestInfo)throws ResourceException {ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, connectionRequestInfo);ConnectionInfo ci = new ConnectionInfo(mci);getStack().getConnection(ci); // 这里通过拦截器机制完成事件监听注册和enlistReourceObject connection = ci.getConnectionProxy();if (connection == null) {connection = ci.getConnectionHandle();}return connection;}// MCFConnectionInterceptor.javapublic void getConnection(ConnectionInfo connectionInfo) throws ResourceException {// ManagedConnectionInfo mci = ...try {// ManagedConnection mc = ......GeronimoConnectionEventListener listener = new GeronimoConnectionEventListener(stack, mci);mci.setConnectionEventListener(listener);mc.addConnectionEventListener(listener);} catch (ResourceException re) {...}}// TransactionEnlistingInterceptor.javapublic void getConnection(ConnectionInfo connectionInfo) throws ResourceException {next.getConnection(connectionInfo);try {ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo();Transaction transaction = TxUtil.getTransactionIfActive(transactionManager);if (transaction != null) {XAResource xares = mci.getXAResource();transaction.enlistResource(xares);}} catch (Exception e) {...}}

?

?

小结

解读《JHJ》的目的只为抛砖引玉,激发思考和探讨。此外,这里留下一个问题,在Spring的JtaTransactionManager的源码中发现,spring使用的是UserTransaction而不是TransactionManager这是为何呢?

?

?

?

?

1 楼 whaosoft 2009-01-17 呵呵 学习一下哈
JCA
Jencks
Jackrabbit 这个3个我都不会呵呵

读书人网 >软件架构设计

热点推荐