




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
什么是分布式事务?在开始研究如何使用分布式事务开发应用程序之前,让我们回顾一下什么是分布式事务以及为什么说它们很有用。有几个术语经常被混淆:事务、分布式事务、两阶段提交(two-phasecommit)、XA事务、事务传播和CORBAOTS事务。但实际上这些术语的含义各不相同:事务一作为工作的单一逻辑单元而执行的一系列操作,在执行过程中要么所有的操作都被执行,要么一个都不执行(也被称为本地或简单事务)。事务经常被描述为ACID-原子性、一致性、隔离性和持久性。为使事务持久,在事务的试验期所做的变更,最终必须用提交操作作为事务的结尾。如果有任何变更不能被提交,则事务将回滚(rollback),并取消所有的变更,恢复到事务从没有发生之前的状态。如果代码执行的操作决定不进行提交或者不能成功提交,那么它必须回滚该事务以取消这些操作。如果在事务进行期间应用程序崩溃,则在重启时,事务恢复将回滚该事务。在写事务中,所有的变更必须全部提交或者全部回滚。在读事务中,没有变更需要提交,但是事务会防止对正在被读取的数据的修改,直到所有的读操作全部结束。分布式事务一两个或更多事务资源(比如,两个单独的数据库)之间的ACID事务。为使事务成功提交,所有的独立资源必须全部成功提交。如果其中的任何一个没有成功提交,则事务必须在所有的资源中回滚。两阶段提交一一种分两步提交分布式事务的方法:第1阶段,准备每个资源报告是否其已经准备完毕,可以提交--通常通过继续并保持新数据,但仍然不删除旧数据。第2阶段,提交:如果所有的资源都准备就绪,则全部进行提交--在旧数据删除且事务不再回滚之后进行。两阶段提交确保了分布式事务也可以始终提交或者始终回滚,即使在事务提交过程中系统的一部分崩溃,也不会受到影响。有许多(但不是全部)分布式事务的实现使用两阶段提交。XA规范--开放组织(OpenGroup)的X/Open分布式事务流程(DTP)模型,它定义了应用程序如何使用事务管理程序跨多个资源管理程序来协调分布式事务。如果事务是通过遵循XA的事务管理程序来进行协调的,则任何遵循XA规范的资源管理程序都可以参与该事务,因此就可以让不同厂商的事务产品可以共同工作。所有遵循XA的事务都是分布式事务。XA既支持一步提交,也支持两阶段提交。下图是XA规范,它展示了分布式事务的各部分:X/Open分布式事务(DTP)模型事务传播一通过将事务上下文作为线程的一部分进行传递,以允许多个合作对象参与单个事务。当线程经过合作对象时,事务管理程序使用线程的事务上下文来执行所有的工作。CORBAOTS规范一对象管理组(ObjectManagementGroup)的通用对象请求代理体系结构对象事务服务(CommonObjectRequestBrokerArchitectureObjectTransactionService)--定义遵循规范的流程如何跨多个流程线程将事务上下文从一个流程传播到另一个流程。这种传播使得即使分布式对象运行于来自不同厂商的容器中,也可以在单个事务中合作°CORBAOTS规范建立在XA规范的基础之上。下图是OTS规范,它展示了包含分布式对象的事务的各部分:对象事务服务(OTS)模型IBM®WebSphere®ApplicationServerV5为其应用程序提供既符合XA规范又符合CORBAOTS规范的事务管理程序。该事务管理程序实现了两个API,这两个API是Java™2EnterpriseEdition(J2EE)的一部分--Java事务API(JTA),它提供对Java事务服务(JavaTransactionService,JTS)的简单访问。对于任何遵循XA规范的资源,JTA的XA部分都有能力协调用这些资源的事务(通过接口javax.transaction.xa.XAResource)。J2EE中支持XA的两个资源类型是Java数据库连接(JavaDatabaseConnectivity,JDBC)API(通过接口javax.sql.XAConnection)和Java消息服务(JavaMessageService,JMS)API(通过接口javax.jms.XAConnection)。当一个容器中的EJB调用另一个容器中的EJB时,事务管理程序将使用CORBAOTS。为什么使用分布式事务?当应用程序需要访问或更新事务资源中的数据时,它应该(通常是必须)使用事务来进行该项工作。在没有自动提交的标准JDBC代码中,应用程序使用一个连接来访问和更新数据,然后提交该连接以结束这个事务(并启动另一个事务)。当JMS客户端发送或接收消息时,消息传递提供方使用事务来向目标中添加消息或从目标中删除消息。JMS客户端可以任意的显式控制该事务,比如在同一个消息传递系统中,协同处理从一个队列接收消息和向另一个队列发送消息。当应用程序有一个单独的功能需要访问或更新多个事务资源中的数据时,应该使用分布式事务。您可以在每个资源中使用独立的简单事务,但是这种方法很容易出错。如果一个资源中的事务成功提交,而另一个资源中的事务提交失败且必须回滚,那么第一个事务将不再回滚,这将使应用程序的状态不一致。如果一个资源成功提交,但在另一个资源成功提交前系统崩溃,那么也会造成应用程序状态不一致。哪些功能需要访问多个事务资源?以下是一些例子:•在数据库之间移动数据一将数据从一个数据库移动到另一个数据库的应用程序需要使用分布式事务。否则,数据可能会重复(如果插入成功但删除失败)或丢失(如果删除成功但插入失败)。•在数据库和消息之间移动数据--应用程序需要将数据从JMS消息移动到数据库表,或者相反。如果不使用分布式事务,数据可能会重复或丢失。•将消息纪录到数据库一应用程序也许要使用数据库来保存“跟踪纪录”,“跟踪纪录”中记录了该应用程序与合作伙伴应用程序进行交换的消息。为了让纪录保持持久且准确,需要在发送或接收消息的分布式事务中记录这些消息。•在消息传递系统之间移动消息一许多消息传递场景包括接收一个消息并发送另一个消息作为结果。当两个目的地在同一个消息传递系统中时,接收和发送可以在一个简单事务中进行,这是因为它们只涉及单一的事务资源。然而,当从一个消息传递系统接收消息,并将消息发送到另一个单独的消息传递系统时,应用程序应该在两个消息传递系统间的分布式事务中执行操作,以确保消息不会重复或丢失。•与企业信息系统(EIS)协同工作--J2EE规范包含J2EE连接器体系结构,该体系结构用于实现适配器以访问企业信息系统(EIS),比如CICS或SAP。适配器提供的事务支持级别一无、本地或XA--这取决于EIS被赋予的适配能力。如果适配器支持XA事务,应用程序就可以使用分布式事务来协调EIS资源与JDBC和JMS资源。基本上,只要应用程序使用多个事务性持久资源,就需要使用分布式事务。操作多个资源的任何功能都应该使用分布式事务。事务和EJBEnterpriseJavaBeans(EJBs)有许多优点:组件化、远程调用、安全性、持久性功能、消息传递功能等等。尽管这些功能都很有用,但使用EJB的最大好处可能就是事务管理。EJB和容器管理事务(container-managedtransactions,CMTs)使事务管理对于bean开发人员来说实质上是透明的。EJB上的每个公共方法都定义了EJB容器和EJB客户端之间的事务边界,并在部署描述符指定该边界。这种方式的结果是客户端调用的所有EJB代码都运行于单个容器管理事务中(直到部署描述符指定另一个),这样代码的工作要么全部执行,要么全部回滚。此外,bean开发人员实际上不需要编写任何用于处理事务的代码,比如确定何时调用commit()方法以及调用失败时该如何处理。容器通过事务边界和部署描述符表示了事务模型,并在运行时控制事务的提交和回滚。即使多个EJB合作执行任务时,EJB容器管理事务也可以工作。一旦线程中的第一个EJB建立了事务上下文,事务容器将使用事务传播来将该上下文传递到合作EJB,这样所有的工作都在同一事务中执行(直到部署描述符指定另一个)。即使合作EJB存在于不同的容器中,CORBAOTS也可以启用容器的事务管理程序进行协调,从而使事务跨容器传播。EJB容器管理事务对控制分布式事务特别有帮助。该方法允许代码操作多套数据,而不需要关心数据是来自单个资源(需要简单事务)还是多个资源(需要分布式事务)。应用程序只根据需要来使用EJB操作数据。EJB容器的事务管理程序在运行时确定数据是来自单个资源(这种情况下它使用资源管理程序管理事务),还是来自多个资源(这种情况下使用事务管理程序管理事务,并协同资源管理程序)。不管数据来自于单个还是多个资源,EJB代码保持不变,而由EJB容器适当的处理事务。回页首使用分布式事务进行开发现在我们已经审查了想达到什么目标。我们确定了分布式事务是什么、有帮助且必需的场景,以及EJB技术如何使这些场景对bean开发人员大大简化。现在我们使用WebSphereStudioApplicationDeveloper(以下简称ApplicationDeveloper)来创建并运行一个简单的范例。这些代码片断向您展示了如何创建ApplicationDeveloper测试服务器,以及如何为JDBC和JMS配置该服务器。它向您演示了使用特定于本范例的值来填写特定设置。每个表单前的描述说明了哪些值是适用于所有应用程序的,哪些值是特定于本范例的。本范例也将说明如何为两个常用JDBC数据库产品(DB2®和Oracle)配置XA数据源。还将说明如何用XA连接来配置JMS目的地。为开始本范例,我们需要创建一个新的测试服务器。为此,切换到Servers透视图。从ServerConfiguration视图的上下文(通过单击鼠标右键)菜单,选择New=>ServerandServerConfiguration。在创建对话框中,输入服务器名称(例如'XAExampleServer”),选择TestEnvironment(对于本范例,WebSphere5.0版本或WebSphere5.1版本都可以)作为服务器类型,然后单击finish。创建新服务器和服务器配置对话框配置OracleXA数据源在创建数据源之前,我们将创建JAAS身份验证条目,以后我们将使该条目关联到数据源,以便登录数据库。在服务器配置编辑器中,切换到Security页面。在JAASAuthenticationEntries列表中添加一个条目。您的条目必须对您的数据库有效,如本文所示,它能够创建表和添加数据。在本范例中,我们将使用一个注册范例,它是缺省Oracle安装的一部分。您可以通过特定的安装来使用不同的注册。OracleJAAS身份验证条目设置属性名称属性值是否缺省?AliasScottUserIDscottPasswordtiger添加JAAS身份验证条目对话框对于本范例,服务器配置必须包含JNDI中注册的JDBC数据源,比如jdbc/OracleXADS。它是JDBC提供者,并将作为OracleXA数据库而被访问。首先,我们需要创建描述如何访问OracleXA的JDBC提供者。在服务器配置编辑器中,切换到DataSource页面。在JDBC提供者列表中按下面所示添加一个提供者。名称可以任选,我们将使用与提供者类型相同的名称。OracleJDBC提供者设置属性名称属性值是否缺省?JDBCProvidertypeOracleJDBCDriver(XA)NameOracleJDBCDriver(XA)Implementationclassnameoracle.jdbc.xa.client.OracleXADataSourcedefaultClasspath${ORACLE_JDBC_DRIVER_PATH}/ojdbc14.jardefault创建JDBC提供者对话框第二步,创建JDBC数据源以提供对特定OracleXA数据库的访问。选择我们刚刚创建的Oracle提供者,然后用如以下所示的设置添加一个数据源。名称可以任选。JNDI名是您的代码用来查找数据源的唯一标识符。本文的范例代码使用jdbc/OracleXADS作为JNDI名。对于容器管理的身份验证别名,选择我们先前创建的JAAS身份验证条目。URL是所需的资源属性,它指定访问数据库的路径。OracleJDBC数据源设置属性名称属性值是否缺省?JDBCProvidertypeOracleJDBCDriver(XA),version5.0NameExampleOracleXADataSourceJNDInamejdbc/OracleXADSHelperclasscom.ibm.websphere.rsadapter.OracleDataStoreHelperdefaultAuthenticationaliasScottURLjdbc:oracle:thin:@localhost:1521:example创建JDBC数据源对话框我们刚才创建的JDBC提供者会在特定的目录中查找它的JAR文件,该目录通过变量ORACLE_JDBC_DRIVER_PATH指定。该变量必须设置为正确的目录,但WebSphereStudio并不知道您的Oracle客户端安装在哪里,因此您必须指定该目录。在服务器配置编辑器中,切换到Substitutionvariables页面。在Node设置下面是已定义变量列表。找到用于Oracle的变量,并将其设置为包含ojdbc14.jar文件的目录。Oracle定义的变量(对节点)设置属性名称属性值是否缺省?ORACLE_JDBC_DRIVER_PATHC:\oracle\ora92\jdbc\lib
编辑OracleJDBC驱动程序路径变量对话框现在您已经用OracleXAJDBC数据源配置了服务器。保存服务器配置。尽管您已经用OracleXAJDBC数据源配置了您的测试服务器,但还需要对Oracle数据库自身进行配置以使其支持XA事务。OracleDBA可以帮助您确定是否需要进一步的配置,并可以帮助您执行这些步骤。在本文的后面,我们将讨论如果您的Oracle针对XA进行配置,将会出现什么错误,以及如何进行正确的配置。配置DB2XA数据源本范例还包含了DB2XA数据源°DB2数据源的配置设置与Oracle数据源的配置设置很相似。首先,定义一个JAAS标识用于登录到您的数据库。在本范例中,我们设置了一个名为DB2的标识。DB2JAAS身份验证条目设置第二步,我们需要为DB2XA数据源创建一个JDBC提供者。DB2JDBC提供者设置属性名称属性值是否缺省?JDBCProvidertypeDB2UniversalJDBCDriverProvider(XA)NameDB2UniversalJDBCDriverProvider(XA)Implementationcom.ibm.db2.jcc.DB2XADataSourcedefault
classnameClasspath${DB2UNIVERSAL_JDBC_DRIVER_PATH}}/db2jcc.jar${UNIVERSAL_JDBC_DRIVER_PATH}}/db2jcc_license_cu.jar${DB2UNIVERSAL_JDBC_DRIVER_PATH}}/db2jcc_license_cisuz.jardefault第三步,需要使用JNDI名称jdbc/DB2XADS创建DB2XA数据源。我们将使用在第1步中创建的JAAS标识。尽管Oracle数据源需要URL字符串来访问数据库,但DB2数据源只需要数据库名称,在本范例中数据库名称为“sample”。DB2JDBC数据源设置属性名称属性值是否缺省?JDBCProvidertypeDB2UniversalJDBCDriverProvider(XA),version5.0NameExampleDB2XADataSourceJNDInamejdbc/DB2XADSHelperclasscom.ibm.websphere.rsadapter.DB2UniversalDataStoreHelperdefaultAuthenticationaliasDB2databaseNamesample第四步,需要指定安装DB2驱动程序的路径,这是包含了db2jcc.jar文件的目录。另外,还需要核对数据源类路径中其他变量的缺省值。DB2定义的变量(对节点)设置属性名称属性值是否缺省?DB2UNIVERSAL_JDBC_DRIVER_PATHC:\db2\SQLLIB\javaUNIVERSAL_JDBC_DRIVER_PATH$(WAS_INSTALL_ROOT}/universalDriver/libdefault现在您已经配置了DB2XA数据源,并将其注册为jdbc/DB2XADS。保存服务器配置。配置JMS提供者为了演示XA事务,我们还需要嵌入JMS资源。ApplicationDeveloper中内嵌了JMS模拟器,它是一个简单的JMS资源,但却包含了全部的XA功能。您的使用DB2或OracleXA的WebSphere应用程序可以使用JMS以外的资源,但本范例需要使用JMS。
在服务器配置编辑器中,切换到JMS页面。在JMSServerProperties下,添加队列名XAExampleQ。在JMSProvider下,选择MQSimulatorforJavaDevelopers。在本范例中,服务器配置必须包括两个JMS资源:一个名为jms/XAExampleQCF的队列连接工厂(queueconnectionfactory)和一个名为jms/XAExampleQ的队列。在服务器配置编辑器的JMS页面上,在WASQueueConnectionFactories条目列表中,按以下所示添加一个新的队列连接工厂。确保XA支持被启用,这是本范例中最重要的一点。WAS队列连接工厂设置属性名称属性值是否缺省?NameXAExampleQCFJNDINamejms/XAExampleQCFEnableXASupportTrue(checked)default添加WAS队列连接工厂对话框
在WASQueue条目列表中,用以下设置添加一个新队列:WAS队列设置属性名称属性值是否缺省?NameXAExampleQJNDINamejms/XAExampleQ添加WAS队列对话框保存服务器配置。现在服务器配置已经全部完成。它有一个用于通过XA访问Oracle的数据源,以及一个使用支持XA事务的队列连接工厂的JMS队列。您甚至现在就可以运行服务器。它不包含任何应用程序,但您可以检验它是否可以正常启动,并可以检验我们为该服务器配置的JNDC中的对JDBC和JMS资源的绑定。成功的启动将包含以下特定于JMS以及特定于JDBC的消息:JMSMQJDProvidAMSGS0656I:StartingtheMQJDJMSProviderJMSMQJDProvidAMSGS0650I:MQJDJMSProvideropenforbusinessResourceMgrImIWSVR0049I:BindingXAExampleQCFasjms/XAExampleQCFResourceMgrImIWSVR0049I:BindingXAExampleQasjms/XAExampleQResourceMgrImIWSVR0049I:BindingExampleOracleXADataSourceasjdbc/OracleXADSResourceMgrImIWSVR0049I:BindingExampleDB2XADataSourceasjdbc/DB2XADSCacheServicelIDYNA0048I:WebSphereDynamicCacheinitializedsuccessfully.可选项:导入服务器配置您确实应该按以上描述的方法练习设置服务器配置。但如果您配置不成功,并且希望运行下面将描述的范例应用程序,您可以导入配置。为了开始导入,请下载并解压缩范例文件。它包含一个名为XAExampleServer.wsc的目录,这是WebSphereversion5.1服务器配置。在导入服务器配置之前,您首先需要创建一个服务器,这在本文的开始部分就已经描述过。由于该配置适用于5.1版本,因此确保该服务器是WebSphereversion5.1测试环境(在ApplicationDeveloperversion5.1.1中有效)。它还可以帮助您看到服务器列表和配置列表。在Server透视图的ServerConfiguration视图中,点击Menu按钮选择View=>Advanced。高级服务器配置视图菜单ServerGonfipgurat日司况j研目rd顽XAExampleServerAdvanced下一步,通过下列步骤导入服务器配置:从Studio菜单栏中,选择File=>Import。在Select页面中打开Import向导。选择ServerConfiguration并单击Next。向导切换到它的ImportaServerConfiguration页面。在ConfigurationName字段中,输入一个名称,该名称必须不同于您刚才创建的服务器名称,比如“ImportedConfiguration”。Folder字段将是您的服务器项目的缺省名称,通常名为“Servers”。为ConfigurationType选择WebSphereversion5.1=>ServerConfiguration。在Location字段中,单击Browse并选择您已经下载的XAExampleServer.wsc文件。单击Finish以导入服务器配置。ServerConfiguration视图将列出您指定的新配置名称。导入服务器配置对话框现在我们需要切换到您已经创建好的服务器,这样就使用您刚才导入的服务器配置。在ServerConfiguration视图中,选择服务器,弹出上下文菜单(通过点击鼠标右键),选择Switchconfiguration,然后选择您所导入的配置。为您的服务器打开服务器配置编辑器,您将看到它现在已经有了早前描述的JDBC和JMS资源的设置。(如果您没有看到这些设置,请确保将您的服务器切换到导入的配置。)启动服务器,您将看到早前描述的服务器启动日志。回页首设置范例应用程序本文包括了一个J2EE应用程序范例,您可以下载该范例并导入到ApplicationDeveloper,然后运行。它将使用您早前配置的JDBC和JMS资源来执行一个XA事务。在开始之前,下载并解压缩范例文件。它包含一个名为XAExampleEAR.ear的EnterpriseArchive(EAR)文件。按照以下步骤将该文件导入到您的WebSphereStudio工作区:从Studio菜单栏中选择File=>Import。在Select页面中打开Import向导。选择EARfile并单击Next。向导切换到它的EnterpriseApplicationImport页面。在EARFile字段中,单击Browse并选择您所下载的XAExampleEAR.ear文件。项目名称缺省为XAExampleEAR。单击Finish以导入该EAR文件。您的工作区现在将包含三个项目,分别是XAExampleEAR、XAExampleEJB和XAExampleWeb。XAExampleEJB项目包含EJB,因此您必须生成它们的部署代码。选择XAExampleEJB项目,弹出上下文菜单(通过点击鼠标右键),然后选择Generate=>DeploymentandRMICcode。使用该对话框为XAExampleSessionbean生成代码。ApplicationDeveloper将生成一个名称类似于EJSLocalStatelessXAExampleSession_5a0991c7的新类。这是一个具体类,它与WebSphereApplicationServerEJB容器一同工作,使范例EJB实现EJB规范定义的所有特性。您还必须将EAR项目添加倒测试服务器。这类似于部署EAR,但是更灵活一些,因为当您修改EAR的代码时,您不必重新部署EAR以使用新代码。相反,您可以简单的重启服务器或者在运行中的服务器内重启EAR项目并开始测试您对代码的修改。要将EAR项目添加到测试服务器,请在ServerConfigurations视图中选择服务器,弹出上下文菜单(通过点击鼠标右键),然后选择Addandremoveprojects。在该对话框中,将XAExampleEAR添加到已配置项目列表中。在ServerConfiguration视图中展开导入的配置,您将看到该EAR成为配置的一部分。下载的范例中还包含一个名为XAExampleDB.sql的文件,它创建了一个名为XA_EXAMPLE的数据库表。对于Oracle,在SQL*Plus中运行该文件以创建表:SQL>@C:\temp\XAExampleArticle\XAExampleDB.sqlDROPTABLEXA_EXAMPLE*ERRORatline1:ORA-00942:tableorviewdoesnotexistTablecreated.对于DB2,在DB2命令行处理器中运行该文件:C:\db2\SQLLIB\BIN>db2-tvfC:\temp\XAExampleArticle\XAExampleDB.sqlDROPTABLEXA_EXAMPLEDB21034EThecommandwasprocessedasanSQLstatementbecauseitwasnotavalidCommandLineProcessorcommand.DuringSQLprocessingitreturned:SQL0204N"DB2.XA_EXAMPLE"isanundefinedname.SQLSTATE=42704CREATETABLEXA_EXAMPLE(TEXTVARCHAR(256)NOTNULL)DB20000ITheSQLcommandcompletedsuccessfully.范例代码范例应用程序比较简单,它由两个类组成:XAExampleSessionBean--一个执行XA事务的会话EJB。XAExampleServlet--一个调用EJB的servlet。该会话bean的公共方法persistAndSend(String)将参数写入两个JDBC表(DB2和Oracle)和JMS消息中。单独来看这不是一个非常有用的应用程序,但是,由于JDBC和JMS是事务性资源,因此执行所有三个任务是需要XA事务的。分布式(两阶段)事务确保这三个任务可以成功的执行。如果一个任务不能成功提交,其他的任务将回滚,不执行任何任务。这样就维护了两个资源之间的一致性。publicvoidpersistAndSend(Stringdata)throwsException(try(DataSourceoracleDS=getDataSource("java:comp/env/jdbc/OracleXADS");persist(data,oracleDS);DataSourcedb2DS=getDataSource("java:comp/env/jdbc/DB2XADS");persist(data,db2DS);QueueConnectionFactoryfactory=getQueueConnectionFactory(〃java:comp/env/jms/XAExampleQCF〃);Queuequeue=getQueue(〃java:comp/env/jms/XAExampleQ〃);send(data,factory,queue);}catch(Exceptione)(e.printStackTrace();this.getSessionContext().setRollbackOnly();throwe;}该方法执行以下三个步骤:使用名为jdbc/OracleXADS的数据源保持数据。使用名为jdbc/DB2XADS的数据源保持数据。将JMS消息中的数据发送到名为jms/XAExampleQ的队列。如果发生任何错误,批处理块将捕捉该异常,将事务标记为回滚,并重新抛出该异常。为了代码的完整性,以下列出了实现该会话bean的其余代码:privatevoidpersist(Stringdata,DataSourcedatasource)throwsSQLException(System.out.println("Addinganewdatabaserowcontaining:"+data);Connectionconnection=null;try(connection=datasource.getConnection();PreparedStatementstatement=connection.prepareStatement("INSERTINTOXA_EXAMPLE(TEXT)VALUES(?)");statement.setString(1,data);statement.execute();System.out.println("Successfullyaddedrow:"+data);}finally(if(connection!=null)connection.close();privatevoidsend(Stringdata,QueueConnectionFactoryfactory,Queuequeue)throwsJMSException(System.out.println("Sendingamessagecontaining:"+data);QueueConnectionconnection=null;try(connection=factory.createQueueConnection();QueueSessionsession=connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);QueueSendersender=session.createSender(queue);TextMessagemessage=session.createTextMessage(data);sender.send(message);System.out.println("Successfullysentmessage:"+data);}finally(if(connection!=null)connection.close();}}privateDataSourcegetDataSource(StringjndiName)throwsNamingException(return(DataSource)this.getJNDIObject(jndiName);}privateQueueConnectionFactorygetQueueConnectionFactory(StringjndiName)throwsNamingException(return(QueueConnectionFactory)this.getJNDIObject(jndiName);}privateQueuegetQueue(StringjndiName)throwsNamingException(return(Queue)this.getJNDIObject(jndiName);}privateObjectgetJNDIObject(StringjndiName)throwsNamingException(Contextroot=newInitialContext();returnroot.lookup(jndiName);}这是用于使用JDBC和JMS的标准代码。甚至没有任何代码用于定义事务或者将事务变为XA。但由于WebSphereApplicationServer的EJB容器将这些代码作为单独的公共EJB方法来调用,所以容器会在事务中自动运行这些代码。容器将正常使用简单(单阶段)事务,但当第二个事务资源更新时,容器将自动检测,并将简单事务转换为XA事务。作为该工作的一部分,容器将通知资源并为其协调XA事务,让这些资源参与该事务。所有这些行为都是自动完成的,不需要开发人员编写任何额外的代码,而仅仅通过实现EJB中的代码就可以完成。回页首运行范例应用程序当您阅读本文时,最好应该在ApplicationDeveloper中执行这些步骤。如果您是这样做的,那么现在您已经配置了一个测试服务器并安装了范例EAR。现在可以启动服务器以运行该应用程序。在Server透视图中,进入Servers视图。选择您的服务器并单击Start运行它。如果服务器正确运行,您将在控制台看到类似于以下纪录的启动日志:JMSMQJDProvidAMSGS0656I:StartingtheMQJDJMSProviderJMSMQJDProvidAMSGS0650I:MQJDJMSProvideropenforbusinessResourceMgrImIWSVR0049I:BindingXAExampleQCFasjms/XAExampleQCFResourceMgrImIWSVR0049I:BindingXAExampleQasjms/XAExampleQResourceMgrImIWSVR0049I:BindingExampleOracleXADataSourceasjdbc/OracleXADSResourceMgrImIWSVR0049I:BindingExampleDB2XADataSourceasjdbc/DB2XADSCacheServiceIIDYNA0048I:WebSphereDynamicCacheinitializedsuccessfully.・・・ApplicationMgAWSVR0200I:Startingapplication:XAExampleEAREJBContainerIIWSVR0207I:PreparingtostartEJBjar:XAExampleEJB.jarEJBContainerIIWSVR0037I:StartingEJBjar:XAExampleEJB.jarWebContainerASRVE0169I:LoadingWebModule:XAExampleWeb.WebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:JSP1.2Processor:initWebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:SimpleFileServlet:initWebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:InvokerServlet:initApplicationMgAWSVR0221I:Applicationstarted:XAExampleEAR现在我们可以运行范例应用程序。在您的web浏览器中,调用这个URL:http://localhost:9080/XAExampleWeb/XAExampleServlet?data=hello%20world这将使用一个参数调用我们的XAExampleServletservlet,该参数的名称为data,值为“helloworld”。如果一切运行正常,浏览器中将会显示以下结果:Justpersistedandsentdata:helloworld同样,在服务器控制台,您将看到以下一些状态消息:SystemOutOAddinganewdatabaserowcontaining:helloworldSystemOutOSuccessfullyaddedrow:helloworldSystemOutOAddinganewdatabaserowcontaining:helloworldSystemOutOSuccessfullyaddedrow:helloworldSystemOutOSendingamessagecontaining:helloworldSystemOutOSuccessfullysentmessage:helloworld如果所有这些工作都完成,恭喜您,您已经成功运行了一个使用了XA事务的应用程序,该XA事务跨越JDBC和JMS资源。SystemOut范例应用程序的故障诊断有几个潜在的问题可能导致范例的运行不成功。其中两个是部署范例时的常见错误,这很容易改正。另外两个是关于Oracle数据库中的配置问题,这需要OracleDBA来修改。以下部分列出了可能出现的问题,它说明了ApplicationDeveloper控制台显示的异常,给出了关于为什么会发生问题的简短描述,并说明了如何修改每个问题。ClassNotFoundException:EJSStatelessXAExampleSessionHomeBean启动服务器时,如果应用程序成功启动,您将得到这些消息:ApplicationMgAWSVR0200I:Startingapplication:XAExampleEAREJBContainerIIWSVR0207I:PreparingtostartEJBjar:XAExampleEJB.jarEJBContainerIIWSVR0037I:StartingEJBjar:XAExampleEJB.jarWebContainerASRVE0169I:LoadingWebModule:XAExampleWeb.WebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:JSP1.2Processor:initWebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:SimpleFileServlet:initWebGroupISRVE0180I:[XAExampleWeb][/XAExampleWeb][Servlet.LOG]:InvokerServlet:initApplicationMgAWSVR0221I:Applicationstarted:XAExampleEAR然而,您也可能会得到以下错误:ApplicationMgAWSVR0200I:Startingapplication:XAExampleEAREJBContainerIIWSVR0207I:PreparingtostartEJBjar:XAExampleEJB.jarBeanMetaDataECNTR0075E:Theuser-providedclass"com.ibm.example.xa.EJSStatelessXAExampleSessionHomeBean_5a0991c7"neededbytheEnterpriseBeancouldnotbefoundorloaded.EJBContainerIEWSVR0209E:UnabletoprepareEJBjarXAExampleEJB.jar[ponent.DeployedModuleImpl],enterprisebeancom.ibm.etools.ejb.impl.SessionImpl(XAExampleSession)(transactionType:Container,sessionType:Stateless)java.lang.ClassNotFoundException:com.ibm.example.xa.EJSStatelessXAExampleSessionHomeBean_5a0991c7atcom.ibm.ws.classloader.CompoundClassLoader.findClass(CompoundClassLoader.java:351)atcom.ibm.ws.classloader.CompoundClassLoader.loadClass(CompoundClassLoader.java:261)atjava.lang.ClassLoader.loadClass(ClassLoader.java(CompiledCode))atcom.ibm.ejs.container.BeanMetaData.loadExistedClass(BeanMetaData.java:2573)atcom.ibm.ejs.container.BeanMetaData.<init>(BeanMetaData.java:888)ponent.EJBContainerImpl.createBeanMetaData(EJBContainerImpl.java:980)...DeployedAppliWWSVR0206E:Module,XAExampleEJB.jar,ofapplication,XAExampleEAR.ear/deployments/XAExampleEAR,failedtostartApplicationMgWWSVR0101W:Anerroroccurredstarting,XAExampleEARApplicationMgAWSVR0217I:Stoppingapplication:XAExampleEARApplicationMgAWSVR0220I:Applicationstopped:XAExampleEAR该错误是ClassNotFoundException,缺少的类是com.ibm.example.xa.EJSStatelessXAExampleSessionHomeBean_5a0991c7。该错误发生在试图启动EJBjarXAExampleEJB.jar的时候。该错误指出了您没有生成EJB代码,因此容器无法为XAExampleSessionbean找到所生成的Home类。要修改该问题,请先在指定的EJB项目中为所有的bean生成DeploymentandRMICcode,然后重新启动服务器。SQLException:Tableorviewdoesnotexist在第一次运行范例时,您可能会得到以下错误:WSRdbDataSourIDSRA8203I:Databaseproductname:OracleWSRdbDataSourIDSRA8204I:Databaseproductversion:PersonalOracle9iRelease.0-ProductionWiththePartitioning,OLAPandOracleDataMiningoptionsJServerRelease.0-ProductionWSRdbDataSourIDSRA8205I:JDBCdrivername:OracleJDBCdriverWSRdbDataSourIDSRA8206I:JDBCdriverversion:.0WebGroupESRVE0026E:[ServletError]-[ORA-00942:tableorviewdoesnotexist]:java.sql.SQLException:ORA-00942:tableorviewdoesnotexistatoracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)atoracle.jdbc.ttc7.TTIcessError(TTIoer.java:289)atoracle.jdbc.ttc7.Oall7.receive(Oall7.java:573)atoracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1891)atoracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1093)atoracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2047)atoracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1940)atoracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2709)atoracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:589)atoracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:656)atcom.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.execute(WSJdbcPreparedStatement.java:386)atcom.ibm.example.xa.XAExampleSessionBean.persist(XAExampleSessionBean.java:45)atcom.ibm.example.xa.XAExampleSessionBean.persistAndSend(XAExampleSessionBean.java:30)atcom.ibm.example.xa.EJSLocalStatelessXAExampleSession_5a0991c7.persistAndSend(EJSLocalStatelessXAExampleSession_5a0991c7.java:23)atXAExampleServlet.persistAndSend(XAExampleServlet.java:44)atXAExampleServlet.doGet(XAExampleServlet.java:28)atjavax.servlet.http.HttpServlet.service(HttpServlet.java:740)atjavax.servlet.http.HttpServlet.service(HttpServlet.java:853)该错误是SQLException,错误代码为ORA-00942。很显然,是因为期望的数据库表或视图不存在。但是,该错误没有说明具体是哪个表或视图未找到。栈跟踪显示该错误发生在一XAExampleSessionBean.persist方法中,它位于.java文件的第45行。点击那个栈跟踪行,编辑器将进入该代码的execute行:PreparedStatementstatement=connection.prepareStatement("INSERTINTOXA_EXAMPLEVALUES(?)");statement.setString(1,data);statement.execute();该问题发生在向XA_EXAMPLE表中插入纪录的时候。这说明您没有运行创建数据库表的SQL文件。要修改该问题,请运行SQL文件:SQL>@C:\workspace\XAExampleEJB\XAExampleDB.sql现在重新运行范例。OracleXAException:XAER_RMERR(InternalXAError)在第一次运行范例时,您可能会得到以下错误:WSRdbDataSourIDSRA8203I:Databaseproductname:OracleWSRdbDataSourIDSRA8204I:Databaseproductversion:PersonalOracle9iRelease.0-ProductionWiththePartitioning,OLAPandOracleDataMiningoptionsJServerRelease.0-ProductionWSRdbDataSourIDSRA8205I:JDBCdrivername:OracleJDBCdriverWSRdbDataSourIDSRA8206I:JDBCdriverversion:.0WSRdbXaResourEDSRA0304E:XAExceptionoccurred.XAExceptioncontentsanddetailsare:TheXAErroris:-3TheXAErrormessageis:Aresourcemanagererrorhasoccurredinthetransactionbranch.TheOracleErrorcodeis:65535TheOracleErrormessageis:InternalXAErrorThecauseis:null.WSRdbXaResourEDSRA0302E:XAExceptionoccurred.Errorcodeis:XAER_RMERR.Exceptionis:<null>RegisteredResEWTRN0078E:Anattemptbythetransactionmanagertocallstartonatransactionalresourcehasresultedinanerror.TheerrorcodewasXAER_RMERR.Theexceptionstacktracefollows:oracle.jdbc.xa.OracleXAExceptionatoracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1157)atoracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:295)atcom.ibm.ws.rsadapter.spi.WSRdbXaResourceImpl.start(WSRdbXaResourceImpl.java:927)atcom.ibm.ejs.j2c.XATransactionWrapper.start(XATransactionWrapper.java:1267)atcom.ibm.ws.Transaction.JTA.JTAResourceBase.start(JTAResourceBase.java:164)atcom.ibm.ws.Transaction.JTA.RegisteredResources.startRes(RegisteredResources.java:389)atcom.ibm.ws.Transaction.JTA.TransactionImpl.enlistResource(TransactionImpl.java:1903)atcom.ibm.ws.Transaction.JTA.TranManagerSet.enlist(TranManagerSet.java:494)该错误是因为事务管理程序不能将事务转换为XA事务。Oracle明确的返回错误XAER_RMERR,错误代码编号为65535。ORA-65535不是一个有效错误代码,并且XAER_RMERR实质上意味着XA发生了某些错误。这说明您的Oracle数据库没有被配置为支持XA事务。因此,当WebSphereApplicationServer事务管理程序命令Oracle事务管理程序参与这个XA事务时,Oracle拒绝该命令并抛出这个异常。解决方法是运行Oracle安装中包含的两个脚本。这很可能需要通过您的OracleDBA来执行,您必须以SYSOPER或SYSDBA身份登录到Oracle,以拥有足够的权限来运行这些脚本。这些脚本是:directory:<ORACLE_HOME>\javavm\installofile:initxa.sqlofile:initjvm.sqlinitxa.sql脚本配置XA数据库。一旦它成功运行,您的数据库就被配置为XA。该脚本在您第一次运行的时候可能成功。不幸的是,由于一些数据库的内存空间太小,该脚本也可能无法成功运行。为修改该问题,运行initjvm.sql脚本。它可能也会运行失败,但是在失败时,该脚本会说明哪个参数需要调整。参数被保存在该文件中:directory:<ORACLE_HOME>\databaseo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- DB32/T 4556-2023药品生产检验结果超标调查指南
- DB32/T 4521-2023乌鳢池塘健康养殖技术规程
- DB32/T 4470-2023道路干法废胎颗粒沥青混合料应用技术规程
- DB32/T 4432-2022视频监控联网信息安全自动化漏洞扫描技术规范
- 租赁合同书(场地)
- DB32/T 4370-2022危险废物综合利用与处置技术规范通则
- DB32/T 4272-2022医用超声测量用水处理指南
- DB32/T 3847-2020用电场所智慧安全监控系统技术规范
- DB32/T 3761.9-2020新型冠状病毒肺炎疫情防控技术规范第9部分:职业健康技术服务机构
- DB32/T 3643-2019气压劈裂真空预压加固软土地基技术规程
- 雷雨剧本文件完整版电子书下载
- 外墙保温施工考核试卷
- 除颤仪使用的试题及答案
- 储料仓施工方案
- 风机叶片故障诊断-深度研究
- 新版统编版七年级下册道德与法治四单元课件 11.1 法不可违
- 烧烤店员工培训
- 2025年全球及中国智能艾灸服务机器人行业头部企业市场占有率及排名调研报告
- 大学生创新创业教育课件
- 连云港市农商控股集团限公司2025年专业技术人员招聘高频重点提升(共500题)附带答案详解
- 甘肃省陇南市武都区2024-2025学年八年级上学期期末学业水平测试历史试题(含答案)
评论
0/150
提交评论