本文讨论weblogic server 9(下简称wls9)中的新特性:java web service (jws)。wls9的web services子系统实现了j2ee 1.4中的web services的新标准: enterprise web services 1.1 specification (jsr-921)。该规范定义了标准的j2ee web service打包格式,部署模块以及运行时服务。
jsr-921是j2ee 1.3中web services规范jsr-109的1.1维护版本。在web services 1.1中描述了j2ee web service的业务逻辑有两种实现方式:一种是使用web容器中的javabean,另一种是使用ejb容器中的无状态session bean。与旧的web services开发方式不同,bea建议使用jws这种基于注释的web services编程方式以简化开发。这种编程方式的开发过程大概是这样,利用jdk5的新特性元数据注释(jsr-175),在编写上述的java bean或ejb的bean类时在业务逻辑代码中添加一些特殊注释,然后用ant的一些扩展任务可以生成一些相关java类代码(主要是ejb的存根、桩)和配置文件,最后自动编译这些类代码并自动打包。所以可以说jws方式是web services新标准的核心。jws文件实际就是普通的.java文件(扩展名依旧是.java),通过添加注释来制定ws的特性。这些注释在jsr181中有完整的说明。如果web service用java bean类实现,自动打包后会包含web.xml,weblogic.xml, webservices.xml,weblogic-webservices.xml,jax-rpc数据类型映射文件和wsdl等,并被打包成标准web应用的war。如果用ejb实现,则会包含ejb-jar.xml和weblogic-ejb.jar.xml等,并被自动打包成标准ejb的jar。下图描述了jws文件生成可部署的j2ee模块的详细过程。后面我们会用两个例子详细说明如何开发、部署基于java bean和基于ejb的web services。

