当前位置: 首页 > news >正文

JBoss JTA的使用心得

前些日子,农总行的客户有个需求,需要跨Sybase ASE和Sybase IQ两个数据库操作,并且保证事务的完整性,而且客户不希望通过数据库层来保证事务,只希望在代码层控制。
这样的需求可能第一反应就是采用JTA,及XA事务(及通常所说的两阶段提交)支持。但是,这其中有一个数据库Sybase IQ,这是一个“数据仓库型”的数据库。Sybase中国区的技术支持也不能肯定是否IQ支持XA事务,因为IQ跨数据库事务操作在国内还没有过。
于是,只得做了个技术预研。说真的,虽然搞了这么多年java,还真没有碰到过跨数据库事务的项目,这次机会难得,好好研究一把。
本机暂时没有Sybase ASE,只能拿SQLServer替代一下。测试环境如下:
JTA Server: Jboss4.0.4
DataBase One: MS SQLServer 2000
DataBase Two:Sybase IQ 12.6
OS: Windows2003
JDBC Driver for sqlserver: jTDS1.2
JDBC Driver for Sybase IQ: jConnect-6_05
首先在Jboss中配置XADataSource。在 jboss404\docs\examples\jca 目录下,只有 mssql-xa-ds.xmlsybase-ds.xml,没有sybase-xa-ds.xml样例。于是自己写了一个sybase-xa-ds.xml。—— 后来发现这是“错误的做法”,只使用sybase-ds.xml即可了。
mssql-xa-ds.xml内容如下:
< datasources >
< xa-datasource >
< jndi-name > MSSQLXADS </ jndi-name >
< track-connection-by-tx />
< isSameRM-override-value > false </ isSameRM-override-value >
< xa-datasource-class > net.sourceforge.jtds.jdbcx.JtdsDataSource </ xa-datasource-class >
< xa-datasource-property name ="ServerName" > localhost </ xa-datasource-property >
< xa-datasource-property name ="DatabaseName" > foxtest </ xa-datasource-property >
< user-name > sa </ user-name >
< password > sa </ password >
< metadata >
< type-mapping > MSSQLSERVER2000 </ type-mapping >
</ metadata >
</ xa-datasource >
</ datasources >
sybase-xa-ds.xml内容如下:
< datasources >
< xa-datasource >
< jndi-name > XASybaseDS </ jndi-name >
< track-connection-by-tx />
< isSameRM-override-value > false </ isSameRM-override-value >
< xa-datasource-class > com.sybase.jdbc3.jdbc.SybDataSource </ xa-datasource-class >
< xa-datasource-property name ="ServerName" > localhost </ xa-datasource-property >
< xa-datasource-property name ="User" > dba </ xa-datasource-property >
< xa-datasource-property name ="Password" > sql </ xa-datasource-property >
< exception-sorter-class-name >
org.jboss.resource.adapter.jdbc.vendor.SybaseExceptionSorter
</ exception-sorter-class-name >
< no-tx-separate-pools />
< metadata >
< type-mapping > Sybase </ type-mapping >
</ metadata >
</ xa-datasource >
</ datasources >

专门写了一个 TestCase ,准备同外围访问通过 remote jndi 方式访问 datasource
Hashtableevn = new Hashtable();
evn.put(Context.INITIAL_CONTEXT_FACTORY,
" org.jnp.interfaces.NamingContextFactory " );
evn.put(Context.PROVIDER_URL,
" jnp://localhost:1299/ " );
InitialContextjndiContext
= new InitialContext(evn);
DataSourceds
= (DataSource)jndiContext.lookup( " java:MSSQLXADS " );
但是怎么连都访问不通:
而且jboss启动时候,datasource部署的信息也是:
13:34:31,473 INFO[WrapperDataSourceService]
Bound ConnectionManager 'jboss.jca:name=MSSQLXADS,service=DataSourceBinding'
to JNDI name 'java:MSSQLXADS'

