天天看點

用 JOTM 向Servlet中添加事務

  原子性:事務的操作,或者是全部成功(此時送出事務),或者是全部不成功(此時復原事務),謂之為 all-or-nothing 屬性。一個事務應該被視為單個工作單元,在一個事務裡面絕對不可能同時存在完成了的和沒有完成的操作。

  一緻性:完成了的事務将資源從一個有效狀态轉變為另一個有效狀态。一緻性的具體例子有:資料庫的參照完整性和表中的主鍵唯一性。

  獨立性在事務沒有送出之前,事務作用的共享資源的改變在事務之外是不可見的。獨立性確定了不同僚務不會同時通路正在更新的資料。

  持久性:由事務送出的改變會永久存在。

  為了突出事務是怎樣增強 web 應用程式的,舉一個常用的例子, web 浏覽器與用戶端互動的 ATM 。

  ATM 樣例:

  情景

  此例比較簡單:一個客戶想從 ATM 提款,輸入了他的客戶名稱,john_doe;想提款數,$50。如果他的銀行帳戶上有足夠的錢并且在 ATM 機上有足夠的現金的話,應用程式就能給他相當數目的現金,并從銀行帳戶上提出同樣的數目。否則,操作中斷,并且除出現錯誤資訊之外,其他都不會改變。我們無需擔心安全問題,隻是在猜想使用者是否正确授權。

  這是一個非常簡單的例子,但是如果不使用事務,用别的方法執行起來将會很難。用戶端操作将會涉及到兩個不同的資源:ATM 和客戶銀行帳号。它們會自動的在應用程式設計中産生 ACID 問題。例如:如果在 ATM 上操作成功而在銀行帳戶上卻失敗(也許是因為交流失敗),客戶将會取到錢,但是他的帳戶将不會更新。對于銀行來說,這就虧大了。更糟的是,如果銀行帳戶更新了,但是由于一個錯誤阻止 ATM 傳送錢,客戶得不到現金,但是帳戶上卻提掉了這筆款。

  為了防止出現上述事故,在你的應用程式裡,你能夠 1) 聯系兩個資源,并告知兩者客戶執行的所有目前操作,2) 詢問兩者是否能執行操作,3)如果兩者都同意,則請求操作。即使這樣,此方法也不能謂之足夠健壯,因為,如果客戶帳戶上的錢在第二步和第三步的時候被另外一操作提走,提款可能會失敗,例如,客戶帳戶不能出現逆差。

  事務能使應用程式更簡單更健壯的之處就是:在同一事務的兩個資源上執行所有的操作的時候,它将會解決 ACID 的問題(尤其是原子性)。

  應用程式設計

  資料層:在資料層,有兩個不同的資料庫,并各自有一張表。為了使例子更接近實際,我們使用兩個不同的資料庫,因為有可能從 ATM 提走不是屬于該客戶帳戶的款(請參見下文配置資料庫)。

  banktest 包含代表客戶帳号的 account 表。

  atmtest包含代表 ATM 的 atm 表。

  邏輯層:在邏輯層,有三個類來通路資源和執行操作:

  foo.BankAccount 代表給定客戶的銀行帳号 account,并能通過 JDBC在 account 執行資料庫操作。

  bar.ATM 代表 ATM,并在 atm 表上執行 JDBC 操作。

  bar.CashDelivery 使用前面兩個類來執行一個客戶操作。

  所有邏輯在 CashDelivery.java 的 deliverCash 方法中實作。

  javax.transaction.UserTransaction 接口用于劃分事務所有 utx.begin() 和 utx.commit() (或 utx.rollback())之間的操作在同一事務内執行。這確定了應用程式不會受到如前述的遭遇。

  事務使得應用程式更為簡單,由以下簡單的步驟組成:

  1. 開始事務。

  2. 聯系客戶的銀行帳戶并從帳戶上提款。

  3. 告訴 ATM 傳送錢。

  4. 完成事務:如果所有事件完成,送出事務。否則,復原事務。

  5. 報告客戶事務結果。如果事務成功,現金将被提出,錢數也将從帳戶上提出。否則,一切都不會改變。

例1. CashDelivery.java

  表示層:在表示層,就用程式由兩個 JSP 檔案組成:

  atm.jsp, 應用程式,它發送給bar.CashDelivery 類客戶登入和提款數目,并顯示客戶操作的結果 。

  admin.jsp,,用于顯示和更新兩個資源的資訊。(它不屬于應用程式設計的部分,但是添加它來簡化資源更新,比如處理客戶帳戶的錢數。)

圖1 應用程式設計

  配置資料庫

  已配置了一個 MySQL 的例子,使用者名為 javauser,密碼為 javadude。確定該使用者已被建立并且擁有建立資料庫的權限。

  建立資料庫和表的腳本在 scripts/ 目錄下的 example file 内含有。它将建立一個 account 表并插入兩個客戶:john_doe 他的帳戶金額為 $100。jane_doe 他的帳戶金額為 $600。

例2 建立 account 表

腳本還會建立有 $500 可用現金的 atm 表。

