通过wtc使tuxedo与weblogic通信开发

更新时间:2024-04-29 15:39:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

标题:通过wtc、jolt进行tuxedo与weblogic通信开发

[评论]

作者:李振嘉(dev2dev ID:lizhenjia)

(一)摘要

bea tuxedo与weblogic作为业界优秀的交易与应用服务器中间件产品,在电信,银行,金融等领域广泛应用,通常由tuxedo处理系统的核心业务,weblogic将业务应用扩展到internet平台,实现电子商务,由weblogic调用tuxedo的服务或者由tuxedo的服务调用通过weblogic部署的ejb,所以tuxedo与weblogic之间的互连通信会经常遇到,本文通过2个例子介绍tuxedo与weblogic通信的配置与开发,两个例子分别通过wtc(weblogic tuxedo connector)、jolt实现weblogic与tuxedo通信的配置与开发.本文所有例子程序与配置均在Sun Solaris,weblogic8.1,tuxedo8.0平台上进行,如在windows等其他平台开发配置方法大同小异;另外为了减少篇幅文中涉及的例子代码没有全部罗列,只选择粘贴了关键部分的代码.

(二)通过wtc进行tuxedo与weblogic通信的配置与开发

1)域间通信以及wtc介绍

Tuxedo的域间通信进程介绍

Wtc是tuxedo通过域间通信实现的,所以需要tuxedo启动用于域间通信的进程,介绍wtc之前先介绍以下几个域间通信的进程.

*DMADM(DOMAIN ADMINISTRATOR SERVER)

管理域的server,在运行时管理BDMCONFIG,对已登记的gateway group提供支持,在tuxedo系统中,只能有一个DMADM进程,且不能对它采用MSSQ,不能有REPLYQ.

*GWADM(GATEWAY ADMINISTRATOR SERVER)

管理域的域网关进程,在运行时可以对某一组域网关进行管理,主要从DMADM那里取得域的配置信息,并对域网管进程及跨越域的全局事务的LOG文件进行管理.

*GWTDOMIN(GATEWAY PROCESS)

处理域之前的互操作,使本地域和调用远程域可以互相调用彼此的service,其中GMADM和GWTDOMAIN必须在一个组中,一个tuxedo应用可以有多个GWADM,GWTDOMAIN对,一个组只能有一个

GMADM,GWTDOMAIN对,但一个tuxedo应用只能有一个DMADM,DMADM可以在如何一个组中,一个本地域可以和多个远程域实现互操作.

Wtc介绍

Wtc(weblogic tuxedo connector)是weblogic server的一个组成部分,可以实现tuxedo和weblogic之间的应用集成,为weblogic和tuxedo提供了双向的互操作性,即tuxedo service可以调用在weblogic上部署的ejb,在weblogic上部署的ejb可以调用tuxedo的service.

2)Tuxedo方面需要进行的工作

修改并编译ubb文件

1) 在ubb文件*GROUPS节点中增加如下3个tuxedo Group:

DMGroup

LMID=simple GRPNO=2 OPENINFO=NONE

DMGroup

LMID=simple GRPNO=3 OPENINFO=NONE

WSGroup

LMID=simple GRPNO=4 OPENINFO=NONE

2)在ubb文件*SERVERS节点中增加如下3个tuxedo server:

DMADM

SRVGRP=DMGroup SRVID=22230

GWADM

SRVGRP=GWGroup SRVID=22340

GWTDOMAIN

SRVGRP=GWGroup SRVID=22350

其中GWADM和GWTDOMAIN应该在同一个组中,保存ubb文件并按如下完成编译:

tmloadcf ubb_filename

之后tmboot-y启动tuxedo server,如果启动以上3个server时报类似Application initialization failure的启动失败的提示信息,那么注意查看tuxedo的ULOG日志文件,通过日志的提示排除错误,这里常见的一个错误是没有在系统环境变量中定义

BDMCONFIG或者指定该文件路径错误.(关于环境变量的修改见下文).

增加并编译dm文件

dm文件是tuxedo进行域间通信时的配置文件,tuxedo与weblogic通过wtc通信是通过域间通信实现的,所以dm文件需要创建,dm文件通常可以存放在ubb文件所在的路径下.

Dm需要做的配置如下:

*DM_LOCAL_DOMAINS

tuxedo_domain GWGRP=GWGroup

TYPE=TDOMAIN

DOMAINID=billing

DMTLOGDEV=\

*DM_REMOTE_DOMAINS

weblogic_domain TYPE=TDOMAIN

DOMAINID=weblogic

*DM_TDOMAIN

tuxedo_domain NWADDR=\

