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.pswp.cn/news/371542.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371542.shtml
英文地址,請注明出處:http://en.pswp.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 …