例3 建立 atm 表

  最後,複制 $CATALINA_HOME/shared/lib 内的 JDBC 驅動程式 .jar 檔案。

  擷取并安裝 TOMCAT:本章主要介紹 Tomcat 4.1.18 及以上的版本。首先確定沒有使用以前的舊版本,安裝 TOMCAT 沒有什麼特别,隻需下載下傳并解壓縮即可。

  擷取并安裝 JOTM:如果要使用 JOTM,隻需要下載下傳最近的二進制版本并将解壓縮即可。再從lib/ 目錄下将.jar 檔案(除了 log4j.jar、ommons-cli.jar 和 jotm_iiop_stubs.jar) 複制到 $CATALINA_HOME/shared/lib。這樣就完成了。

  配置 TOMCAT:需要配置 Tomcat,使之能夠從 JNDI 擷取 UserTransaction 和 DataSource 對象(它們用在 foo.BankAccount 和 bar.ATM)。

  首先,告訴 TOMCAT 你所使用的 JNDI 名字,以便在 WEB 應用程式中查詢資料源。這些步驟由 web.xml 完成,其代碼如下。對于銀行帳戶資料源,使用的 JNDI 名字是 java:comp/env/jdbc/bankAccount ,而且隻能在 java:comp/env/ 之後給出名字。TOMCAT 通過 JNDI 機制來解決其餘的問題。對于 ATM 資料源也同樣于此。

例 4. web.xml

  您必須告訴 TOMCAT 怎麼樣傳回 web.xml内的資源,這個過程就由bank.xml檔案來完成了。對于銀行帳戶和 ATM 資源,您必須設定參數,以便 TOMCAT 能将 WEB 應用程式與資料源正确相連。有關更多的詳細資訊,請參考 TOMCAT JNDI 資料源基礎知識。(參見 Resources)

  其中一個參數需特别關注:factory.類中設定這個參數,用于當 WEB 應用程式通過 JNDI 查詢時來建立一個資料源。另外一個重要的資源(在 web.xml 中有描述)是 UserTransaction。java:comp/UserTransaction 使用這個資源來區分事務,它由 JOTM 來執行。

例 5 bank.xml

  展開 WEB 應用程式:一旦你設定了 JOTM 和TOMCAT ,展開并使用 WEB 應用程式就很容易了。首先,下載下傳 bank.tgz 并将之解壓縮, 再将bank.xml 和 bank.war 複制到 $CATALINA_HOME/webapps 下;然後,啟動 TOMCAT:

您會在日志裡面發現 JOTM 還沒有啟動。它是在當您第一次通路 DataSource 時才會啟動的,在那個時候,您将會發現以下資訊:

  使用 WEB 應用程式

  WEB 應用程式的首頁包含兩個連結:

  1. 是 Cash Delivery 頁面,您可以在上面像在 ATM 一樣提款。

圖2 Cash Delivery 頁面

  2. 是management console,您在上面可以對 ATM 或自己建立的銀行帳戶進行檢測或更新。

圖3 Management Console

操作之前,ATM 有$500,John Doe 銀行帳戶上有 $100 ,Jane Doe 銀行帳戶有 $600 。

如果 John Doe想取 $400 ,交易将會失敗,因為在他的帳戶上餘額不夠。結果将是:

Client ID:john_doe, value: $400

Cash can not be delivered to you

because:not enough money in your account (only $100).

如果 Jane Doe想取 $550 ,交易也會失敗,因為ATM上的現金不夠。結果将是:

Client ID:jane_doe, value: $550

because:not enough cash available from this ATM (only $500).

如果 John Doe 取 $50 的話,交易将會成功。結果将是:

Client ID:john_doe, value: $50

Please take your cash ($50)

Thank you!

  總結

  這個簡單的例子證明了 servlet 是怎樣通過使用事務提供健壯和簡化的,并且確定在任何情況下都正确。Tomcat 和 JOTM 完美的結合使在 servlet 内能輕而易舉的取得事務的優勢。

  除上述簡單的例子以外,JOTM還有更多的優點。JOTM 提供了以下性能,有助于增強 WEB 應用程式。

  1.完全分布式事務支援.如果資料層、業務層、表示層運作在不同的 JVM 上,則有可能有一個全程的事務跨度這些JVM,事務的内容在 RMI/JRMP 和 RMI/IIOP 上傳播。

  2.整合 JDBC。使用的 XAPool例子就是一個 XA-相容的 JDBC 連接配接池,可以與資料庫互相操作。XAPool 類似于 Jakarta DBCP,隻是增加了 XA-相容的特征,如果要結合 JDBC 使用 JTA 事務就必須遵從這個特征。

  3.整合 JMS。JOTM 可以結合 JORAM,由ObjectWeb 協會開發的“JMS 提供者”提供了事務的 JMS 消息。你可以得到出現在 servlet中同一事務的 JMS 消息發送件和更新的資料庫。

  4.WEB 服務事務。JOTM 提供了BTP(Business Transaction Protocol)、JOTM-BTP接口,它們用于在 WEB 服務中增加事務行為。

  所有這些功能的樣例和文檔都可以在 JOTM 的檔案和網站上找到。