NWDEVICE=\

weblogic_domain NWADDR=\

*DM_REMOTE_SERVICES

*DM_LOCAL_SERVICES

fml32_test RNAME=\

*DM_LOCAL_DOMAINS定义本地tuxedo域的信息,分别定义该域所在的组,域类型,域的唯一标识,域间通信时日志的全路径,其中GWGRP, DOMAINID的值要与ubb文件中的定义匹配.

*DM_REMOTE_DOMAINS定义远程weblogic域的信息,分别定义域类型,域的唯一性标识,该id标识需要与在weblogic server中的配置名称吻合,否则通信将会失败,关于在weblogic中的相应配置下文将作详细描述.

*DM_TDOMAIN定义在DM_LOCAL_DOMAIN中已经说明的本地域和在DM_REMOTE_DOMAINS中已经说明的远程域的具体的通信ip地址以及通信端口,其中NWDEVICE指定tuxedo发布的server通信进程文件所在的路径.

*DM_REMOTE_SERVICES定义当前域需要调用远程域的服务名称,本例中的服务作为被调用服务,所以此处可以为空.

*DM_LOCAL_SERVICES定义当前域对外发布的tuxedo service名称,可以通过RNAME重新命名service.

在以上NWADDR中指定的端口一定不能是已经被占用的端口,否则通信将失败,之前应该用netstat命令查询得到空闲的端口.

保存dm文件并按如下完成编译:

dmloadcf dm_filename

修改系统环境变量

在系统环境变量中增加:

export BDMCONFIG=$HOME/your_path/bdmconfig

其中bdmconfig文件为dmloadcf dm_filename编译之后生成的2进制配置文件.

编写基于tuxedo的程序以及makefile.

说明

Tuxedo支持string,carry,view,view32,fml,fml32等数据缓冲区,其中fml32类型相对复杂且比较常用,本例子采用fml32数据缓冲区开发,首先需要编写fml32数据缓冲区的定义文件,包括fml32数据缓冲区各个字段的名称已经长度等等,并将该文件生成相应的c语言.h头文件,在应用程序中需要包含该头文件,这样应用程序中即可以使用fml32数据缓冲区, fml32类型通常在开发数据库应用程序的时候比较常用,以下的例子完成的功能是:根据输入的学生学号从数据库中查询得到该学生的姓名和年龄,其实输入和输出参数采用fml32类型.

编写并编译fml32数据缓冲区定义文件

定义fml32数据缓冲区文件student_fld文件如下:

*base 10000

# name number type flags comments

student_id 1 long - 学生学号

student_name 2 string - 学生姓名

student_age 3 long - 学生年龄

student_id等3项就是自定义fml32类型的域字段,其中每一个字段都对应一个number,这些number有一个公共的起始值,通过*base 10000定义.

定义之后通过mkfldhdr32 student_fld编译该文件,之后生成student_fld.h头文件,在应用程序中将引用该文件.

编写源程序以及定义表

定义t_student表,其中id表示学号,name表示学生姓名,age定义表示姓名.

进入oracle sqlplus,键入:

create table t_student (id number(10), name varchar2(20), age number(3));

源程序文件wtc_jolt.pc(该程序通过pro*c文件访问数据库oracle数据库):

#include

#include

#include

#include

#include \

EXEC ORACLE OPTION (RELEASE_CURSOR = YES);

#if defined(__STDC__) || defined(__cplusplus)

tpsvrinit(int argc, char *argv[])

#else

tpsvrinit(argc, argv)

int argc;

char **argv;

#endif

