Play 2.0框架和XA交易

XA事务非常有用,而且开箱即用,今天的Play 2.0不支持它们。 在这里,我展示了如何添加该支持:

首先,介绍一些XA有用的示例:

–如果您使用来自两个不同persistence.xml的实体,则JPA使用两个物理连接–这两个连接可能需要在一个事务中提交,因此XA是您唯一的选择
–提交数据库更改,同时向JMS提交消息。 例如,您想保证在成功将订单异步提交到数据库后发送了一封电子邮件。 还有其他方法,但是JMS提供了一种事务性的方法来完成此任务,而不必考虑故障。 –由于多种政治原因(遗留系统,负责不同数据库服务器的不同部门/不同预算)中的任何原因而写入物理上不同的数据库。 –请参阅http://docs.codehaus.org/display/BTM/FAQ#FAQ-WhywouldIneedatransactionmanager

因此,从我的角度来看,XA是Play需要“支持”的东西。

添加支持非常容易。 我创建了一个基于Bitronix的播放插件。 资源是在Bitronix JNDI树中配置的(为什么Play会使用配置文件而不是JNDI ?!无论如何...)您可以使用“ withXaTransaction”启动事务:

def someControllerMethod = Action {withXaTransaction { ctx =>TicketRepository.addValidation(user.get, bookingRef, ctx)ValidationRepository.addValidation(bookingRef, user.get, ctx)}val tickets = TicketRepository.getByEventUid(eventUid)Ok(views.html.ticketsInEvent(eventUid, getTickets(eventUid), user, eventValidationForm))}

ctx对象是XAContext(我自己的类),它使您可以查找资源(如数据源),或在发生故障时设置回滚。 因此,验证存储库使用ScalaQuery(我使用“ withSession”而不是“ withTransaction!”)来完成此操作:

def addValidation(bookingRef: String, validator: User, ctx: XAContext) = {val ds = ctx.lookupDS("jdbc/maxant/scalabook_admin")Database.forDataSource(ds) withSession { implicit db: Session =>Validations.insert(Validation(bookingRef, validator.email, new java.sql.Timestamp(now)))}}

票务回购使用JMS执行以下操作:

