http://blog.csdn.net/liwei_cmg/archive/2006/06/02/769150.aspx
http://blog.csdn.net/liwei_cmg/archive/2006/06/03/771906.aspx
Java通過Jolt調用Tuxedo服務
草木瓜 2006-6-1
------------------------
一、簡介
------------------------
外部應用訪問Tuxedo服務是很經常的事,一般有兩種方法WTC和Jolt,網上很多關于Jolt調用Tuxedo服務
文章,描述的太多籠統,其實通過Jolt并不是很復雜的事情,這里使用Eclipse3.1+Jolt+WebLogic8.1
+Tuxedo9.0環境描述調用服務的全過程。
Jolt是Bea Tuxedo自帶的jar組件,在Tuxedo9.0的安裝過程中可以看到安裝的Jolt組件。
調用服務理論步驟是這樣的:
1.先準備Tuxedo服務端代碼
2.在Tuxedo中配置Jolt相關文件
3.啟動Tuxedo服務
4.配置WebLogic服務與Tuxedo Jolt相關的參數
5.配置Eclipse3.1啟動WebLogic服務
6.編寫Eclipse Servlet代碼,運行調用服務。
本例使用了《Windows Tuxedo的安裝配置-數據庫補充》一文中的Tuxedo數據服務文件,所以在啟動
Tuxedo服務前,必須先啟動數據庫實例,因為在tpsvinit()里面就配置了數據連接。關于Tuxedo配置
要點需參閱《Tuxedo的安裝配置-...》的四篇文章。
------------------------
二、Tuxedo服務文件全代碼
------------------------
這里把server.pc服務文件代碼再次列出。其中包括三個服務DBREAD(讀數據庫)和TOUPPER(轉換大寫)。
本例不使用TOUPPER,所以不用理會那段代碼。
其中liwei/liwei@windb連接的表tuxedo_test,結構如下:
CREATE TABLE TUXEDO_TEST(
ID NUMBER(2),
NAME VARCHAR2(10)
)
ID NAME
------------------------
1 aaaaaaa
2 bbbbbbb
#include <stdio.h>
#include <ctype.h>
#include <atmi.h> /* TUXEDO Header File */
#include <userlog.h> /* TUXEDO Header File */
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR ora_no[2];
int ora_id;
VARCHAR ora_value[10];
VARCHAR ora_cn[30];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca;
tpsvrinit()
{
strcpy(ora_cn.arr,"liwei/liwei@windb");
ora_cn.len = strlen(ora_cn.arr);
ora_cn.arr[ora_cn.len]='\0';
//EXEC SQL WHENEVER SQLERROR GOTO cnError;
EXEC SQL CONNECT :ora_cn;
return(0);
}
tpsrvdone()
{
EXEC SQL COMMIT WORK RELEASE;
}
DBREAD(TPSVCINFO *rqst)
{
strcpy(ora_no.arr,(char *)rqst->data);
ora_no.len=strlen(ora_no.arr);
ora_no.arr[ora_no.len]='\0';
userlog("ERRSRV: %s",ora_no.arr);
EXEC SQL select name into :ora_value from tuxedo_test where id=:ora_no;
if(sqlca.sqlcode!=0)
{
userlog("ERRSRV: select name from tuxedo_test where id=, sqlcode=%ld , sqlerr=\n",sqlca.sqlcode);
strcpy(rqst->data,sqlca.sqlerrm.sqlerrmc);
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
/* Return the transformed buffer to the requestor. */
strset(rqst->data,"");
strcpy(rqst->data,ora_value.arr);
tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}
TOUPPER(TPSVCINFO *rqst)
{
int i;
for(i = 0; i < rqst->len-1; i++)
rqst->data[i] = toupper(rqst->data[i]);
/* Return the transformed buffer to the requestor. */
tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}
------------------------
三、編譯服務
------------------------
編譯命令的注意事項,以前Tuxedo系列文章都提過。
proc server.pc include=%TUXDIR%\include
buildserver -o server -f server.c -s DBREAD -s TOUPPER -v -l orasql9.lib
------------------------
四、配置Tuxedo服務的config文件
------------------------
完全文件如下:
#Liwei
*RESOURCES
IPCKEY 123456
DOMAINID liweiapp
MASTER lw
MAXACCESSERS 150
MAXSERVERS 100
MAXSERVICES 100
MODEL SHM
LDBAL N
*MACHINES
LWYM
LMID = lw
TUXDIR = "E:\bea\tuxedo9.0"
TUXCONFIG = "G:\Liwei\Tuxedo\dbread\tuxconfig"
APPDIR = "G:\Liwei\Tuxedo\dbread"
MAXWSCLIENTS=1
TLOGDEVICE = "G:\Liwei\Tuxedo\dbread\TLOG"
TLOGNAME=TLOG
TLOGSIZE = 100
*GROUPS
APPGRP LMID=lw GRPNO = 1
#OPENINFO="Oracle_XA:Oracle_XA+Acc=P/liwei/liwei+SqlNet=linux+SesTm=600+MaxCur=5+LogDir=."
#TMSNAME="TMS_ORA9i" TMSCOUNT=2
JSLGRP LMID=lw GRPNO = 2
JREPGRP LMID=lw GRPNO = 3
*SERVERS
server SRVGRP=APPGRP SRVID=1
#WSL SRVGRP=APPGRP SRVID =300
#CLOPT="-A -- -n //192.168.0.166:8888 -d/dev/tcp -m1 -M5 -x 10"
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2"
JREPSVR SRVGRP=JREPGRP SRVID=302
CLOPT="-A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository"
*SERVICES
DBREAD
TOUPPER
細心一看,這個config文件比在*GROUPS和*SERVERS各加了兩項對應內容:
JSLGRP LMID=lw GRPNO = 2
JREPGRP LMID=lw GRPNO = 3
和
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2"
JREPSVR SRVGRP=JREPGRP SRVID=302
CLOPT="-A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository"
這兩項是用于jolt的訪問接口。JSL和JREPSVR必須是獨自的GROUP,由于外部調用通過JSL和JREPSVR直接于
Tuxedo服務通信,WSL就沒用了。JSL的主機地址是Tuxedo服務器地址,端口是隨意指定的,不要與其他重復
即可,一般設置的大一點。在config里面加入這此內容后,config文件就Ok了。
------------------------
五、配置jrepository文件
------------------------
直接打開E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository文件添加以下內容:
add SVC/DBREAD:vs=1:ex=1:bt=STRING:\
bp:pn=STRING:pt=string:pf=167772161:pa=rw:ep:
add PKG/SIMPSERV:DBREAD:
這個文件如果沒有DBREAD配置,調用會提示DBREAD not avaliable,DBREAD配置錯誤,會提示DBREAD has
been modifed ...
對這個文件操作還有以下兩種方式:
方式一:在IE打開E:\bea\tuxedo9.0\udataobj\jolt\RE.html,是個java applet,里面是圖形界面,添加
完服務,設置好參數即可。具體方法可以查閱網上資料,有圖文解說的。
方式二:在命令行鍵入Java bea.jolt.admin.jbld //192.168.0.166:9878 services.rep,其中//192..要與
JSL的設置一致。services.rep是隨意的一個文件,不過文件內容絕對不隨意,如下:
service=DBREAD
inbuf=STRING
outbuf=STRING
export=true
param=STRING
type=string
access=inout
要執行這個命令設置jdk環境變量是必不可少的,PATH,CLASSPATH。我的CLASSPATH加入了以下內容,
E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar;
E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar;
E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar;
E:\bea\tuxedo9.0\udataobj\jolt\joltadmin.jar
個人認為對于這個java命令joltadmin是必須的,其他三個沒用,不過沒有親自嘗試。
方式一,二修改后,jrepository文件會顯得比較亂,所以我不喜歡!最好是自已手工修改。
------------------------
六、編譯啟動服務
------------------------
當然,數據庫必須要有了,編譯config后,啟動tuxedo服務。
tmloadcf -y config
tmboot -y
提示如下:
exec BBL -A :
process id=3520 ... Started.
Booting server processes ...
exec server -A :
process id=3812 ... Started.
exec JSL -A -- -n //192.168.0.166:9878 -M 10 -x 10 -m 2 :
process id=252 ... Started.
exec JREPSVR -A -- -W -P E:\bea\tuxedo9.0\udataobj\jolt\repository\jrepository :
process id=2920 ... Started.
4 processes started.
------------------------
七、配置Eclipse3.1
------------------------
我們要在Eclipse里面啟動WebLogic服務,《Eclipse3.1 Web開發配置》一文中已經說明了,如何配置
WebLogic8.1的服務器,這里對WebLogic的服務本身也要做此必要的配置。
打開選用的WebLogic8.1服務路徑,編輯config.xml文件,本機位置G:\Liwei\WebLogic\WebServer\config.xml。
加入如下內容:
<JoltConnectionPool FailoverAddresses="http://192.168.0.166:9878"
MaximumPoolSize="2" MinimumPoolSize="1" Name="JoltPool"
PrimaryAddresses="http://192.168.0.166:9878"
SecurityContextEnabled="false" Targets="webServer"/>
<StartupClass
ClassName="bea.jolt.pool.servlet.weblogic.PoolManagerStartUp"
LoadBeforeAppActivation="true" Name="MyStartup" Targets="webServer"/>
<ShutdownClass
ClassName="bea.jolt.pool.servlet.weblogic.PoolManagerShutDown"
Name="MyShutdown" Targets="webServer"/>
這里要說明一下:PrimaryAddresses,FailoverAddresses地址是前面Tuxedo配置文件指定的JSL地址和端口
SecurityContextEnabled一定要是false!所有name是隨意的,StartupClass和ShutdownClass的ClassName
絕對不能錯!
除此方法,還可以通過Weblogic服務的控制臺進行管理。啟動服務后,在http://localhost:7001/console/
登陸后的主頁面上選擇 連接性->通過 JOLT 的 Tuxedo ->配置新的Jolt 連接緩沖池...輸入參數內容就是
上面config.xml的參數。另外首頁中 已部署的資源 ->啟動和關閉 需要設置兩個Class,參數也同上。
連接性->通過 JOLT 的 Tuxedo ->配置新的Jolt 連接緩沖池...
①進入選項卡的General(常規),輸入參數:
Name: JoltPool
Minimum Pool Size: 1
Maximum Pool Size: 2
Recv Timeout: 0
點擊Apply應用按紐
②進入選項卡的Addresses(地址),輸入參數:
Primary Addresses: //192.168.0.166:9878
Failover Addresses: //192.168.0.166:9878
點擊Apply應用按紐
③進入Targets欄:
選中myserver
點擊Apply應用按紐.
已部署的資源 ->啟動和關閉 分別配置StartUp,ShutDown的Class
①進入Configuration(設置)
在ClassName:中輸入: bea.jolt.pool.servlet.weblogic.PoolManagerStartUp,
其它采用默認值。
②進入Targets(目標)欄:
選中myserver,點擊Apply應用按紐.
①進入Configuration(設置)
在ClassName:中輸入: bea.jolt.pool.servlet.weblogic.PoolManagerShutDown,
其它采用默認值。
②進入Targets(目標):
選中myserver,點擊Apply應用按紐.
到這里config.xml文件就設置完了,下面需要編輯startWebLogic.cmd,加入對jolt jar的引用,否則jolt
是啟動失敗的。在echo CLASSPATH=%CLASSPATH%前加入以下代碼,設置CLASSPATH,這里classpath跟外部環境
變量是兩碼事。
set CLASSPATH=%CLASSPATH%;E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar;E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar;E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar
設置完后,重啟服務,在Eclipse管理WebLogic服務時如果出現啟動關閉不成功,多試幾次就可以了。
在啟動的console界面里如果出現以下內容,就說明jolt pool啟動成功!
<2006-6-1 下午09時12分55秒 CST> <Notice> <WebLogicServer> <BEA-000327> <Starting WebLogic Admin Server "webServer" for domain "WebServer">
Jolt pool deployed for webServer
<2006-6-1 下午09時13分13秒 CST> <Notice> <Security>...
------------------------
八、Eclipse3.1編寫Servlet代碼
------------------------
首先需要在所建工程->右鍵->Properties->Java BuildPath ->Library->Add External jars ..添加jolt的jar包
這里需要三個jar包,如下:
E:\bea\tuxedo9.0\udataobj\jolt\jolt.jar
E:\bea\tuxedo9.0\udataobj\jolt\joltjse.jar
E:\bea\tuxedo9.0\udataobj\jolt\joltwls.jar
添加jar完后,建立一個主頁面index.jsp和一個Servlet。關于Eclipse3.1配置Servlet在《Eclipse3.1 Web開發配置》
一文也有說明。這里Servlet名為liwei.java,具體內容如下:
index.jsp
<body>
<form id=form1 name="form1" action=liwei method=post>
<input type="text" name="STRING" value="1">
<input type=submit value=submit>
</form>
</body>
說明:name要是STRING,用來傳遞參數,action是liwei.java即Servlet。
liwei.java
public class liwei extends javax.servlet.http.HttpServlet
{
//聲明管理連接池的變量
private bea.jolt.pool.servlet.ServletSessionPoolManager bool_mgr = (bea.jolt.pool.servlet.ServletSessionPoolManager) bea.jolt.pool.SessionPoolManager.poolmgr;
public void init(javax.servlet.ServletConfig config) throws javax.servlet.ServletException
{
//初始化servlet
super.init(config);
}
public void destroy() {
//關閉servlet
bool_mgr = null;
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
bea.jolt.pool.servlet.ServletResult result;
//設置頁面類型,如果沒有charset,顯示漢字會亂碼
response.setContentType("text/html;charset=UTF-8");
java.io.PrintWriter out =response.getWriter();
out.println("<html>");
out.println("<body>");
//System.out.println("TEST________________________1");
//獲取在WebLogic服務定義好的連接池,JoltPool
bea.jolt.pool.servlet.ServletSessionPool pool_session = (bea.jolt.pool.servlet.ServletSessionPool)
bool_mgr.getSessionPool("JoltPool");
if (pool_session == null) {
out.println("獲取Tuxedo服務失敗。"+
"<br>"+
"確認Tuxedo服務已啟動且配置正確。"+
"</font></body></html>");
out.close();
return;
}
System.out.println(pool_session);
String sendvalue;
sendvalue=request.getParameter("STRING");
System.out.println(sendvalue);
// 調用服務
try
{
System.out.println("OK!");
//調用服務DBREAD
result = pool_session.call("DBREAD", request);
out.println("傳遞的參數 = " + sendvalue);
out.println("Tuxedo服務成功調用。 ");
//跟據傳遞的變量STRING值,獲取返回值
out.println("返回值:"+result.getValue("STRING", ""));
}
catch (bea.jolt.pool.SessionPoolException e)
{
// 連接池繁忙
out.println("此時請求不能被處理。\n"+
"錯誤信息: "+e.getMessage()+"\n"+
"可能的原因:1.無效的連接池 2.連接池已關閉");
}
catch (bea.jolt.pool.ServiceException e)
{
// 服務出錯,這里主要是Tuxedo的服務配置,jrepository文件出錯
e.printStackTrace();
out.println("錯誤信息:"+
"Error message:"+e.getMessage()+
"Error number:"+e.getErrno());
}
catch (bea.jolt.pool.ApplicationException e)
{
// 應用程序出錯
result = (bea.jolt.pool.servlet.ServletResult) e.getResult();
out.println("錯誤代碼:"+result.getApplicationCode());
}
catch (Exception e)
{
out.println("意外錯誤:"+e);
}
out.println("</body></html>\n");
out.close();
}
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
this.doGet(request,response);
}
}
------------------------
九、RUN
------------------------
Run on server ,點擊Submit,顯示 傳遞的參數 = 1 Tuxedo服務成功調用。 返回值:aaaaaaa !
=======================
Java通過Jolt訪問Tuxedo服務-補充說明
草木瓜
2006-6-2
一、頁面參數文件說明以及通過WebLogic調用Tuxedo服務
《Java通過Jolt訪問Tuxedo服務》一文是在Eclipse環境下開發調用Tuxedo服務。
其中在index.asp和liwei.java中有這么幾句語句:
index.asp
<form id=form1 name="form1" action=liwei method=post>
<input type="text" name="STRING" value="1">
<input type=submit value=submit>
liwei.java
//跟據傳遞的變量STRING值,獲取返回值
out.println("返回值:"+result.getValue("STRING", ""));
這兩段的STRING是不可以隨便替換的,這必須與E:\bea\tuxedo9.0\udataobj\jolt\repository
下jrepository文件描述的服務參數相一致!且必須為大寫!即:
add SVC/DBREAD:vs=1:ex=1:bt=STRING:\
bp:pn=STRING:pt=string:pf=167772161:pa=rw:ep: //這里面定義的參數就是STRING
add PKG/SIMPSERV:DBREAD:
下面用WebLogic對Tuxedo服務調用再詳細的舉例說明。
WebLogic通過jolt調用Tuxedo服務,有了上文的前提就顯得很容易,說白了只是Servlet與Jsp的一點
小轉換。除了最后一步在Eclipse3.1編寫Servlet代碼,其他的前提步驟是必須的。WebLogic要使用
Jolt接口,同樣需要jolt,joltjse,joltwls三個jar包,將它們Copy到WEB-INF下的lib文件夾即可。
以下是完整的示例,參數名用大寫的TEST。
index.jsp
---------------------------------
<form action="_test/testTuxedo.jsp" method="post">
<p>
<input type="text" value="1" name="TEST" id="text1"><input type="submit" value="tuxedo">
</p>
</form>
testTuxedo.jsp
---------------------------------
<body>
<p>
<%
bea.jolt.pool.servlet.ServletSessionPoolManager bool_mgr = (bea.jolt.pool.servlet.ServletSessionPoolManager) bea.jolt.pool.SessionPoolManager.poolmgr;
bea.jolt.pool.servlet.ServletResult result;
//獲取在WebLogic服務定義好的連接池
bea.jolt.pool.servlet.ServletSessionPool pool_session = (bea.jolt.pool.servlet.ServletSessionPool)
bool_mgr.getSessionPool("JoltPool");
if (pool_session == null) {
out.println("獲取Tuxedo服務失敗。"+
"<br>"+
"確認Tuxedo服務已啟動且配置正確。");
out.close();
return;
}
// 調用服務
try
{
result = pool_session.call("DBREAD", request);
System.out.println("OK!");
out.println("傳遞的參數 = " + sendvalue);
out.println("Tuxedo服務成功調用。 ");
out.println("返回值:"+result.getValue("TEST", ""));
}
catch (bea.jolt.pool.SessionPoolException e)
{
// 連接池繁忙
out.println("此時請求不能被處理。\n"+
"錯誤信息: "+e.getMessage()+"\n"+
"可能的原因:1.無效的連接池 2.連接池已關閉");
}
catch (bea.jolt.pool.ServiceException e)
{
// 服務出錯
e.printStackTrace();
out.println("Error:"+
"Error message:"+e.getMessage()+
"Error number:"+e.getErrno());
}
catch (bea.jolt.pool.ApplicationException e)
{
// 應用程序出錯
result = (bea.jolt.pool.servlet.ServletResult) e.getResult();
out.println("錯誤代碼:"+result.getApplicationCode());
}
catch (Exception e)
{
out.println("意外錯誤:"+e);
}
%>
</p>
</body>
二、典型的服務應用
Oracle服務器 192.168.0.111
Tuxedo服務器 192.168.0.66
Web服務器
通過Web客戶端訪問Web服務器,調用Tuxedo服務訪問數據庫
1.配置Tuxedo服務器的Oracle連接字符串(TNSNAME)。注意Oracle服務器的防火墻
WINDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.111)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = wincn)
)
)
2.配置Tuxedo的jrepository文件
3.配置Tuxedo的Config文件,JSR服務的IP與端口要與本地IP一致。
JSL SRVGRP=JSLGRP SRVID=301
CLOPT="-A -- -n //192.168.0.66:9988 -M 10 -x 10 -m 2"
4.配置Web服務器的WebServer,config.xml中ip與端口即為Tuxedo服務器的JSR服務IP與端口
注意Tuxedo服務器的防火墻。
<JoltConnectionPool FailoverAddresses="http://192.168.0.66:9988"
MaximumPoolSize="2" MinimumPoolSize="1" Name="JoltPool"
PrimaryAddresses="http://192.168.0.66:9988"
SecurityContextEnabled="false" Targets="webServer"/>