jsr181与jsr175介绍
我们先来看一段典型的使用jsr175特征的代码。
package webservices.jsr181.pojo;
import javax.jws.webmethod;
import javax.jws.webservice;
@webservice(name="stringchangerport", targetnamespace="http://wwtt.bea.com")
public class stringchanger {
@webmethod()
public string toupper(string upperreqstring)
{
……
这个类的源代码和普通的java代码没太多区别,但和普通java代码不同的是这里面还包含了很多以@开头的代码,或者称为注释,也就是在java 5中的新语法,jsr-175。jsr-175规范只是定义这种语法规则,而用这种语法来如何将这个类生成一个web service接口,则需要由jsr-181规范来决定。所以这些jsr-175的注释才真正决定了这个web service的行为和外观。
也许你会觉得这种语法比较奇怪,有些像普通java方法的语法,只是前面多了一个@。实际在jsr175规范的早期,该语法并不是像现在这样的。如果按早期写法,@webservice()会该写为:
/**
* @webservice(......)
*/ 后来出于简化,成了现在的样子。如果使用weblogic platform 7.x或8.x产品,会在许多其专有的代码文件中看到这种格式的注释。由于撰写本文时weblogic platform 9还没有发布。发布后是否那些专有代码会使用基于jsr-175的语法还不得而知,但可以确定的是在weblgic server 9中这种语法已经被全面支持了,无论在web service中,还是在ejb中。
事实上jsr 181是bea提出的用于加速web services开发的一种基于注释驱动的编程模式,并被批准纳入到j2ee 1.5标准。jsr181提供了一种简单的web service开发编程模型和标准的编译及部署方式。只需要编写jsr-175风格的注释就可以制定wsdl,消息产生属性,安全认证方式,以及特定的消息头。
练习的预备工作
准备必要软件。
进行练习前需要预先安装wls9正式版,可以到bea官方网站上免费下载。本练习可在能安装wls9的任何操作系统上完成,为了方便起见,文中仅以在windows xp上开发为例。此外本文中代码的开发环境为eclipse 3.1及对应的lomboz,当然如您所愿任何其他支持ant的开发环境都是可以的。
配置weblogic server。
准备好上述软件后,首先用配置创建一个新的wls domain。记得用户名和密码要都设为weblogic,端口为7001。创建好后启动该domain,并用浏览器启动相应的console,用帐户weblogic/weblogic登录进入。
配置eclipse。
如果希望eclipse的配置尽量吻合本文的环境,可参考我的另一篇文章:“使用eclipse加速weblogic server开发”的第一步到第二步。配置好后在eclipse的file->new project中选取java project,在project name中将我们这个练习的名字设为jsr-181 web services或任何你喜欢的名字,jdk compliance中选择“use a project specific compliance 5.0”,其余保持默认。一个符合我们需要的project就建好了。
修改脚本文件。
本练习所有的构建过程都由ant来完成,因此我们需要添加一些ant的脚本配置文件。属性文件,宏定义文件可以完全参照《使用eclipse加速weblogic server开发》,因此只需要吧那里面的那三个文件拿过来用就可以了。
需要修改的是build.xml文件,这里定义的属性主要是为后面两个例子设置一些路径。
<?xml version="1.0"?>
<project name="wls v9 jsr-181 web services" basedir=".">
<property file="wls-build-tools/weblogicserver.properties" />
<import file="wls-build-tools/weblogicserver.macrodef" />
<taskdef file="wls-build-tools/weblogictasks.properties" classpathref="jwsbuild.class.path" />
<property name="apps.src.dir" location="." />
<property name="apps.dest.dir" location="${temp.dir}" />
<property name="clients.src.dir" location="." />
<property name="clients.dest.dir" location="${temp.dir}" />
<property name="clients.package.name" value="client.test"/>
<property name="clients.package.path" value="client/test"/>
<property name="jbapp.context.name" value="jb" />
<property name="jbapp.package.name" value="webservices.jsr181.pojo"/>
<property name="jbapp.src.dir" location="${apps.src.dir}/webservices/jsr181/pojo"/>
<property name="jbapp.jwssource.file" value="stringchanger.java" />
<property name="jbapp.dest.dir" location="${apps.dest.dir}/${jbapp.context.name}" />
<property name="jbapp.service.name" value="stringchangerservice" />
<property name="jbapp.wsdl.url" value="http://${domain.address}:${domain.port}/${jbapp.context.name}/${jbapp.service.name}?wsdl" />
<property name="jbapp.deploy.name" value="wls v9 jsr-181 javabean web service" />
<property name="ejbapp.context.name" value="ejb" />
<property name="ejbapp.package.name" value="webservices.jsr181.ejb"/>
<property name="ejbapp.src.dir" location="${apps.src.dir}/webservices/jsr181/ejb"/>
<property name="ejbapp.jwssource.file" value="purchaseorder.java" />
<property name="ejbapp.dest.dir" location="${apps.dest.dir}/${ejbapp.context.name}" />
<property name="ejbapp.service.name" value="purchaseorderservice" />
<property name="ejbapp.wsdl.url" value="http://${domain.address}:${domain.port}/${ejbapp.context.name}/${ejbapp.service.name}?wsdl" />
<property name="ejbapp.wsdl.local" value="jar:file:${apps.dest.dir}/${ejbapp.context.name}/purchaseorder.jar!/meta-inf/${ejbapp.service.name}.wsdl" />
<property name="ejbapp.deploy.name" value="wls v9 jsr-181 ejb web service" />
<path id="jwsbuild.class.path">
<fileset dir="${weblogic.home}/server/lib">
<include name="weblogic.jar" />
<include name="xbean.jar" />
</fileset>
<fileset dir="${jdk5.home}/lib">
<include name="tools.jar" />
</fileset>
</path>
<path id="javabuild.class.path">
<pathelement path="${clients.dest.dir}" />
<fileset dir="${weblogic.home}/server/lib">
<include name="webserviceclient.jar" />
</fileset>
</path>
<!--后面的练习中我们将根据需要在此添加一些target。-->
</project>
如何快速查看例子的结果,而跳过开发环节。
做好1到4步骤就可以按照后面几节所述完成练习。但如果想快速看一下练习结果,将本文附件solution包括所有源代码。解压到您磁盘任何位置,用eclipse创建好一空的名为jsr-181 web services的project后,用solution解出的jsr-181 web services文件夹替换这个project的文件夹。最后在eclipse的package explorer中刷新一下,就浏览已经开发配置好eclipse project代码了。修改项目的wls-build-tools路径下weblogicserver.properties中的wls和jdk环境变量,然后就可以执行ant脚本中的任务来编译,部署,测试等步骤。
开发基于javabean的web services
基于javabean的web servics是最简单的一种方式。我们只需要在普通的javabean码中添加一些符合jsr181的注释,在build.xml中调用wls提供的扩展ant task,就可以完成一个完整的web services。
创建一个java bean。
在project的根目录下创建一个类名为stringchanger,包名为webservices.jsr181.pojo,写入如下内容:
package webservices.jsr181.pojo;
import javax.jws.webmethod;
import javax.jws.webservice;
import javax.jws.soap.soapbinding;
import weblogic.jws.wlhttptransport;
@webservice(name="stringchangerport", targetnamespace="http://bea.com")
@soapbinding(style=soapbinding.style.rpc, use=soapbinding.use.encoded)
@wlhttptransport(contextpath="jb", serviceuri="stringchangerservice")
public class stringchanger {
@webmethod()
public string toupper(string upperreqstring)
{
string upper = upperreqstring.touppercase();
system.out.println("toupper request: " + upperreqstring);
system.out.println("toupper reply: " + upper);
return(upper);
}
@webmethod(operationname="tolower")
public string tolowercase(string lowerreqstring)
{
string lower = lowerreqstring.tolowercase();
system.out.println("tolowercase request: " + lowerreqstring);
system.out.println("tolowercase reply: " + lower);
return(lower);
}
}
这个类是用于实现我们这个web services模块的业务逻辑,以及描述这个web service接口。该类中包含两个public的业务方法:toupper(string): string和tolowercase(string): string。其中的逻辑也很简单:前者将传入的字符串全变成大写,后者则全变成小写。并且两个方法都将在终端上将操作过程打印出来。除了这两法方法,其余都是用于描述web service接口的jsr-181注释。
先看一些类级别的注释。@webservice()表示这个类可以生成web service。name用于映射到wsdl文件的<wsdl:porttype>元素,可以在生成的wsdl中找到<wsdl:porttype>的值为stringchangerport。targetnamespace用于指定wsdl文件中元素的命名空间,能在生成的wsdl中找到对应的targetnamespace="http://bea.com"。@soapbinding()表示这个服务可以映射到一个soap消息中。style用于指定soap消息请求和回应的编码方式为rpc。use用于指定soap消息请求和回应是明文还是密文,此处表示为密文。@wlhttptransport是一个weblogic专用的注释,用于指生成的配置文件中的上下文路径和这个web service的uri。contextpath用于指定上下文路径为jb,也就是说可以用 http://localhost:7001/jb/ 这个url来调用这个web services应用。serviceuri表示客户端访问这个web service的uri为 http://localhost:7001/jb/stringchangerservice。
再看一些方法级别的注释。方法级注释为@webmethod()。operationname为操作的名字,用于映射到wsdl文件的<wsdl:operation>元素。默认值为对应的方法名。因此在这个javabean生成的web service中toupper方法对应的操作名为toupper,tolowercase方法对应的操作名为tolower。
编写build.xml target。
<target name="build.jb" depends="clean.jb">
<jwsc srcdir="${jbapp.src.dir}" destdir="${jbapp.dest.dir}" listfiles="true" classpathref="jwsbuild.class.path">
<jws file="${jbapp.jwssource.file}" />
</jwsc>
</target>
<target name="deploy.jb" depends="check.jb" if="jb.exists">
<wls.deploy deploy.dir="${jbapp.dest.dir}" deploy.name="${jbapp.deploy.name}" />
</target>
build.jb 这个target主要用于建立一个可部署的web services模块。jwsc这个任务是用于分析jws文件中的注释,生成对应java文件配置文件,编译代码,最后在destdir指定的位置生成这个web services的war包。
deploy.jb这个target主要用于把web service模块部署到wls domain中。wls.deploy是一个在weblogicserver.macrodef中定义的task,调用wls的ant扩展任务wldeploy。
编译web services。
现在我们在ant view中执行任务build.ws.pojo,可以看到在console窗口显示出对应的操作过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
clean.jb:
[delete] deleting directory c:/temp/jb
[mkdir] created dir: c:/temp/jb
build.jb:
[jwsc] 1 jws files will be processed.
[jwsc] processing jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java
[jwsc] jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java validated.
[jwsc] compiling 2 source files to c:/temp/_ukbwfm
[jwsc] c:/temp/_ukbwfm/stringchangerporttype.java
[jwsc] c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/pojo/stringchanger.java
[jwsc] building war: c:/temp/jb/stringchanger.war
[jwsc] created jws deployment file: c:/temp/jb/stringchanger.war
[antutil.deletedir] deleting directory c:/temp/_ukbwfm
build successful
total time: 22 seconds
打开目录c:/temp/jb,我们能看到生成了两个文件夹和一个war文件。在文件夹meta-inf下的 application.xml中的<web-uri>元素的值来自jws中的注释@wlhttptransport。打开生成的war文件我们能看web-inf路径下已经生成了一些对应的配置文件。查看其中的wsdl文件名为stringchangerservice.wsdl,这也是来自jws中的注释@wlhttptransport。在wsdl文件中能看到targetnamespace为http://wwtt.bea.com,这是来自jws中的注释@webservice。同样我们能在该文件中看到service元素中port为stringchangerport,也是来自@webservice。在这个文件中包括了两个operation元素,name分别为tolower和toupper,对应到jws中两个注释@webmethod。同时我们能看到对应的style为rpc,use为encoded。这些都符合我们在jws的@soapbinding注释中的设置。同时我们能看到该war的web-inf/classes/webservices/jsr181/pojo 目录中包含两个class文件:stringchanger.class内是stringchanger.java描述的业务逻辑,stringchangerporttype是为这个类生成的接口。stringchangerporttype会在后面生成web services代码时被自动调用。
public interface stringchangerporttype extends remote{
public abstract string tolowercase(string s)
throws remoteexception;
public abstract string toupper(string s)
throws remoteexception;
}
部署web service
我们在ant view中执行任务deploy.jb,可以看到在console窗口中显示对应部署过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
check.jb:
deploy.jb:
[wldeploy] weblogic.deployer -noexit -name wls v9 jsr-181 javabean web service -source c:/temp/jb -targets adminserver -adminurl t3://localhost:7001 -user weblogic -password ******** -deploy
[wldeploy] weblogic.deployer invoked with options: -noexit -name wls v9 jsr-181 javabean web service -source c:/temp/jb -targets adminserver -adminurl t3://localhost:7001 -user weblogic -deploy
[wldeploy] <2005-11-28 下午06时12分15秒 cst>
[wldeploy] task 13 initiated: [deployer:149026]deploy application wls v9 jsr-181 javabean web service on adminserver.
[wldeploy] task 13 completed: [deployer:149026]deploy application wls v9 jsr-181 javabean web service on adminserver.
[wldeploy] target state: deploy completed on server adminserver
build successful
total time: 14 seconds
用浏览器打开http://localhost:7001/console/,用weblogic/webogic登录,在左边目录树的deploy展开能看到已经部署了一个名为“wls v9 jsr-181 javabean web service”的企业应用(enterprise application),状态为active。

测试
用浏览器打开 http://localhost:7001/jb/stringchangerservice?wsdl ,可以看到一个展开的wsdl文件。这个文件的内容和我们前面在war中看到的wsdl文件应该是完全一致的。到此我们已经学会了开发一个简单的基于javabean的web service应用。
基于javabean的web service开发测试客户端
从上面的例子我们已经了解了如何开发,部署及测试一个web services模块,下面我们要学习如何开发一个web service客户端来调用web service逻辑。
编写build.xml target
<target name="build.jbclient">
<clientgen wsdl="${jbapp.wsdl.url}" destdir="${clients.src.dir}" packagename="${clients.package.name}" />
<javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
</target>
<target name="build.jbdriver">
<javac srcdir="${jbapp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
</target>
build.jbclient 这个target主要用于建立一个web services模块的客户端,其中包含两个任务。clientgen这个任务可以根据一个wsdl文件生成一组调用该web service的客户端文件。clientgen的属性wsdl指定wsdl文件的位置,packagename指定生成的测试代码的包名。javac这个任务将生成的客户端java代码文件编译成对应的class文件。
build.jbdriver这个target主要用于编译测试类。
生成并编译客户端代码
现在我们在ant view中执行任务build.jbclient,可以看到在console窗口显示出对应的操作过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
build.jbclient:
[clientgen] generating client from http://localhost:7001/jb/stringchangerservice?wsdl ...
[clientgen] getting partner link
[clientgen] package name is client.test
[clientgen] destdir is c:/project/eclipse31/workspace/jsr-181 web services
[clientgen] class name is stringchangerport_stub
[clientgen] service class name is stringchangerservice
[clientgen] porttype name is stringchangerport
[clientgen] service impl name is stringchangerservice_impl
[javac] compiling 4 source files to c:/temp
build successful
total time: 20 seconds
回到eclipse的package explorer视图,在“jsr-181 web services”上右键选refresh,能看到在项目中增加了一个名为client.test的包。展开这个包能看到里面包含若干java文件,xml文件和wsdl文件。这些文件就是自动生成的客户端代码。打开资源管理器到c:/temp/client/test,能看到生成的客户端代码的class文件。

我们注意到,一共生成了4个类,接口stringchangerport和其实现类stringchangerport_stub是我们在stringchanger类中用@webservice(name="stringchangerport",......)指定的,用于定义业务方法的参数类型和参数转换传输的方法。接口stringchangerservice和其实现类stringchangerservice_impl是我们在stringchanger类中用@wlhttptransport(......, serviceuri="stringchangerservice")中指定的,用于获得service连接,定义消息的收发方式。
创建并编译一个测试类
下面我们创建一个测试类testdriver_pojo来调用刚才我们创建的web service客户端。和刚才创建java bean一样,在webservices.jsr181.pojo中创建一个类testdriver_pojo,写入如下内容:
package webservices.jsr181.pojo;
import java.rmi.remoteexception;
import javax.xml.rpc.serviceexception;
import client.test.stringchangerport;
import client.test.stringchangerservice;
import client.test.stringchangerservice_impl;
public class testdriver_pojo {
public static void main(string[] args) throws serviceexception, remoteexception{
string url = "http://localhost:7001/jb/stringchangerservice?wsdl";
stringchangerservice service = new stringchangerservice_impl(url);
stringchangerport port = service.getstringchangerportsoapport();
string teststring = "this is my test string ;-)";
system.out.println("toupper request: " + teststring);
system.out.println("toupper results: " + port.toupper(teststring));
system.out.println("tolower request: " + teststring);
system.out.println("tolower results: " + port.tolower(teststring));
}
}
我们能看到,一个java类调用一个web service客户端是非常简单的。首先通过提供wsdl文件的位置来获得客户端类(stringchangerservice)以及soap接口(stringchangerport)。然后就可以通过服务名来调用这个soap接口提供的各种服务(toupper和tolower)。
运行测试类观察结果
因为测试类只是用于测试,简化起见我们直接运行这个类而不使用ant。右键点这个类的java文件,选择“run as…=> java application”。这时我们在console能看到运行结果。如果一切正确:
toupper request: this is my test string ;-)
toupper results: this is my test string ;-)
tolower request: this is my test string ;-)
tolower results: this is my test string ;-)
到此,我们已经成功创建了一个基于jsr-181的web service以及对应客户端。如果有兴趣,可以试着在jws文件中修改一些代码和注释,看看这些代码和注释会影响什么。无论如何,这会加深你对jsr-181的理解。
开发基于session ejb的web service
使用基于ejb的web servics和基于javabean的方式类似。我们只需在bean类中添加一些符合jsr181的注释,在build.xml中调用wls提供的扩展ant task来完成web services。
1. 创建一个ejb。
在project的根目录下创建一个类名为purchaseorder,包名为webservices.jsr181.ejb,写入如下内容:
package webservices.jsr181.ejb;
import java.rmi.remoteexception;
import javax.ejb.ejbexception;
import javax.ejb.sessionbean;
import javax.ejb.sessioncontext;
import javax.jws.webmethod;
import javax.jws.webservice;
import javax.jws.soap.soapbinding;
import weblogic.ejbgen.constants;
import weblogic.ejbgen.filegeneration;
import weblogic.ejbgen.jndiname;
import weblogic.ejbgen.remotemethod;
import weblogic.ejbgen.session;
import weblogic.jws.wlhttptransport;
@session(ejbname = "purchaseorderejb", serviceendpoint = "webservices.jsr181.ejb.purchaseorderporttype")
@jndiname(remote = "purchaseorderejb.remote")
@filegeneration(remoteclass = constants.bool.true, remoteclassname = "purchaseorderremote", remotehome = constants.bool.true, remotehomename = "purchaseorderhome")
@webservice(name="purchaseorderport", servicename="purchaseorderservice", targetnamespace="http://bea.com /purchaseorder")
@soapbinding(style=soapbinding.style.document, use=soapbinding.use.literal, parameterstyle=soapbinding.parameterstyle.bare)
@wlhttptransport(portname="purchaseorderport", contextpath="ejb", serviceuri="purchaseorderservice")
public class purchaseorder implements sessionbean {
private static final long serialversionuid = 1l;
public void ejbcreate() {}
@remotemethod()
@webmethod()
public string toupper(string upperreqstring)
{
string upper = upperreqstring.touppercase();
system.out.println("toupper request: " + upperreqstring);
system.out.println("toupper reply: " + upper);
return(upper);
}
public void setsessioncontext(sessioncontext arg0) throws ejbexception,
remoteexception {}
public void ejbremove() throws ejbexception, remoteexception {}
public void ejbactivate() throws ejbexception, remoteexception {}
public void ejbpassivate() throws ejbexception, remoteexception {}
}
这个类是我们创建的ejb的bean类,并通过jsr175方式描述该ejb接口以及生成的web service接口。该类中只包含一个public的业务方法:toupper(string): string,其余都是ejb要求的方法,以及用于描述ejb和web service的jsr-175注释。
先看一些类级别的注释。和基于javabean的jws类似,包含了jsr181定义的三行注释@webservice(),@soapbinding()和@wlhttptransport()。与javabean不同的是这里还包括一些用于生成ejb配置文件和接口的注释。@session表示这是一个session bean,属性ejbname和serviceendpoint分别表示ejb的名字和接口名。@jndiname()中属性remote表示这个ejb发布在jndi上的地址为purchaseorderejb.remote。@filegeneration()表示由这个bean类生成的代码文件。属性remoteclass,remoteclassname,remotehome和remotehomename分别指定使用远程接口和远程home接口,并且这两个接口为purchaseorderremote和purchaseorderhome。
在方法级别上,除了和javabean类似用@webmethod()声明暴露的web service操作外,用@remotemethod()将这个方法指定为发布到远程接口上的方法。
2. 编写build.xml target。
<target name=”build.ejb” depends=”clean.ejb”>
<jwsc srcdir=”${ejbapp.src.dir}” destdir=”${ejbapp.dest.dir}” listfiles=”true” classpathref=”jwsbuild.class.path”>
<jws file=”${ejbapp.jwssource.file}” />
</jwsc>
</target>
<target name=”deploy.ejb” depends=”check.ejb” if=”ejb.exists”>
<wls.deploy deploy.dir=”${ejbapp.dest.dir}” deploy.name=”${ejbapp.deploy.name}” />
</target>
build.jb和deploy.jb两个target主要用于建立一个可部署的web services模块并部署到domain中。这与前面javabean例子使用方式完全一致。
3. 编译web services。
现在我们在ant view中执行任务build.ejb,可以看到在console窗口显示出对应的操作过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
clean.ejb:
[delete] deleting directory c:/temp/ejb
[mkdir] created dir: c:/temp/ejb
build.ejb:
[jwsc] 1 jws files will be processed.
[jwsc] processing jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java
[jwsc] jws: c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java validated.
[jwsc] ejbgen 9.0
[jwsc] creating c:/temp/_f26ur6/purchaseorderhome.java
[jwsc] creating c:/temp/_f26ur6/purchaseorderremote.java
[jwsc] creating c:/temp/_f26ur6//ejb-jar.xml
[jwsc] creating c:/temp/_f26ur6//weblogic-ejb-jar.xml
[jwsc] compiling 4 source files to c:/temp/_f26ur6
[jwsc] c:/temp/_f26ur6/purchaseorderhome.java
[jwsc] c:/temp/_f26ur6/purchaseorderporttype.java
[jwsc] c:/temp/_f26ur6/purchaseorderremote.java
[jwsc] c:/project/eclipse31/workspace/jsr-181 web services/webservices/jsr181/ejb/purchaseorder.java
[jwsc] building jar: c:/temp/ejb/purchaseorder.jar
[jwsc] created jws deployment file: c:/temp/ejb/purchaseorder.jar
[antutil.deletedir] deleting directory c:/temp/_f26ur6
creating c:/temp/_f26ur6/ejbgen-build.xml
build successful
total time: 17 seconds
打开目录c:/temp/ejb,我们能看到生成了两个文件夹和一个jar文件。在文件夹meta-inf下的。打开生成的jar文件我们能看meta-inf路径下已经生成了一些对应的配置文件。其中大部分和在javabean中生成的配置文件类似,此外还包括一些与ejb相关的配置文件,比如weblogic-ejb-jar.xml,ejbgen-build.xml和ejb-jar.xml,没有了与web应用相关的配置文件weblogic.xml和web.xml
部署web service
我们在ant view中执行任务deploy.ejb,可以看到在console窗口中显示对应部署过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
check.ejb:
deploy.ejb:
[wldeploy] weblogic.deployer 每noexit 每name wls v9 jsr-181 ejb web service 每source c:/temp/ejb 每targets adminserver 每adminurl t3://localhost:7001 每user weblogic 每password ******** -deploy
[wldeploy] weblogic.deployer invoked with options: -noexit 每name wls v9 jsr-181 ejb web service 每source c:/temp/ejb 每targets adminserver 每adminurl t3://localhost:7001 每user weblogic 每deploy
[wldeploy] <2005-11-28 ?b??09?c21煦47镞 cst>
[wldeploy] task 1 initiated: [deployer:149026]deploy application wls v9 jsr-181 ejb web service on adminserver.
[wldeploy] task 1 completed: [deployer:149026]deploy application wls v9 jsr-181 ejb web service on adminserver.
[wldeploy] target state: deploy completed on server adminserver
build successful
total time: 7 seconds
用浏览器打开http://localhost:7001/console/,用weblogic/webogic登录,在左边目录树的deploy展开能看到已经部署了一个名为“wls v9 jsr-181 ejb web service”的企业应用(enterprise application),状态为active。

