分享
 
 
 

JBoss JTA的使用心得

王朝other·作者佚名  2007-06-08
窄屏简体版  字體: |||超大  

前些日子,农总行的客户有个需求,需要跨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.xml和 sybase-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>MS SQLSERVER2000</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。

Hashtable evn = new Hashtable();

evn.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");

evn.put(Context.PROVIDER_URL, "jnp://localhost:1299/");

InitialContext jndiContext = new InitialContext(evn);

DataSource ds = (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 {

UserTransaction utx = null;

try {

InitialContext jndiContext= new InitialContext();

utx= (javax.transaction.UserTransaction)jndiContext.lookup("UserTransaction");

utx.begin();

insertSQL_();

insertSybase();

utx.commit();

} catch (Exception e) {

if(utx!=null){

utx.rollback();//此处异常代码省略

}

}

}

private void insertSQL_() throws Exception{

Connection conn1 = createXAConnection("MSSQLXADS");

insertData(conn1); //插入数据测试,代码省略

}

private void insertSybase()throws Exception{

Connection conn2 = createXAConnection("XASybaseDS");

insertDataSybase(conn2); //插入数据测试,代码省略

throw new Exception(""); //此处做异常回滚测试

}

private Connection createXAConnection(String jndiname)throws Exception{

InitialContext jndiContext;

try {

jndiContext = new InitialContext();

DataSource ds = (DataSource)jndiContext.lookup(jndiname);

return ds.getConnection();

} catch (Exception e) {

// TODO Auto-generated catch block

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的事务完整性控制。

目前这个还是有些疑问,有待再仔细查阅资料,如果有明理者,也请告知一二。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有