java 客户端调用 Tuxedo中间件
原文章地址
簡介
Oracle Tuxedo服務可以使用純java來編寫。使用java實現(xiàn)的服務的功能和其他Tuxedo服務實現(xiàn)是一樣的。你可以使用客戶端或者Tuxedo服務器通過ATMI接口來調(diào)用Tuxedo Java Server(TMJSVASVR)對外提供的服務;你也在java實現(xiàn)的服務中通過TJATMI接口來調(diào)用Tuxedo server提供的服務。
另外,你可以使用任何類型的Tuxedo客戶端調(diào)用java實現(xiàn)的服務,比如本地客戶端,/WS客戶端和Jolt客戶端。
可以使用TJATMI接口、JATMI類型緩沖、POLO java對象等主流Java技術來實現(xiàn)Tuxedo服務。
編程方針
- Java服務類,實現(xiàn)Java服務,需要繼承TuxedoJavaServer類;Java服務類應該有一個默認的構造函數(shù)
- Java服務類中的Java方法會被向外提供成Java服務,應該聲明為public, 并將TPSVCINFO接口作為唯一的輸入?yún)?shù)
- Java服務類應該實現(xiàn)tpsvrinit()方法,在Tuxedo Java服務啟動時會被調(diào)用
- Java服務類應該實現(xiàn)tpsvrdone()方法,在Tuxedo Java服務關閉時會被調(diào)用
- Java服務可以使用Tuxedo Java ATMI接口(例如tpcall,tpbegin等)
- Java服務可以使用tpreturn向客戶端返回結果,或者通過拋出異常退出
Tuxedo Java 服務器線程與Java類實例模型
- Tuxedo Java服務使用傳統(tǒng)的Tuxedo多線程模型,必須運行在多線程模式下
- 一旦啟動,Tuxedo Java服務為每一個定義在配置文件中的類創(chuàng)建一個全局對象(實例),處理Java服務時工作線程共享全局對象(實例)
Tudexo Java服務器 tpsvrinit()/tpsvrdone()處理
tpsvrinit()處理:
用戶需要實現(xiàn)tpsvrinit()方法。由于該方法會在服務啟動時調(diào)用,最好在該方法中完成類的初始化。如果一個類的tpsvrinit()方法失敗,用戶日志中會報告一條警告信息,Java服務會繼續(xù)執(zhí)行。
tpsvrdone()處理:
用戶需要實現(xiàn)tpsvrinit()方法。該方法在服務關閉時調(diào)用,推薦將類范圍的清理工作放入這個方法中。
Tuxedo Java服務器tpreturn()處理
Java服務的tpreturn()并不會立即結束Java服務方法的執(zhí)行,而是向Tuxedo Java服務器返回一個結果。
Java 服務的tpreturn()的行為與現(xiàn)有Tuxedo系統(tǒng)的tpreturn()行為不同:
- 當現(xiàn)有Tuxedo系統(tǒng)調(diào)用tpreturn()時,流控制自動轉向Tuxedo
- 當Java服務調(diào)用tpreturn()時,tpreturn()之后的語句依舊會被執(zhí)行。用戶必須保證tpreturn()是Java服務中最后一條執(zhí)行的語句。如果不是,建議在tpreturn()之后加上return;否則tpreturn()不會自動將流控制轉向Tuxedo系統(tǒng)
注意:不建議在Java服務中前面沒有tpreturn()時使用return。這種用法會使Java服務器返回rcode為0的TPFAIL到相關的客戶端。
Tuxedo Java服務器異常處理
- Java服務執(zhí)行期間可以拋出任何的異常然后退出Java服務。這種情況下Java服務器會返回TPFAIL到其客戶端,其中rcode設置為0
- 所有的異常信息會記錄在$APPDIR/stderr文件中。
編程環(huán)境
更新UBB配置文件
你需要配置一個路徑,通過該路徑Tuxdeo Java服務器可以找到CLOPT中Java實現(xiàn)的服務的配置文件。
由于ATMI Java服務器是一個多線程服務器,你還需要指名線程分配的限制??梢圆榭碊efining the Server Dispatch Threads一章獲取更多關于多線程服務配置的信息。
清單2-1 顯示了ATMI Java服務器的UBB配置文件示例:
清單2-1
*SERVERS TMJAVASVR SRVGRP=TJSVRGRP SRVID=3 CLOPT="-- -c /home/oracle/app/javaserver/TJSconfig.xml" MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=3注意:UBBCONFIG中為Java服務器指明的MAXDISPATCHTHREADS最小值為2。
參見
- Setting Up an Oracle Tuxedo Application
- UBBCONFIG(5) in the File Formats, Data Descriptions, MIBs, and System Processes Reference
ATMI Java Server 用戶接口
TuxedoJavaServer
TuxedoJavaServer是一個抽象類,所有用戶定義的實現(xiàn)服務的類都應該繼承它。
表3-1 TuxedoJavaServer接口
| tpsvrinit | 抽象方法,子類實現(xiàn)時做一些初始化的工作 |
| tpsvrdone | 抽象方法,子類實現(xiàn)時做一些清理工作 |
| getTuxAppContext | 用來取回當前連接的Tuxedo應用Java上下文 |
Oracle Tuxedo Java上下文
為了獲取Oracle Tuxedo Java Server提供的TJATMI原始功能,你需要獲取一個TuxAppContext對象,該對象實現(xiàn)了所有的TJATMI功能
因為服務類繼承自TuxedoJavaServer,你可以在服務中調(diào)用getTuxAppContext()方法獲取上下文對象。然而,你不能在tpsvrinit()中或其TuxAppContext,因為此時TuxAppContext沒有準備好。如果你在tpsvrinit()中嘗試獲取TuxAppContext,tpsvrinit()會出錯并拋出異常。
Tuxedo Java 應用中的TJATMI功能
TJATMI是原生功能的集合,提供客戶端和服務器端的通信功能,比如調(diào)用服務,開始和結束事務,獲取到數(shù)據(jù)源的連接,日志等等。更多信息參考Java Server Javadoc.
表3-2 TJATMI功能
| tpcall | 用于在請求/應答通信中同步調(diào)用Oracle Tuxedo服務 |
| tpreturn | 用于在Tuxedo Java Server中設置返回值 |
| tpbegin | 開始事務 |
| tpcommit | 提交當前事務 |
| tpabort | 終止當前事務 |
| tpgetlev | 檢查事務是否正在執(zhí)行 |
| getConnection | 獲取到已配置的數(shù)據(jù)源的連接 |
| userlog | 在Tuxedo用戶日志文件中打印日志 |
注意:在tpreturn結束執(zhí)行后服務依舊在運行。推薦把tpreturn作為服務中最后執(zhí)行的語句。
Tuxedo Java應用的類型緩沖
ATMI Java server 重用了Oracle WebLogic Tuxedo Connector TypedBuffers 作為相應的Oracle Tuxedo類型緩沖。消息通過類型緩沖傳入 server 。ATMI Java server提供的類型緩沖見表3-3:
表3-3 類型緩沖
| TypedString | 數(shù)據(jù)是以null字符作為結束的字符數(shù)組時使用。Oracle Tuxedo 等價類型:STRING |
| TypedCArray | 數(shù)據(jù)是未定義字符數(shù)組(字節(jié)數(shù)組),任一字節(jié)都有可能是null。Oracle Tuxedo等價類型:CARRAY |
| TypedFML | 數(shù)據(jù)自定義時使用。每個數(shù)據(jù)域攜帶自己的標識,事件數(shù),有可能有長度指示器。Oracle Tuxedo等價類型:FML |
| TypedFML32 | 類似于TypedFML但是允許更大的字符范圍和域,更大的緩沖。Oracle Tuxedo等價類型:FML32 |
| TypedXML | 數(shù)據(jù)是基于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函數(shù)
| getServiceData | 用來返回Oracle Tuxedo客戶端發(fā)送過來的服務數(shù)據(jù) |
| getServiceFlags | 用來返回客戶端發(fā)送過來的服務標識 |
| getServiceName | 用來返回調(diào)用的服務名 |
| getAppKey | 獲取程序認證客戶端密鑰 |
| getClientID | 獲取客戶端標識符 |
使用TuxATMIReply從服務請求中獲取回應數(shù)據(jù)和元數(shù)據(jù)
表3-5 用于回應的Getter函數(shù)
| getReplyBuffer | 返回從服務返回的類型緩沖(可能是null) |
| gettpurcode | 返回從服務返回的tpurcode |
異常
你需要捕獲服務中JATMI原語拋出的異常,比如tpcall()。JATMI可能拋出兩種類型的異常:
- TuxATMITPException:該異常拋出表明TJATMI出錯
- TuxATMITPReplyException:如果服務出錯(TPESVCFAIL或者TPSVCERROR)該異常拋出,用戶數(shù)據(jù)關聯(lián)到異常中。
跟蹤
你還需要導出TMTRACE=atmi:ulog,正如你使用傳統(tǒng)ATMI那樣。TJATMI API跟蹤信息被寫入ULOG。
在Oracle Tuxedo Java Server 中實現(xiàn)服務
典型過程
- 使用getTuxAppContext()獲取TuxAppContext對象
- 使用TPSVCINFO.getServiceData()從TPSVCINFO對象中獲取客戶端請求數(shù)據(jù)
- 如果配置了數(shù)據(jù)源,使用TuxAppContext.getConnection()方法獲取到數(shù)據(jù)源的連接
- 完成商業(yè)邏輯,比如使用TuxAppContext.tpcall()調(diào)用其他服務,操縱數(shù)據(jù)庫等
- 分配新的類型緩沖,把應答數(shù)據(jù)放入類型緩沖中
- 調(diào)用TuxAppContext.tpreturn()將應答數(shù)據(jù)返回客戶端
實例:沒有事務的Java服務實現(xiàn)
如下實例是實現(xiàn)TOUPPER服務的簡單示例。
定義Java類
清單4-1
import 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);}} }創(chuàng)建Java Server配置文件
清單4-2顯示了配置示例,將MyTuxedoJavaServer.JAVATOUPPER()方法導出成Tuxedo 服務JAVATOUPPER,將MyTuxedoJavaServer.JAVATOUPPERFORWARD()方法導出成Tuxedo 服務JAVATOUPPERFORWARD。
清單4-2
<?xml version="1.0" encoding="UTF-8"?> <TJSconfig><TuxedoServerClasses><TuxedoServerClass name="MyTuxedoJavaServer"> </TuxedoServerClass></TuxedoServerClasses> </TJSconfig>更新UBB配置文件
清單4-3 UBB配置文件
*GROUPS TJSVRGRP LMID=simple GRPNO=2 *SERVERS TMJAVASVR SRVGRP= TJSVRGRP SRVID=4 CLOPT="-- -c TJSconfig.xml" MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=2實例:帶有事務的Java Service實現(xiàn)
清單4-4給出了一個示例,實現(xiàn)WRITEDB_SVCTRN_COMMIT服務,該服務將用戶請求字符串插入表TUXJ_TRAN_TEST中。
定義Java類
清單4-4
import 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);} }創(chuàng)建Java 服務配置文件
表4-5
<?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
*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=3CLOPT="-- -c TJSconfig.xml"MINDISPATCHTHREADS=2 MAXDISPATCHTHREADS=4總結
以上是生活随笔為你收集整理的java 客户端调用 Tuxedo中间件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【columnstore】mariadb
- 下一篇: 【安卓作业】星座查询小程序