5. 测试
用浏览器打开http://localhost:7001/ejb/stringchangerservice?wsdl,可以看到一个展开的wsdl文件。这个文件的内容和我们前面在jar中看到的wsdl文件应该是完全一致的。
为基于session ejb的web service开发测试客户端
和javabean一样,我们可以为这个基于session bean的web service创建一个客户端,并用来测试。
1. 编写build.xml target
<target name="build.ejbclient">
<clientgen wsdl="${ejbapp.wsdl.local}" destdir="${clients.src.dir}" packagename="${clients.package.name}"/>
<javac srcdir="${clients.src.dir}" destdir="${clients.dest.dir}" includes="${clients.package.path}/*.java" debug="on" classpathref="javabuild.class.path" />
</target>
<target name="build.ejbdriver">
<javac srcdir="${ejbapp.src.dir}" destdir="${clients.dest.dir}" includes="*.java" classpathref="javabuild.class.path" />
</target>
build.jbclient 与build.ejbdriver和javabean中的对应目标也类似。唯一区别的是在clientgen任务中使用的wsdl文件不是来自url,而是来自build.ejb生成的jar包。使用local或url方式对其他客户端代码没有影响,基本这两种方式可以互换使用。
2. 生成并编译客户端代码
现在我们在ant view中执行任务build.jbclient,可以看到在console窗口显示出对应的操作过程。
buildfile: c:/project/eclipse31/workspace/jsr-181 web services/build.xml
build.ejbclient:
[clientgen] generating client from jar:file:c:/temp/ejb/purchaseorder.jar!/meta-inf/purchaseorderservice.wsdl …
[clientgen] getting partner link
[clientgen] package name is client.test
[clientgen] destdir is c:/project/eclipse31/workspace/jsr-181 web services
[clientgen] class name is purchaseorderport_stub
[clientgen] service class name is purchaseorderservice
[clientgen] porttype name is purchaseorderport
[clientgen] service impl name is purchaseorderservice_impl
[javac] compiling 4 source files to c:/temp
build successful
total time: 11 seconds
回到package explorer视图的包client.test。能看到里面又增加了若干java文件,xml文件和wsdl文件。这些文件就是自动生成的客户端代码。打开资源管理器到c:/temp/client/test,能看到生成的客户端代码的class文件。

