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

Play 2.0框架和XA交易相关推荐

  1. Ext2.0框架的Grid使用介绍(转)

     Ext2.0框架的Grid使用介绍 最近空闲时间在学习Ext2.0框架,只有一个字的感叹"强",我从未想到JS代码能够写出这么绚丽的Web页面出来,以前看到YUI,惊若天人,如今 ...

  2. yii2.0框架中自定义接口,实现类的多继承

    一.前言 最近有个需求,比如有A,B,C,D四个文件,原来的逻辑是,A继承B,C继承D.后来由于A和C的逻辑太像,既然如此的话,为什么不把A,C写一起呢,第一是方便维护,第二也是减少无用的代码,说干就 ...

  3. 在ASP.NET AJAX 1.0框架中访问Web服务

    一. 简介     如今,微软最新推出的AJAX框架为ASP.NET AJAX 1.0(下载地址为[url]http://ajax.asp.net/downloads/default.aspx[/ur ...

  4. 使用ASP.NET AJAX 1.0框架PreviewGlitz进行网页动画编程

    一.引言 微软最新推出的AJAX框架为ASP.NET AJAX 1.0(下载地址为[url]http://ajax.asp.net/downloads/default.aspx[/url]),此框架由 ...

  5. IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API

    IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...

  6. php实现多条件查找分页,Yii2.0框架实现带分页的多条件搜索功能示例

    本文实例讲述了Yii2.0框架实现带分页的多条件搜索功能.分享给大家供大家参考,具体如下: 方法一 在控制器中 public function actionShow(){ $where['title' ...

  7. 应梦框架9.0框架_.Net框架能力问题和解答

    应梦框架9.0框架 This section contains Aptitude Questions and Answers on .Net Framework. 本节包含有关.Net Framewo ...

  8. EJB3.0框架实例----区分有状态bean和无状态bean

    1.通过这个例子可以区分,有状态bean和无状态bean中的数据会不会混淆; 2.一种取巧的做法是:在建立的客户端的工程上右键,选择build path--->把服 务端的EJB工程导入的,新建 ...

  9. 入口文件到控制器 php,tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析...

    本文实例讲述了tp5.0框架隐藏index.php入口文件及模块和控制器的方法.分享给大家供大家参考,具体如下: 1. 隐藏入口文件: [ IIS ] 在IIS的高版本下面可以配置web.Config ...

最新文章

  1. 一文读懂傅立叶变换处理图像的原理
  2. anconda安装后命令行中安装tensorflow报错
  3. Java设计模式(代理模式-模板方法模式-命令模式)
  4. 【宽搜】XMU 1039 Treausure
  5. python过去日期_利用python获取当前日期前后N天或N月日期的方法示例
  6. 内核探测工具systemtap简介
  7. django默认数据库sqlite3改为mysql
  8. Python自然语言处理学习笔记(19):3.3 使用Unicode进行文字处理
  9. rabbitmq技术的一些感悟(二)
  10. vue设置输入框输入长度_Vue实现input宽度随文字长度自适应操作
  11. python入门经典100题-零基础学习Python开发练习100题实例(1)
  12. 三、地址族与数据序列
  13. 一个表可以建几个索引_一个人失业在家,可以做哪些挣钱的小生意?推荐几个供参考...
  14. 虚拟机安装python包会出问题吗_虚拟机CentOS7安装python3.6.2及requests模块的问题汇总...
  15. [CSS]关于Flexbox
  16. 华为笔试题 字符串解压缩(C语言解法)
  17. 床长人工智能教程 - 前言
  18. 内外网同时使用-路由配置
  19. STM32 通过定时器产生PPM信号
  20. 中学生应具备的良好的学习习惯

热门文章

  1. java异常——分析堆栈跟踪元素+使用异常机制的技巧
  2. 简单的hibernate环境搭建、自动生成model/配置/hibernate.xml配置文件
  3. 查看oracle会话和进程_带有Oracle Digital Assistant和Fn Project的会话式UI。 第三部分,迁移到云...
  4. 机器学习java_如何开始使用Java机器学习
  5. tdd java_Java TDD简介–第1部分
  6. gradle排除依赖_如何从Gradle中的所有依赖项中排除库
  7. spring可用于数据层吗_Spring XD用于数据提取
  8. java基准测试_星期五基准功能Java
  9. CUBA 7的新功能
  10. javafx 自定义控件_JavaFX自定义控件– Nest Thermostat第3部分