{

EXEC SQL BEGIN DECLARE SECTION;

char sConnStr [100];

EXEC SQL END DECLARE SECTION;

argc = argc;

argv = argv;

memset(sConnStr, 0x00, sizeof(sConnStr));

strcpy(sConnStr, “数据库连接串”);

EXEC SQL Connect :sConnStr;

if (sqlca.sqlcode)

{

userlog(\连接数据库失败,错误号码:%d,详细原因:%s \

return -1;

}

}

#ifdef __cplusplus

extern \

#endif

void

#if defined(__STDC__) || defined(__cplusplus)

fml32_test(TPSVCINFO *rqst)

#else

fml32_test(rqst)

TPSVCINFO *rqst;

#endif

{

FBFR32 *recebuf = NULL;

FBFR32 *sendbuf = NULL;

FLDLEN32 recebuflen = 0;

EXEC SQL BEGIN DECLARE SECTION;

long lStudentId = 0;

char sName[15] = \

long lAge = 0;

EXEC SQL END DECLARE SECTION;

recebuf = (FBFR32 *)rqst->data;

if ((sendbuf = (FBFR32 *)tpalloc(\

{

tpterm();

exit(-1);

}

recebuflen=0;

Fget32(recebuf, student_id, 0, (char *)&lStudentId, &recebuflen);

EXEC SQL Select age, name Into :lAge, :sName

From t_student

Where student_id = :lStudentId;

if (sqlca.sqlcode)

{

userlog(\查询失败,code=%d,detail=%s \

exit(-2);

}

Fchg32(sendbuf, student_age, 0, (char *)&lAge, 0);

Fchg32(sendbuf, student_name, 0, sName, 0);

tpreturn(TPSUCCESS , 0, (char *)sendbuf, 0, 0);

}

编写makefile文件

.SUFFIXES:.pc .c

CC=cc

TUXINCLUDE=$(TUXDIR)/include

ORAINCLUDE=$(ORACLE_HOME)/precomp/public

WORKPATH=$(HOME)/../../...

APPPATH=$(HOME)/bin

TARGET=wtc_jolt

all: $(TARGET)

-@echo \

wtc_jolt:wtc_jolt.c

buildserver -f wtc_jolt.o -o wtc_jolt -s \

.pc.c:

proc iname=$<$(PROCPLSFLAGS) oname=$*.c parse=full hold_cursor=no release_cursor=yes include=$(TUXINCLUDE) include=$(ORAINCLUDE)

$(CC) -I$(ORAINCLUDE) -I$(TUXINCLUDE) -c $(ORACFLAGS) $*.c

将例子文件发布成tuxedo server和service.

通过makefile将wtc_jolt.pc编译成可执行文件wtc_jolt之后.

(一)修改tuxedo ubb配置文件.

1)在 *server节点中添加:

wtc_jolt SRVGRP=GROUP SRVID=1100

其中GROUP是tuxedo应用所在的组, SRVID是该server的标识id,注意不要与其他SRVID重复,wtc_jolt是刚刚编译生成的可执行文件名字,这样该文件就被发布为tuxedo server.

2)在*service节点中添加:

fml32_test

其中fml32_test是wtc_jolt.pc文件中的函数名字,这样该函数就被发布为属于server:wtc_jolt中的一个tuxedo service.

3)编译修改之后的ubb文件:

tmloadcf ubb_filename

(二)修改tuxedo dm配置文件.

1)在*DM_LOCAL_SERVICES节点中添加:

fml32_test RNAME=\

发布fml32_test service,使该service可以被其他域中的服务调用.

2)编译修改之后的dm文件:

dmloadcf dm_filename

以上配置和开发工作完成之后tuxedo方面的工作完成,tmboot ?y启动tuxedo,如有以下提示信息,tuxedo方面的工作宣告成功.

1) exec DMADM -A :

process id=28863 ... Started.

exec GWADM -A :

process id=28864 ... Started.

exec GWTDOMAIN -A :

process id=28865 ... Started.

以上信息说明域间通信进程启动成功!

2) exec wtc_jolt -A :

process id=28950 ... Started.

以上信息说明发布的server进程启动成功!

此时键入命令tmadmin, 键入子命令psc, 如有以下提示信,说明发布service成功.

Service Name Routine Name Prog Name Grp Name ID Machine # Done Status

---------------------------------------------------------------------

fml32_test fml32_test wtc_jolt GROUP 1100 simple 0 AVAIL

进行到这里tuxedo方面所有的工作已经完成,下面进入weblogic方面的工作.

3)Weblogic方面需要进行的工作.

创建tuxedo fml(32) 数据缓冲区定义文件对应的java类文件

本文例子用到tuxedo fml32数据缓冲区,所以首先要创建该fml32数据缓冲区定义文件对应的java描述文件的类文件,将前面定义的文件student_fld.

1) 执行weblogic环境变量setWLSEnv.sh,使weblogic环境变量生效.

2) 运行: java weblogic.wtc.jatmi.mkfldclass32 student_fld生成student_fld.java描述文件.

3) 运行: javac ?d student_fld.java生成student_fld.class文件.

4) 该类文件的存放路径一定可以被weblogic识别,即保存在weblogic启动后CLASSPATH的路径中,否则在后面配置wtc resource时会失败.

配置weblogic wtc service

进入weblgoic console,mydomain->services->wtc->Configure a new WTC service…

Name属性键入: WTC_Service,create保存设置,此时WTC_Service将生成local tuxedo access等若干子项,在下面将一步一步配置这些项目.

配置local tuxedo access

mydomain->services->wtc-> WTC_Service-> Configure a new local tuxedo access point…