后来在jboss wiki(http://wiki.jboss.org/wiki/Wiki.jsp?page=ConfigDataSources)上发现了问题所在 :<use-java-context> - A boolean indicating if the jndi-name should be prefixed with java: which causes the DataSource to only be accessible from within the jboss server vm. The default is true..
于是在ds.xml配置文件中增加了 <use-java-context>false</use-java-context> 属性,才算能够访问到jndi对象,只是 jndiContext.lookup("java:MSSQLXADS"); 需要更改为 jndiContext.lookup("MSSQLXADS")。
但是,在执行到DataSource ds = (DataSource)jndiContext.lookup("MSSQLXADS");这一步的时候,就抛出了ClassCastException,跟踪发现这个问原来是jndiContext.lookup返回的是javax.naming.Reference对象。
查了查资料,才发现这个问题的根源是由于javax.sql.DataSource不是可序列化,所以不能够在通过JNDI远程访问: The datasource unlike EJBs, does not implement a remote interface. (Notice the returned object is a javax.naming.Reference rather than DataSource). Hence if you want to lookup datasource, you have to be in the same process.
这个问题详细可参考:
http://forum.java.sun.com/thread.jspa?threadID=619429&tstart=0
没有办法,之后转移到Jboss Server内部来测试,不通过TestCase远程JNDI访问测试了。
内部通过一个Servlet测试,代码主体如下:
public void init() throws ServletException{
UserTransactionutx
= null ;
try {
InitialContextjndiContext
= new InitialContext();
utx
= (javax.transaction.UserTransaction)jndiContext.lookup( " UserTransaction " );
utx.begin();
insertSQL_();
insertSybase();
utx.commit();
}
catch (Exceptione){
if (utx != null ){
utx.rollback();
// 此处异常代码省略
}
}
}

private void insertSQL_() throws Exception{
Connectionconn1
= createXAConnection( " MSSQLXADS " );
insertData(conn1);
// 插入数据测试,代码省略
}

private void insertSybase() throws Exception{
Connectionconn2
= createXAConnection( " XASybaseDS " );
insertDataSybase(conn2);
// 插入数据测试,代码省略
throw new Exception( "" ); // 此处做异常回滚测试
}

private ConnectioncreateXAConnection(Stringjndiname) throws Exception{
InitialContextjndiContext;
try {
jndiContext
= new InitialContext();
DataSourceds
= (DataSource)jndiContext.lookup(jndiname);
return ds.getConnection();
}
catch (Exceptione){
// TODOAuto-generatedcatchblock
e.printStackTrace();
}
return null ;
}

但是程序在执行到获取 Sybase JNDI DataSource 的时候总是出现 ClassCastException ,错误如下:
16:26:14,605 WARN[JBossManagedConnectionPool] Throwable while attempting to get a new connection: null
org.jboss.resource.JBossResourceException:
Could not create connection; - nested throwable: (java.lang.ClassCastException)
at org.jboss.resource.adapter.jdbc.xa.XAManagedConnectionFactory.
createManagedConnection(XAManagedConnectionFactory.java:162)
at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.
createConnectionEventListener(InternalManagedConnectionPool.java:539)
at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.
allocateConnection(BaseConnectionManager2.java:812)
at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:88)

这个错误耽误很长时间,后来突然发现,Sybase的jConnect驱动,竟然没有实现javax.sql.XADataSource的接口。
于是,搜索了一下是否还有其他商业驱动支持Sybase IQ,但发现只有Sybase自身的jConnect。
到这里好像Sybase IQ不支持XA,但是随后做了一个大胆的测试,就是对Sybase使用sybase-ds.xml,而对SQLServer依然采用mssql-xa-ds.xml。sybase-ds.xml配置如下:
< datasources >
< local-tx-datasource >
< jndi-name > jdbc/SybaseDB </ jndi-name >
< connection-url > jdbc:sybase:Tds:localhost:2638 </ connection-url >
< driver-class > com.sybase.jdbc3.jdbc.SybDataSource </ driver-class >
< user-name > dba </ user-name >
< password > sql </ password >
< exception-sorter-class-name >
org.jboss.resource.adapter.jdbc.vendor.SybaseExceptionSorter
</ exception-sorter-class-name >
< metadata >
< type-mapping > Sybase </ type-mapping >
</ metadata >
</ local-tx-datasource >
</ datasources >
这个测试后,竟然发现此种配置竟然也支持JTA。
虽然这个实验可以控制Sybase IQ在JTA中的事务,但是到目前为止,我还是不太情况Sybase jConnect没有支持XADataSource接口,如何能够在JTA事务中控制的。
后来又做了进一步的测试,把MSSqlServer的那个数据源也换成了mssql-ds.xml,也是没有使用XA那个,竟然发现也受JTA的事务完整性控制。
目前这个还是有些疑问,有待再仔细查阅资料,如果有明理者,也请告知一二

相关文章:

  • 确保测试代码不会在发布版上运行
  • Tech-ED2006会场见闻图片集
  • 拨打电话时直接拨分机号
  • 技巧和诀窍:在VS 2005里使用Vista的IIS7
  • 使UIButton的子view不影响button的点击事件
  • 网站如何做分布式(集群)的大纲
  • iOS7下有时MKMapView中的字特别大的问题的解决
  • 有感Atlas - 优点、缺点、学习
  • NSInvocationOperation的cancelAllOperations不会取消正在运行的operation
  • 微软.NET俱乐部Tech-ED2006追踪报道!
  • MAC下SVN客户端Versions和Cornerstone的比较
  • 在ubuntu下用wine玩魔兽世界
  • 小孩不能吃黑枣
  • 9月23日培训日记
  • 治瘊子的小秘方
  • 2017 年终总结 —— 在路上
  • 77. Combinations
  • Apache Pulsar 2.1 重磅发布
  • CSS魔法堂:Absolute Positioning就这个样
  • JavaScript实现分页效果
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Redux系列x:源码分析
  • vuex 学习笔记 01
  • windows下mongoDB的环境配置
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 成为一名优秀的Developer的书单
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 记一次用 NodeJs 实现模拟登录的思路
  • 面试遇到的一些题
  • 如何使用 JavaScript 解析 URL
  • 如何学习JavaEE,项目又该如何做?
  • 使用权重正则化较少模型过拟合
  • 推荐一个React的管理后台框架
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 移动端唤起键盘时取消position:fixed定位
  • 译自由幺半群
  • 找一份好的前端工作,起点很重要
  • 白色的风信子
  • linux 淘宝开源监控工具tsar
  • Spring Batch JSON 支持
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​你们这样子,耽误我的工作进度怎么办?
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (4)事件处理——(7)简单事件(Simple events)
  • (编译到47%失败)to be deleted
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (转) Android中ViewStub组件使用
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (轉)JSON.stringify 语法实例讲解
  • .net6+aspose.words导出word并转pdf