來源:Programming an Oracle Tuxedo Application Using Javahtml
Oracle Tuxedo服務可使用純java來編寫。使用java實現的服務的功能和其餘Tuxedo服務實現是同樣的。你可使用客戶端或者Tuxedo服務器經過ATMI接口來調用Tuxedo Java Server(TMJSVASVR
)對外提供的服務;你也在java實現的服務中經過TJATMI接口來調用Tuxedo server提供的服務。java
另外,你可使用任何類型的Tuxedo客戶端調用java實現的服務,好比本地客戶端,/WS客戶端和Jolt客戶端。web
可使用TJATMI接口、JATMI類型緩衝、POLO java對象等主流Java技術來實現Tuxedo服務。sql
TuxedoJavaServer
類;Java服務類應該有一個默認的構造函數TPSVCINFO
接口做爲惟一的輸入參數tpsvrinit()
方法,在Tuxedo Java服務啓動時會被調用tpsvrdone()
方法,在Tuxedo Java服務關閉時會被調用tpcall
,tpbegin
等)tpreturn
向客戶端返回結果,或者經過拋出異常退出tpsvrinit()/tpsvrdone()
處理tpsvrinit()
處理:
用戶須要實現tpsvrinit()
方法。因爲該方法會在服務啓動時調用,最好在該方法中完成類的初始化。若是一個類的tpsvrinit()
方法失敗,用戶日誌中會報告一條警告信息,Java服務會繼續執行。數據庫
tpsvrdone()
處理:
用戶須要實現tpsvrinit()
方法。該方法在服務關閉時調用,推薦將類範圍的清理工做放入這個方法中。編程
tpreturn()
處理Java服務的tpreturn()
並不會當即結束Java服務方法的執行,而是向Tuxedo Java服務器返回一個結果。數組
Java 服務的tpreturn()
的行爲與現有Tuxedo系統的tpreturn()
行爲不一樣:服務器
tpreturn()
時,流控制自動轉向Tuxedotpreturn()
時,tpreturn()
以後的語句依舊會被執行。用戶必須保證tpreturn()
是Java服務中最後一條執行的語句。若是不是,建議在tpreturn()
以後加上return
;不然tpreturn()
不會自動將流控制轉向Tuxedo系統注意:不建議在Java服務中前面沒有
tpreturn()
時使用return
。這種用法會使Java服務器返回rcode爲0的TPFAIL
到相關的客戶端。多線程
TPFAIL
到其客戶端,其中rcode設置爲0$APPDIR/stderr
文件中。你須要配置一個路徑,經過該路徑Tuxdeo Java服務器能夠找到CLOPT中Java實現的服務的配置文件。
因爲ATMI Java服務器是一個多線程服務器,你還須要指名線程分配的限制。能夠查看Defining the Server Dispatch Threads一章獲取更多關於多線程服務配置的信息。oracle
清單2-1 顯示了ATMI Java服務器的UBB配置文件示例:
清單2-1
conf*SERVERS TMJAVASVR SRVGRP=TJSVRGRP SRVID=3 CLOPT="-- -c /home/oracle/app/javaserver/TJSconfig.xml" MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=3
注意:UBBCONFIG中爲Java服務器指明的
MAXDISPATCHTHREADS
最小值爲2。
UBBCONFIG(5)
in the File Formats, Data Descriptions, MIBs, and System Processes ReferenceTuxedoJavaServer
是一個抽象類,全部用戶定義的實現服務的類都應該繼承它。
表3-1 TuxedoJavaServer接口
函數 | 描述 |
---|---|
tpsvrinit | 抽象方法,子類實現時作一些初始化的工做 |
tpsvrdone | 抽象方法,子類實現時作一些清理工做 |
getTuxAppContext | 用來取回當前鏈接的Tuxedo應用Java上下文 |
爲了獲取Oracle Tuxedo Java Server提供的TJATMI原始功能,你須要獲取一個TuxAppContext
對象,該對象實現了全部的TJATMI功能
由於服務類繼承自TuxedoJavaServer
,你能夠在服務中調用getTuxAppContext()
方法獲取上下文對象。然而,你不能在tpsvrinit()
中或其TuxAppContext
,由於此時TuxAppContext
沒有準備好。若是你在tpsvrinit()
中嘗試獲取TuxAppContext
,tpsvrinit()
會出錯並拋出異常。
TJATMI是原生功能的集合,提供客戶端和服務器端的通訊功能,好比調用服務,開始和結束事務,獲取到數據源的鏈接,日誌等等。更多信息參考Java Server Javadoc
.
表3-2 TJATMI功能
名字 | 操做 |
---|---|
tpcall | 用於在請求/應答通訊中同步調用Oracle Tuxedo服務 |
tpreturn | 用於在Tuxedo Java Server中設置返回值 |
tpbegin | 開始事務 |
tpcommit | 提交當前事務 |
tpabort | 終止當前事務 |
tpgetlev | 檢查事務是否正在執行 |
getConnection | 獲取到已配置的數據源的鏈接 |
userlog | 在Tuxedo用戶日誌文件中打印日誌 |
注意:在
tpreturn
結束執行後服務依舊在運行。推薦把tpreturn
做爲服務中最後執行的語句。
ATMI Java server 重用了Oracle WebLogic Tuxedo Connector TypedBuffers 做爲相應的Oracle Tuxedo類型緩衝。消息經過類型緩衝傳入 server 。ATMI Java server提供的類型緩衝見表3-3:
表3-3 類型緩衝
緩衝類型 | 描述 |
---|---|
TypedString | 數據是以null字符做爲結束的字符數組時使用。Oracle Tuxedo 等價類型:STRING |
TypedCArray | 數據是未定義字符數組(字節數組),任一字節都有多是null。Oracle Tuxedo等價類型:CARRAY |
TypedFML | 數據自定義時使用。每一個數據域攜帶本身的標識,事件數,有可能有長度指示器。Oracle Tuxedo等價類型:FML |
TypedFML32 | 相似於TypedFML可是容許更大的字符範圍和域,更大的緩衝。Oracle Tuxedo等價類型:FML32 |
TypedXML | 數據是基於XML的消息。Oracle Tuxedo等價類型:XML |
TypedView | 應用使用Java結構,使用視圖描述文件來定義緩衝結構。Oracle Tuxedo等價類型:VIEW |
TypedView32 | 相似於View,容許更大的字符範圍、域、緩衝。Oracle Tuxedo等價類型:VIEW32 |
更多關於類型緩衝的信息,參見"weblogic.wtc.jatmi"
TypedFML32
中Fldid()/Fname()
嵌套在另外一個TypedFML32
中時沒法工做。爲了應對這種狀況,你可使用fieldtable
類傳輸name/id。weblogic.wtc.gwt.XmlViewCnv/XmlFmlCnv
類沒法使用。使用TPSVCINFO
類經過客戶端獲取/設置服務信息
表3-4 Getter函數
函數 | 描述 |
---|---|
getServiceData | 用來返回Oracle Tuxedo客戶端發送過來的服務數據 |
getServiceFlags | 用來返回客戶端發送過來的服務標識 |
getServiceName | 用來返回調用的服務名 |
getAppKey | 獲取程序認證客戶端密鑰 |
getClientID | 獲取客戶端標識符 |
使用TuxATMIReply
從服務請求中獲取迴應數據和元數據
表3-5 用於迴應的Getter函數
函數 | 描述 |
---|---|
getReplyBuffer | 返回從服務返回的類型緩衝(多是null) |
gettpurcode | 返回從服務返回的tpurcode |
你須要捕獲服務中JATMI原語拋出的異常,好比tpcall()
。JATMI可能拋出兩種類型的異常:
TuxATMITPException
:該異常拋出代表TJATMI出錯TuxATMITPReplyException
:若是服務出錯(TPESVCFAIL或者TPSVCERROR)該異常拋出,用戶數據關聯到異常中。你還須要導出TMTRACE=atmi:ulog
,正如你使用傳統ATMI那樣。TJATMI API跟蹤信息被寫入ULOG。
TuxedoJavaServer
的類tpsvrinit()
和tpsvrdone()
方法TPSVCINFO
做爲惟一的參數getTuxAppContext()
獲取TuxAppContext
對象TPSVCINFO.getServiceData()
從TPSVCINFO
對象中獲取客戶端請求數據TuxAppContext.getConnection()
方法獲取到數據源的鏈接TuxAppContext.tpcall()
調用其餘服務,操縱數據庫等TuxAppContext.tpreturn()
將應答數據返回客戶端以下實例是實現TOUPPER服務的簡單示例。
定義Java類
清單4-1
javaimport weblogic.wtc.jatmi.TypedBuffer; import weblogic.wtc.jatmi.TypedString; import com.oracle.tuxedo.tjatmi.*; public class MyTuxedoJavaServer extends TuxedoJavaServer { public MyTuxedoJavaServer() { return; } public int tpsvrinit() throws TuxException { System.out.println("MyTuxedoJavaServer.tpsvrinit()"); return 0; } public void tpsvrdone() { System.out.println("MyTuxedoJavaServer.tpsvrdone()"); return; } public void JAVATOUPPER(TPSVCINFO rqst) throws TuxException { TypedBuffer svcData; TuxAppContext myAppCtxt = null; TuxATMIReply myTuxReply = null; TypedBuffer replyTb = null; /* Get TuxAppContext first */ myAppCtxt = getTuxAppContext(); svcData = rqst.getServiceData(); TypedString TbString = (TypedString)svcData; myAppCtxt.userlog("Handling in JAVATOUPPER()"); myAppCtxt.userlog("Received string is:" + TbString.toString()); String newStr = TbString.toString(); newStr = newStr.toUpperCase(); TypedString replyTbString = new TypedString(newStr); /* Return new string to client */ myAppCtxt.tpreturn(TPSUCCESS, 0, replyTbString, 0); } public void JAVATOUPPERFORWARD(TPSVCINFO rqst) throws TuxException { TypedBuffer svcData; TuxAppContext myAppCtxt = null; TuxATMIReply myTuxReply = null; TypedBuffer replyTb = null; long flags = TPSIGRSTRT; /* Get TuxAppContext first */ myAppCtxt = getTuxAppContext(); svcData = rqst.getServiceData(); TypedString TbString = (TypedString)svcData; myAppCtxt.userlog("Handling in JAVATOUPPERFORWARD()"); myAppCtxt.userlog("Received string is:" + TbString.toString()); /* Call another service "TOUPPER" which may be implemented by another Tuxedo Server */ try { myTuxReply = myAppCtxt.tpcall("TOUPPER", svcData, flags); /* If success, get reply buffer */ replyTb = myTuxReply.getReplyBuffer(); TypedString replyTbStr = (TypedString)replyTb; myAppCtxt.userlog("Replied string from TOUPPER:" + replyTbStr.toString()); /* Return the replied buffer to client */ myAppCtxt.tpreturn(TPSUCCESS, 0, replyTb, 0); } catch (TuxATMITPReplyException tre) { myAppCtxt.userlog("TuxATMITPReplyException:" + tre); myAppCtxt.tpreturn(TPFAIL, 0, null, 0); } catch (TuxATMITPException te) { myAppCtxt.userlog("TuxATMITPException:" + te); myAppCtxt.tpreturn(TPFAIL, 0, null, 0); } } }
建立Java Server配置文件
清單4-2顯示了配置示例,將MyTuxedoJavaServer.JAVATOUPPER()
方法導出成Tuxedo 服務JAVATOUPPER
,將MyTuxedoJavaServer.JAVATOUPPERFORWARD()
方法導出成Tuxedo 服務JAVATOUPPERFORWARD
。
清單4-2
xml<?xml version="1.0" encoding="UTF-8"?> <TJSconfig> <TuxedoServerClasses> <TuxedoServerClass name="MyTuxedoJavaServer"> </TuxedoServerClass> </TuxedoServerClasses> </TJSconfig>
更新UBB配置文件
清單4-3 UBB配置文件
config*GROUPS TJSVRGRP LMID=simple GRPNO=2 *SERVERS TMJAVASVR SRVGRP= TJSVRGRP SRVID=4 CLOPT="-- -c TJSconfig.xml" MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=2
清單4-4給出了一個示例,實現WRITEDB_SVCTRN_COMMIT
服務,該服務將用戶請求字符串插入表TUXJ_TRAN_TEST
中。
定義Java類
清單4-4
javaimport weblogic.wtc.jatmi.TypedBuffer; import weblogic.wtc.jatmi.TypedString; import com.oracle.tuxedo.tjatmi.*; import java.sql.SQLException; /* MyTuxedoTransactionServer is user defined class */ public class MyTuxedoTransactionServer extends TuxedoJavaServer{ public MyTuxedoTransactionServer () { return; } public int tpsvrinit() throws TuxException { System.out.println("In MyTuxedoTransactionServer.tpsvrinit()"); return 0; } public void tpsvrdone() { System.out.println("In MyTuxedoTransactionServer.tpsvrdone()"); return; } public void WRITEDB_SVCTRN_COMMIT(TPSVCINFO rqst) throws TuxException { TuxAppContext myAppCtxt; TypedBuffer rplyBuf = null; String strType = "STRING"; String ulogMsg; TypedString rqstMsg; Connection connDB = null; Statement stmtDB = null; String stmtSQL; int trnLvl, trnStrtInSVC; int trnRtn; int rc = TPSUCCESS; rqstMsg = (TypedString)rqst.getServiceData(); myAppCtxt = getTuxAppContext(); myAppCtxt.userlog("JAVA-INFO: Request Message Is \"" + rqstMsg.toString() + "\""); rplyBuf = new TypedString("This Is a Simple Transaction Test from Tuxedo Java Service"); long trnFlags = 0; try { trnStrtInSVC = 0; trnLvl = myAppCtxt.tpgetlev(); if (0 == trnLvl) { long trnTime = 6000; myAppCtxt.userlog("JAVA-INFO: Start a transaction..."); trnRtn = myAppCtxt.tpbegin(trnTime, trnFlags); myAppCtxt.userlog("JAVA-INFO: tpbegin return " + trnRtn); trnStrtInSVC = 1; } connDB = myAppCtxt.getConnection(); if (null != connDB) { myAppCtxt.userlog("JAVA-INFO: Get connection: (" + connDB.toString() + ")."); } stmtDB = connDB.createStatement(); if (null != stmtDB) { myAppCtxt.userlog("JAVA-INFO: Create statement: (" + stmtDB.toString() + ")."); } stmtSQL = "INSERT INTO TUXJ_TRAN_TEST VALUES ('" + rqstMsg.toString() + "')"; myAppCtxt.userlog("JAVA-INFO: Start to execute sql (" + stmtSQL + ")..."); stmtDB.execute(stmtSQL); myAppCtxt.userlog("JAVA-INFO: End to execute sql (" + stmtSQL + ")."); if (1 == trnStrtInSVC) { myAppCtxt.userlog("JAVA-INFO: tpcommit current transaction..."); trnRtn = myAppCtxt.tpcommit(trnFlags); myAppCtxt.userlog("JAVA-INFO: tpcommit return " + trnRtn); trnStrtInSVC = 0; if (-1 == trnRtn ) { rc = TPFAIL; } } } catch (TuxATMIRMException e) { String errMsg = "ERROR: TuxATMIRMException: (" + e.getMessage() + ")."; myAppCtxt.userlog("JAVA-ERROR: " + errMsg); rc = TPFAIL; } catch (TuxATMITPException e) { String errMsg = "ERROR: TuxATMITPException: (" + e.getMessage() + ")."; myAppCtxt.userlog("JAVA-ERROR: " + errMsg); rc = TPFAIL; } catch (SQLException e) { String errMsg = "ERROR: SQLException: (" + e.getMessage() + ")."; myAppCtxt.userlog("JAVA-ERROR: " + errMsg); rc = TPFAIL; } catch (Exception e) { String errMsg = "ERROR: Exception: (" + e.getMessage() + ")."; myAppCtxt.userlog("JAVA-ERROR: " + errMsg); rc = TPFAIL; } catch (Throwable e) { String errMsg = "ERROR: Throwable: (" + e.getMessage() + ")."; myAppCtxt.userlog("JAVA-ERROR: " + errMsg); rc = TPFAIL; } finally { if (null != stmtDB) { try { stmtDB.close(); } catch (SQLException e) {} } } myAppCtxt.tpreturn(rc, 0, rplyBuf, 0); } }
建立Java 服務配置文件
表4-5
xml<?xml version="1.0" encoding="UTF-8"?> <TJSconfig> <ClassPaths> <ClassPath>/home/oracle/app/oracle/product/11.2.0/dbhome_2/ucp/lib/ucp.jar </ClassPath> <ClassPath>/home/oracle/app/oracle/product/11.2.0/dbhome_2/jdbc/lib/ojdbc6.jar</ClassPath> </ClassPaths> <DataSources> <DataSource name="oracle"> <DriverClass>oracle.jdbc.xa.client.OracleXADataSource</DriverClass> <JdbcDriverParams> <ConnectionUrl>jdbc:oracle:thin:@//10.182.54.144:1521/javaorcl</ConnectionUrl> </JdbcDriverParams> </DataSource> </DataSources> <TuxedoServerClasses> <TuxedoServerClass name=" MyTuxedoTransactionServer"> </TuxedoServerClass> </TuxedoServerClasses> </TJSconfig>
更新UBB配置文件
清單4-6
config*GROUPS ORASVRGRP LMID=simple GRPNO=1 OPENINFO="Oracle_XA:Oracle_XA+Acc=P/scott/triger+SesTm=120+MaxCur=5+LogDir=.+SqlNet=javaorcl" TMSNAME=TMSORA TMSCOUNT=2 *SERVERS TMJAVASVR SRVGRP=ORASVRGRP SRVID=3 CLOPT="-- -c TJSconfig.xml" MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=4