依次填写Access Point: Local_Wls_Domain

Access Point ID: weblogic

Network Address: //weblogicserver_ip:port

注意:

1) Access Point ID的值应该与在tuxedo dm文件中*DM_REMOTE_DOMAINS节中指定的domainid相同.

2) Network Address中指定的通信端口一定是weblogic server上未被占用的端口.

以上信息填写完成后点击create保存.

配置remote tuxedo domain

mydomain->services->wtc-> WTC_Service-> Configure a new remote tuxedo access point…

依次填写Access Point: Remote_Tuxedo_Domain

Access Point ID: billing

Local Access Point: Local_Wls_Domain

Network Address: //tuxedoserver_ip:port

注意:

1) Access Point ID的值是远程tuxedo domain 的domain_id.

2) Local Access Point的值是上面配置的local tuxedo access point的名字.

以上信息填写完成后点击create保存.

导入tuxedo services

mydomain->services->wtc-> WTC_Service->Imported services->

Configure a new imported service…

Resource Name: fml32_test

Local Access Point: Local_Wls_Domain

Remote Access Point List: Remote_Tuxedo_Domain

Remote Name: fml32_test

注意:

1) Local Access Point是上面配置的local tuxedo access point的名字.

2) Remote Access Point List是上面配置的remote tuxedo access point的名字.

3) Remote Name是可供weblogic调用的远程tuxedo发布的service名字,即在

Tuxedo dm文件的*DM_LOCAL_SERVICES节点中发布的service名字.

配置wtc resource

mydomain->services->wtc-> WTC_Service->resources->

Configure a new Resource….

FldTbl32 classes: student_fld

注意:

1)resource定义fml(32),view(32)等数据缓冲区的类文件定义,其中student_fld就是上面编译得到的类,如果源文件包含在包中那么要标明包名称在内的全路径,如:

com.bea.wtc.test.classname

2)其中fml和fml32类型的java类在这里要分别指定,不能通用,view(32)也是一样.

以上信息填写完成后点击create保存,至此wtc service全部配置完成,单击wtc_service的Target and deploy标签,选择server,apply以上应用.

编写通过wls访问tuxedo service的程序

为了减少篇幅例子代码没有全部罗列,只选择粘贴了代码中的关键部分.

编写访问tuxedo service的ejb

关键函数介绍

创建本地接口文件,远程接口文件以及bean文件,公布以下远程方法:

1)public CallDescriptor Tpacall(String service, TypedFML32 in_params)

throws TPException, TPReplyException, RemoteException;

2)public TypedFML32 Tpgetrply(CallDescriptor cd)

throws TPException, TPReplyException, RemoteException;

3)public TypedFML32 Tpcall(String service_name, TypedFML32 in_params)

throws TPException, TPReplyException, RemoteException;

Tpcall : 同步调用tuxedo service.

Tpacall : 异步调用tuxedo service.

Tpgetrply: 等待异步调用service的返回结果.

关键函数代码

import weblogic.wtc.jatmi.Reply;

import weblogic.wtc.jatmi.TypedFML32;

import weblogic.wtc.jatmi.TPException;

import weblogic.wtc.jatmi.TPReplyException;

import weblogic.wtc.gwt.TuxedoConnection;

import weblogic.wtc.gwt.TuxedoConnectionFactory;

import weblogic.wtc.jatmi.Ferror;

import weblogic.wtc.jatmi.CallDescriptor;

import weblogic.wtc.jatmi.ApplicationToMonitorInterface;

private TuxedoConnection tuxConn = null;

函数setUpConnection

public TuxedoConnection setUpConnection() throws TPException