def addValidation(user: User, bookingRef: String, ctx: XAContext) = {val xml = {bookingRef}{user.email}val qcf = ctx.lookupCF("jms/maxant/scalabook/ticketvalidations")val qc = qcf.createConnection("ticketValidation","password")val qs = qc.createSession(false, Session.AUTO_ACKNOWLEDGE)val q = qs.createQueue("ticketValidationQueue") //val q = ctx.lookup(QUEUE).asInstanceOf[Queue]val sender = qs.createProducer(q)val m = qs.createTextMessage(xml.toString)sender.send(m)sender.closeqs.closeqc.close}

我已经通过编写MySQL并将JMS消息发送给JBoss(HornetQ)进行了测试,它似乎运行良好(除了让hornetQ与Bitronix一起玩是个bit子-参见此处: https ://community.jboss.org/ 线程/ 206180?tstart = 0 )。

XA支持的scala代码为:

package ch.maxant.scalabook.play20.plugins.xasupportimport play.api.mvc.RequestHeader
import play.api.mvc.Results
import play.api.mvc.Request
import play.api.mvc.AnyContent
import play.api.mvc.Result
import play.api.mvc.Action
import play.api.mvc.Security
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import ch.maxant.scalabook.persistence.UserRepository
import bitronix.tm.TransactionManagerServices
import java.util.Hashtable
import javax.naming.Context._
import javax.naming.InitialContext
import javax.sql.DataSource
import bitronix.tm.BitronixTransaction
import java.io.File
import org.scalaquery.session.Database
import org.scalaquery.SQueryException
import scala.collection.mutable.ListBuffer
import java.sql.Connection
import java.sql.SQLException
import org.scalaquery.session.Session
import bitronix.tm.BitronixTransactionManager
import javax.jms.ConnectionFactoryclass XAContext {private val env = new Hashtable[String, String]()env.put(INITIAL_CONTEXT_FACTORY, "bitronix.tm.jndi.BitronixInitialContextFactory")private val namingCtx = new InitialContext(env);var rollbackOnly = falsedef lookup(name: String) = {namingCtx.lookup(name)}def lookupDS(name: String) = {lookup(name).asInstanceOf[DataSource]}def lookupCF(name: String) = {lookup(name).asInstanceOf[ConnectionFactory]}
}trait XASupport { self: Controller =>private lazy val tm = play.api.Play.current.plugin[XASupportPlugin] match {case Some(plugin) => plugin.tmcase None => throw new Exception("There is no XASupport plugin registered. Make sure it is enabled. See play documentation. (Hint: add it to play.plugins)")}/*** Use this flow control to make resources used inside `f` commit with the XA protocol.* Conditions: get resources like drivers or connection factories out of the context passed to f.* Connections are opened and closed as normal, for example by the withSession flow control offered * by ScalaQuery / SLICK.*/def withXaTransaction[T](f: XAContext => T): T = {tm.begin//get a ref to the transaction, in case when we want to commit we are no longer on the same thread and TLS has lost the TX.//we have no idea what happens inside f!  they might spawn new threads or send work to akka asynclyval t = tm.getCurrentTransactionLogger("XASupport").info("Started XA transaction " + t.getGtrid())val ctx = new XAContext()var completed = falsetry{val result = f(ctx)completed = trueif(!ctx.rollbackOnly){Logger("XASupport").info("committing " + t.getGtrid() + "...")t.commitLogger("XASupport").info("committed " + t.getGtrid())}result}finally{if(!completed || ctx.rollbackOnly){//in case of exception, or in case of set rollbackOnly = trueLogger("XASupport").warn("rolling back (completed=" + completed + "/ctx.rollbackOnly=" + ctx.rollbackOnly)t.rollback}}}
}class XASupportPlugin(app: play.Application) extends Plugin {protected[plugins] var tm: BitronixTransactionManager = nulloverride def onStart {//TODO how about getting config out of jar!val file = new File(".", "app/bitronix-default-config.properties").getAbsolutePathLogger("XASupport").info("Using Bitronix config at " + file)val prop = System.getProperty("bitronix.tm.configuration", file) //defaultSystem.setProperty("bitronix.tm.configuration", prop) //override with default, if not set//start the TMtm = TransactionManagerServices.getTransactionManagerLogger("XASupport").info("Started TM with resource config " + TransactionManagerServices.getConfiguration.getResourceConfigurationFilename)}override def onStop {//on graceful shutdown, we want to shutdown the TM tooLogger("XASupport").info("Shutting down TM")tm.shutdownLogger("XASupport").info("TM shut down")}}

随便使用代码,我免费提供它:-)如果不起作用,请不要抱怨;-)

看到此插件扩展并将其转换成更多生产版本,真是太好了。 Play更好地原生支持事务管理器,包括从JNDI中获取资源。

祝您编程愉快,别忘了分享!

参考:来自Zoo博客The Kitchen的 JCG合作伙伴 Ant Kutschera的Play 2.0框架和XA事务 。


翻译自: https://www.javacodegeeks.com/2012/10/play-20-framework-and-xa-transactions.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java代码注释规范

java代码注释规范 一、规范存在的意义 应用编码规范对于软件本身和软件开发人员而言尤为重要,有以下几个原因:1、好的编码规范可以尽可能的减少一个软件的维护成本 , 并且几乎没有任何一个软件,在其整个生命周期中,均由最初的开…

win10 hyper-v 虚拟机ping不通宿主机问题

在Windows10 Hyper-V 中安装 Linux (Centos6.9)虚拟机无法 ping 通宿主机 这种情况下关闭 Windows 防火墙就能ping通了,当然关闭防火墙不安全。所以需要 做以下步骤: 控制面板-》系统和安全-》Windows防火墙-》高级设置-》入站规则 启用下图被红框选中的两个选…

linux方法参数,Linux的sysctl 命令 参数

Linux内核通过/proc虚拟文件系统向用户导出内核信息,用户也可以通过/proc文件系统或通过sysctl命令动态配置内核。比如,如果我们想启动NAT,除了加载模块、配置防火墙外,还需要启动内核转发功能。我们有三种方法:1. 直接…

Java枚举:您拥有优雅,优雅和力量,这就是我所爱!

当Java 8即将面世时,您确定您对Java 5中引入的枚举很了解吗? Java枚举仍然被低估了,很可惜,因为它们比您想象的要有用,它们不仅仅用于通常的枚举常量! Java枚举是多态的 Java枚举是可以包含行为甚至数据的…

C#删除和清空文件夹的程序

/// <summary>/// 清空指定的文件夹&#xff0c;但不删除文件夹/// </summary>/// <param name"dir"></param>private void DeleteFolder(string dir){foreach (string d in Directory.GetFileSystemEntries(dir)){if (File.Exists(d)){try{…

2)网页请求顺序

&#xff08;1&#xff09;分析浏览器访问一个网页的完整流程逻辑过程&#xff1a;http&#xff1a;//www.abc.com/def/ 转载于:https://www.cnblogs.com/xiaoyoucai/p/7306246.html

JavaOne 2012:非阻塞数据结构如何工作?

当我查看今天的日程安排时&#xff0c;我感到有些惊讶&#xff0c;并指出我目前计划今天参加的所有会议都在希尔顿举行。 当我意识到JavaOne演示文稿中大约有一半是在希尔顿酒店中并且似乎按路线大致定位时&#xff0c;这变得有些不足为奇了。 Tobias Lindaaker &#xff08; 新…

c语言箭头指针的作用,C语言中,结构体成员变量的点和箭头

C语言中&#xff0c;调用成员变量用点还是用箭头&#xff0c;取决于当前的ID是指针还是结构体本身。如&#xff1a;typedef struct {float height;float weight;} Person;int main(int argc, char *argv[]) {Person jiushen;Person *lengleng (Person *)malloc(sizeof(Person)…

JavaOne 2012:调查JVM水晶球

我回到了希尔顿的A / B广场参加星期一的第四届会议&#xff0c;但首先去了希尔顿的顶层收拾午餐。 我每年都在JavaOne的第一天被提醒&#xff0c;涉及到每个人的第一天的午餐获取过程令人惊讶地令人沮丧。 我知道我在JavaOne的第一年的经历使我有些困惑&#xff0c;因为我不确定…

测试遇到的问题

多人合作测试 多人员合作测试&#xff0c;应尽量保证测试平台统一&#xff0c;处理流程统一&#xff0c;相互之间保持实时沟通。问题的处理进度应保证所负责的所有测试人员第一时间实时更新。 多人测试应做到2人或以上进行交叉测试。 转载于:https://www.cnblogs.com/liuliu-wo…

Jquery Memo

jQuery选择器 $( "#id" ) $( ".class" )$( "element" )全选择器&#xff08;*选择器&#xff09; * {padding: 0; margin: 0;}//子选择器 //$(div > p) 选择所有div元素里面的子元素P//后代选择器 //$(div p) 选择所有div元素…

c#语言输出字符串长度,C#统计字符长度(汉字占2个字符)

在C#编程过程中&#xff0c;通过String类的Length属性可以获取对应字符串的长度&#xff0c;但是细心的读者可能注意到了&#xff0c;String类的Length属性返回的是字符串中Char对象的个数&#xff0c;也就是说&#xff0c;一个汉字的长度为1&#xff0c;对此&#xff0c;MSDN的…

使用JMSTester对JMS层进行基准测试

对于我去过的大多数客户端&#xff0c;使用ActiveMQ扩展JMS消息传递层是一个优先事项。 有多种方法可以实现这一目标&#xff0c;但毫无疑问&#xff0c;创建基准测试并在实际硬件上分析架构&#xff08;或者正如我的同事Gary Tully所说的“询问机器”&#xff09;是第一步。 但…

Js引擎解析执行 阅读笔记

Js引擎解析执行 阅读笔记 一篇阅读笔记http://km.oa.com/group/2178/articles/show/145691?kmrefsearch&from_page1&no1 早期:遍历语法树 Js引擎最早使用的是遍历语法树方式 &#xff08;syntax tree walker&#xff09; 分为两步 词法分析语法分析词法分析 i a b *…

红外线遥控c语言程序,红外遥控的C程序

红外遥控在生产和生活中应用越来越广泛,不同的红外遥控芯片有不同的发码协议,但一般都是由引导码,系统码,键码三部分组成.引导码是告诉接收机准备接收红外遥控码.系统码是识别码,不同的遥控芯片有不同的误别码,以免搞错.遥控器上不同的按键有不同的键码,系统码和键码都是16位码…

Retrofit2 完全解析 探索与okhttp之间的关系

转载请标明出处&#xff1a; http://blog.csdn.net/lmj623565791/article/details/51304204&#xff1b; 本文出自:【张鸿洋的博客】 之前写了个okhttputils的工具类&#xff0c;然后有很多同学询问这个工具类和retrofit什么区别&#xff0c;于是上了下官网&#xff0c;发现其底…

不变性真的意味着线程安全吗?

我经常阅读有关“如果对象是不可变的&#xff0c;则它是线程安全的”的文章。 实际上&#xff0c;我从未找到过一篇让我相信不变的意味着线程安全的文章。 即使是Brian Goetz的Java Concurrency in Practice一书中关于不变性的一本书也没有完全令我满意。 在这本书中&#xff0…

c语言设计 数组的知识点,C语言程序设计知识点及示例.pdf

C语言程序设计知识点及示例四川大学锦江学院C语言程序设计知识点及示例知识点1&#xff1a;除了复合语句而外&#xff0c;C语言的语句都以分号结束。示例1&#xff1a;C语言的简单语句 (非复合语句语句)必须以 结束。参考答案&#xff1a;分号知识点2&#xff1a;目标程序和可执…

移动端知识汇总

参见地址: https://github.com/jtyjty99999/mobileTech 转载于:https://www.cnblogs.com/duanyue/p/7337789.html

在移动端设置overflow:hidden禁止滚动的解决方法

如果你是将overflow:hidden用在了body上那么不管用&#xff0c;因为移动端是基于touch事件。 两种解决方法&#xff1a; 1、为html和body同时设置height:100%;overflow:hidden; html, body{height:100%;overflow:hidden; }2、使用touchmove $(document).on(touchmove,function …