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="//192.168.0.166:9878"
MaximumPoolSize="2" MinimumPoolSize="1" Name="JoltPool"
PrimaryAddresses="//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 !