{

Context ctx = null;

TuxedoConnectionFactory tcf = null;

try

{

ctx = new InitialContext();

tcf= (TuxedoConnectionFactory)ctx.lookup(TUXEDOCONN_JNDI_NAME);

}

catch (NamingException ne)

{

throw new TPException(TPException.TPENOENT, \

}

try

{

tuxConn = tcf.getTuxedoConnection();

}

catch (TPException e)

{

throw new TPException(TPException.TPENOENT, \

}

return tuxConn;

}

函数Tpcall

public TypedFML32 Tpcall(String service_name, TypedFML32 in_params) throws TPException, TPReplyException

{

Reply tuxReply = null;

TypedFML32 tuxRtn = null;

try

{

if (tuxConn == null) tuxConn = this.setUpConnection();

}

catch (TPException e)

{

System.out.println(\

throw e;

}

try

{

tuxReply = tuxConn.tpcall(service_name, in_params, 0);

}

catch (TPReplyException tre)

{

System.out.println(\

throw tre;

}

catch (TPException te)

{

System.out.println(\

throw te;

}

catch (Exception ee)

{

System.out.println(\

throw new TPException(TPException.TPESYSTEM, \

}

tuxRtn = (TypedFML32)tuxReply.getReplyBuffer();

return tuxRtn;

}

函数Tpacall

public CallDescriptor Tpacall(String service_name, TypedFML32 in_params) throws TPException, TPReplyException

{

CallDescriptor tuxRtn = null;

try

{

tuxConn = this.setUpConnection();

}

catch (TPException e)

{

System.out.println(\

throw e;

}

try

{

tuxRtn=tuxConn.tpacall(service_name,in_params, ApplicationToMonitorInterface.TPNOTIME);

}

catch (TPReplyException tre)

{

System.out.println(\

throw tre;

}

catch (TPException te)

{

System.out.println(\

throw te;

}

catch (Exception ee)

{

System.out.println(\

throw new TPException(TPException.TPESYSTEM, \

}

return tuxRtn;

}

函数Tpgetrply

public TypedFML32 Tpgetrply(CallDescriptor cd) throws TPException, TPReplyException

{

Reply tuxRtn = null;

TypedFML32 result = null;

try

{

if (tuxConn == null) tuxConn = this.setUpConnection();

}

catch (TPException e)

{

System.out.println(\

throw e;

}

try

{

tuxRtn = tuxConn.tpgetrply(cd, ApplicationToMonitorInterface.TPNOTIME);

}

catch (TPReplyException tre)

{

System.out.println(\

throw tre;

}

try

{

result = (TypedFML32)tuxRtn.getReplyBuffer();

}

catch (Exception e)

{

System.out.println(\

result = null;

}

tuxConn.tpterm();

return result;

}

关于避免调用超时

有时Tuxedo service需要做时间较长的处理,超过了tuxedo默认的调用超时

时间,为了避免超时需要使客户端一直阻塞知道服务器端service返回结果;在传统tuxedo的c语言程序客户端可以指定tp(a)call函数的第6个参数flag为TPNOTIME,此时客户端如果有阻塞条件存在,客户端会一直阻塞即使超时也不返回;但通过weblogic的java客户端如果想要达到这个目的,如果采用异步tpacall调用,不仅仅要在tpacall中指定flag值为ApplicationToMonitorInterface.TPNOTIME,在tpgetrply等待结果时也同样需要指定第2个参数为ApplicationToMonitorInterface.TPNOTIME,否则仅在tpacall中指定不能达到避免超时的目的.

编写ejb客户端

关键函数介绍:

Public int selectService ();

连接weblogic server,调用具体的函数调用tuxedo service.

Public int callTestService(String service_name);

根据输入参数学号,调用tuxedo service,获得返回结果学生姓名和年龄.

关键函数代码

函数selectService

import weblogic.wtc.jatmi.Ferror;

import weblogic.wtc.jatmi.TypedFML32;

import weblogic.wtc.jatmi.CallDescriptor;

Public int selectService ()

{

try

{

…连接weblogic server…………

obj = ctx.lookup(ejb的jndiname);

}

catch (Exception e)

{

…………………

}

wtcHome=(WtcInstanceHome)javax.rmi.PortableRemoteObject.narrow(obj, WtcInstanceHome.class);

try

{

wtcRemote = wtcHome.create();

}

catch (Exception e)

{

………….

}

callTestService(service_name);

try

{

wtcRemote.remove();

}

catch (Exception e)

{

………………

}

}

函数callTestService

public String callTestService (String service_name)

{

CallDescriptor tuxRtn = null;

TypedFML32 inParams = null, tuxResult = null;

try

{

//创建fml32缓冲区java描述类的实例

inParams = new TypedFML32(new student_fld());

//填写输入参数:学号

inParams.Fchg(student_fld.student_id , 0, getStudentId());

}

catch (Ferror e)

{

……

}

try

{ //异步调用tuxedo service.

tuxRtn = wtcRemote.Tpacall(service_name, inParams);

}

catch (Exception e)

{

………

}

try

{ //等待异步调用的service返回结果.

tuxResult = wtcRemote.Tpgetrply(tuxRtn);

}

catch (Exception e)

{

………

}

try

{

//得到学生的姓名和年龄…

stuName = (String)tuxResult.Fget(student_fld.student_name, 0);

stuAge = (Integer) tuxResult.Fget(student_fld.student_age, 0);

}

catch (Ferror e)

{

………

}

………

}

本文来源:https://www.bwwdw.com/article/ibsg.html

Top