我们注意到,一共生成了4个类,stringchangerport和stringchangerport_stub是我们在stringchanger类中用@webservice(name="stringchangerport",......)指定的。stringchangerservice和stringchangerservice_impl是我们在stringchanger类中用@wlhttptransport(......, serviceuri=”stringchangerservice”)中指定的。
3. 创建并编译一个测试类
下面我们在webservices.jsr181.ejb中创建一个类testdriver_ejb,写入如下内容:
package webservices.jsr181.ejb;
import java.rmi.remoteexception;
import javax.xml.rpc.serviceexception;
import client.test.purchaseorderport;
import client.test.purchaseorderservice;
import client.test.purchaseorderservice_impl;
public class testdriver_ejb
{
public static void main(string[] args)
throws serviceexception, remoteexception{
string url = “http://localhost:7001/ejb/purchaseorderservice?wsdl”;
purchaseorderservice service = new purchaseorderservice_impl(url);
purchaseorderport port = service.getpurchaseorderport();
string teststring = “this is my test string ;-)”;
system.out.println(port.toupper(teststring));
}
}
这里面的内容和在javabean中也没什么区别。因此我们可以看出来,在web service后端使用什么方式实现,在前端看是完全透明的。
4. 运行测试类观察结果
右键点文件testdriver_ejb.java,选择“run as…=> java application”。这时我们在console能看到运行结果。如果一切正确:
this is my test string ;-)
到此,我们完成了这个基于ejb的web services的例子。事实上我们可以用各种方法创建web services的业务逻辑,从而轻松的实现系统组件间的松耦合。
闽公网安备 35060202000074号