跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
Beehive中的Web服务开发

时间:2005-04-18
作者:肖菁
浏览次数:
本文关键字:
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章
    Beehive中的Web服务开发工作集中在JWS文件的处理上,极大的简化了Web服务的开发过程,降低了提供Web服务的门槛。作者在本文中以一个简单的例子详细的介绍了如何使用JWS文件来实现Web服务开发的过程。

关键词: Beehive Web服务
1 概述

  通常一个Web服务的开发过程需要两个步骤:
  1、 JavaBean编写
  Web服务提供者编写一系列的JavaBean,实现需要发布为Web服务的功能,确定Web服务的需要接受的参数、返回参数类型等。
  2、 发布Web服务
  通常在编写完成后,还需要修改相关的配置文件声明将JavaBean中的某些方法发布为Web服务,这个过程工作比较多,下面的内容通常是需要准备的--发布JavaBean方法的元素、Web服务的输入参数、Web服务的输出参数,如果Web服务的输入、输出参数是Java类、集合类型等,还需要进行专门的映射元素的准备工作。
  在Beehive框架中,Web服务的开发就简单多了,工作内容变成了维护一些JWS(Java Web Services)文件,发布Web服务所需要的配置文件的准备工作都是Beehive框架的编译过程自动完成的。

1.1 JWS文件
  JWS(Java Web Service)是Beehive中Web服务的核心,一个JWS文件就是一个加入了一些注释的Java文件, Beehive框架下开发Web服务的所有工作都在这个文件中完成。
  JWS文件中需要发布和不需要发布的方法的编写方式和普通的Java方法没什么不同,只是会加入一些注释信息,描述这些被发布方法在被发布时候的一些配置信息。

1.2 JWS文件中的注释信息
  JWS中的注释信息分为四类:WSDL映射、SOAP绑定、安全和消息处理。简单的Web服务开发,我们只需要WSDL映射中的两个注释信息:@WebService和@WebMethod。

  1.2.1 @WebService

  这个注释放置在Java类生命的前面,声明这个类的部分方法可以被发布为Web服务,下面是后面例子中的代码片断:

@WebService(targetNamespace="http://www.vivianj.org/samples/wsm")
public class Service{

  @WebService也有五个属性,用于设置Web服务被发布时的一些配置信息,常用的属性说明如下,讲叙如何开发Web服务的时候将详细解释如何使用这些属性:
  1. name
  Web服务的名字,WSDL中wsdl:portType元素的name属性和它保持一致,默认是Java类或者接口的名字。
  2. serviceName
  Web服务的服务名,WSDL中wsdl:service元素的name属性和它保持一致,默认是Java类的名字+”Service”。
  3. targetNamespace
  WSDL文件所使用的namespace,该Web服务中所产生的其他XML文档同样采用这个作为namespace。

  1.2.2 @WebMethod
  这个注释放在需要被发布成Web服务的方法前面,声明接下来的这个类将被发布成Web服务,下面是后面例子中的代码片断:

@WebMethod
public String sayHelloWorld() {
return "Hello World!";
}

  同样的,@Method也有自己的属性:action和operationName:operationName声明了wsdl文件中该方法对应的wsdl:operation元素的name属性的内容,默认是Java方法的名字;action用于说明SOAP绑定中SOAPAction的属性设置。

2 Web服务开发实例
  我们将开发一个简单的Web服务,详细的演示如何使用JWS文件来实现Web服务的全过程,并且给出了如何生成客户端测试代码来测试被发布Web服务的过程,最后将测试我们发布的Web服务。
  开发的Web服务模拟了Web服务中的主要场景:
  1. 客户端向服务端发送无参数请求
  2. 客户端向服务端发送携带简单类型参数的请求
  3. 客户端向服务器发送携带Java类参数的请求
  4. 服务器端向客户端发送基本类型的返回信息
  5. 服务器端向客户端发送Java类的返回信息
  6. 服务器端向客户端发送数组类型的返回信息
  2.1 实例环境说明
  作者的例子将从Beehive提供的例子wsm-blank应用开始,Web容器采用Tomcat,操作系统采用Windows2000。
  本文中作者默认你的wsm-blank应用已经在Tomcat上配置完成上下文路径是wsm,并且能够正确运行。如果你的Web服务应用还没有能够运行起来,请参考作者的另一篇文章《Beehive入门》。
  2.2 JWS文件分析
  下面这个JWS文件是作者编写的一个JWS文件(保存在%tomcat_home%\webapps\wsm\WEB-INF\src\samples目录下),里面有五个被发布为Web服务的方法,分别演示上面列出的一种或者两种应用场景。
  JWS文件的源代码如下,文件的注释部分分析了JWS的使用情况:

package samples;

import org.vivianj.beehive.samples.wsm.data.*;
import javax.jws.WebMethod;
import javax.jws.WebService;
/*
* 下面的@Service是JWS的注释信息
* 表明这个类中的某些方法可能被发布成Web服务
* 紧跟着括号内的部分表示设置@Service的targetNameSpace属性
*/
@WebService(targetNamespace="http://www.vivianj.org/samples/wsm")
public class Service{
/*
* 下面的@WebMethod是JWS的注释信息
* 表明这个紧跟着这个方法被发布成Web服务
* sayHelloWorld演示了客户端发送无参数请求、服务器端向客户端发送
* 基本类型(String)的返回信息的应用场景
*/
       @WebMethod
    public String sayHelloWorld() {
       return "Hello World!";
    }
/*
* sayHelloWorldTo
演示了客户端向服务端发送携带简单类型参数的请求、
*
服务器端向客户端发送基本类型(
String
)的返回信息的应用场景
*/
    @WebMethod
    public String sayHelloWorldTo(String who) {
       return "Hello " + who + "!";
    }
/*
* registerCustomer
演示了客户端向服务端发送携带
Java
类参数的请求的
*
应用场景
*/
    @WebMethod
    public void registerCustomer(Customer customer) {
       CustomerHelper.add(customer);
    }
/*
* getCustomer
演示了客户端向服务端发送携带简单类型参数的请求、
*
服务器端向客户端发送
Java
类(
Customer
)的返回信息的应用场景
*/
    @WebMethod
    public Customer getCustomer(int location) {
       return CustomerHelper.getByLocation(location);
    }
/*
* getAll
演示了服务器端向客户端发送
Java
类数组(
Customer[]
)的
*
返回信息的应用场景
*/
    @WebMethod
    public Customer[] getAll() {
       return CustomerHelper.getAll();
    }
}

  2.3 Web服务发布
  要发布这个开发的Web服务,只需要使用beehive中提供的编译这个Web应用就可以了,编译指令如下:

ant -f %BEEHIVE_HOME%\ant\buildWebapp.xml -Dwebapp.dir=%tomcat_home%\webapps\wsm build.webapp

  [注] 相应的工具准备和环境变量设置等工作请参考作者的另一篇文章《beehive入门》中的“让Web服务的例子跑起来”章节中的内容。

  2.4 客户端代码生成
  Web服务开发、发布已经完成,自己编写客户端访问代码是个麻烦的事情,还好beehive中已经提供了相应的通过JWS文件生成客户端访问代码的ant脚本文件。进入%tomcat_home%\webapps\wsm\WEB-INF目录下,可以看到里面有个client-build.xml,这个就是我们可以利用的ant脚本文件了。
  默认情况下,这个xml文件的内容是这样的:

<?xml version="1.0" ?>
<project name="AddressBookClient" basedir="." default="all">

<property name="AddressBook.wsdl.url"
value="http://localhost:8080/wsm-blank/template/Blank.jws?wsdl" />

   <path id="jars">
           <fileset dir="lib">
               <include name="**/*.jar"/>
           </fileset>
       </path>
     <taskdef name="wsdl2java" classname="org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask" loaderref="axis" >
        <classpath refid="jars"/>
       </taskdef>
       <target name="clean">       
       <delete dir="build" />
       </target>   
       <target name="dirs">       
       <mkdir dir="build" />       
       <mkdir dir="build/generated" />       
       <mkdir dir="build/classes" />
         </target>
       <target name="all" depends="genClient, compile, test"/>
       <target name="genClient" depends="dirs">
           <wsdl2java url="${AddressBook.wsdl.url}" output="build/generated" testcase="yes">
           </wsdl2java>
       </target>    
       <target name="compile" depends="genClient">  
           <javac srcdir="build/generated" destdir="build/classes" classpathref="jars" failonerror="true"  source="1.4"  />
          </target>
       <target name="test" depends="compile">
       <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
               <classpath>
                     <pathelement location= "build/classes"/>
                     <path refid="jars"/>
                 </classpath>
                  <batchtest fork="yes" todir=".">
      <fileset dir="build/classes">
        <include name="**/*Test*.class"/>
      </fileset>          
    </batchtest>
       </junit>  
       </target>       
</project>

  这个脚本生成了客户端访问指定Web服务(由XML文件中的AddressBook.wsdl.urld的属性确定,见上面的灰色背景部分显示的内容)所需要的客户端代码,并且生成了一个junit测试,用于测试生成的Web服务。
  我们要做的工作就是下面三个简单的步骤:
  1. 启动Tomcat服务器
  2. 修改XML中AddressBook.wsdl.urld的value属性为http://loclahost:8080/wsm/wsamples/Service.jws?wsdl
  3. 执行ant任务
  现在你可以进入%tomcat_home%\webapps\wsm\WEB-INF目录,执行下面的指令生成Web服务的客户端代码和测试代码:

Ant –f client-build.xml compile

  生成的客户段访问代码和测试代码位于%tomcat_home%\webapps\wsm\WEB-INF\build\generated目录下。
  [注] 执行compile任务的时候会编译生成的测试代码,所以你需要拷贝一个junit.jar到%tomcat_home%\webapps\wsm\WEB-INF\lib目录下。

  2.5 测试
  测试代码已经生成了(位于%tomcat_home%\webapps\wsm\WEB-INF\build\generated目录下),要运行测试代码,我们还需要下面几个步骤:
  1、修改生成的测试代码
  不过在运行之前还需要一些修改工作,因为自动生成的测试代码中没有加入测试用例和所需要的判断语句,下面是作者的修改过的测试代码,里面灰色背景的内容是在生成的测试代码基础上增加或者修改的:

/**
* ServiceServiceTestCase.java
*
* This file was auto-generated from WSDL
* by the Apache Axis 1.2RC1 Oct 29, 2004 (04:30:47 EDT) WSDL2Java emitter.
*/

package org.vivianj.www.samples.wsm;

public class ServiceServiceTestCase extends junit.framework.TestCase {
    public ServiceServiceTestCase(java.lang.String name) {
        super(name);
    }
 
    public void testServiceWSDL() throws Exception {
        javax.xml.rpc.ServiceFactory serviceFactory = javax.xml.rpc.ServiceFactory.newInstance();
        java.net.URL url = new java.net.URL(new org.vivianj.www.samples.wsm.ServiceServiceLocator().getServiceAddress() + "?WSDL");
        javax.xml.rpc.Service service = serviceFactory.createService(url, new org.vivianj.www.samples.wsm.ServiceServiceLocator().getServiceName());
        assertTrue(service != null);
    }
 
    public void test1ServiceGetAll() throws Exception {
        org.vivianj.www.samples.wsm.ServiceSoapBindingStub binding;
        try {
            binding = (org.vivianj.www.samples.wsm.ServiceSoapBindingStub)
                          new org.vivianj.www.samples.wsm.ServiceServiceLocator().getService();
        }
        catch (javax.xml.rpc.ServiceException jre) {
            if(jre.getLinkedCause()!=null)
                jre.getLinkedCause().printStackTrace();
            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
        }
        assertNotNull("binding is null", binding);
 
        // Time out after a minute
        binding.setTimeout(60000);
 
        // Test operation
        org.vivianj.beehive.samples.wsm.data.Customer[] value = null;
        value = binding.getAll();
        // TBD - validate results

      // 遍历服务器端返回的所有信息,打印 Customer 对象的 nickname 属性
      // 根据实际情况可以增加 assertEquals 判断

               If (value!=null){
       For(int I = 0;i<value.length;i++){       
       org.vivianj.beehive.samples.wsm.data.Customer customer = (org.vivianj.beehive.samples.wsm.data.Customer) value[i];       
       System.out.println(“customer’s nickname is ” + customer.getNickName());
}
}
    }

    public void test2ServiceSayHelloWorld() throws Exception {
        org.vivianj.www.samples.wsm.ServiceSoapBindingStub binding;
        try {
            binding = (org.vivianj.www.samples.wsm.ServiceSoapBindingStub)
                          new org.vivianj.www.samples.wsm.ServiceServiceLocator().getService();
        }
        catch (javax.xml.rpc.ServiceException jre) {
            if(jre.getLinkedCause()!=null)
                jre.getLinkedCause().printStackTrace();
            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
        }
        assertNotNull("binding is null", binding);
 
        // Time out after a minute
        binding.setTimeout(60000);
 
        // Test operation
        java.lang.String value = null;
        value = binding.sayHelloWorld();
        // TBD - validate results

        String experted = “Hello World!”;
           assertEquals(experted,value);

    }
 
    public void test3ServiceSayHelloWorldTo() throws Exception {
        org.vivianj.www.samples.wsm.ServiceSoapBindingStub binding;
        try {
            binding = (org.vivianj.www.samples.wsm.ServiceSoapBindingStub)
                          new org.vivianj.www.samples.wsm.ServiceServiceLocator().getService();
        }
        catch (javax.xml.rpc.ServiceException jre) {
            if(jre.getLinkedCause()!=null)
                jre.getLinkedCause().printStackTrace();
            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
        }
        assertNotNull("binding is null", binding);
 
        // Time out after a minute
        binding.setTimeout(60000);
 
        // Test operation
        java.lang.String value = null;

        value = binding.sayHelloWorldTo(“ws”);
        // TBD - validate results
           String experted = “Hello ws!”;
           assertEquals(experted,value);

    }
 
    public void test4ServiceRegisterCustomer() throws Exception {
        org.vivianj.www.samples.wsm.ServiceSoapBindingStub binding;
        try {
            binding = (org.vivianj.www.samples.wsm.ServiceSoapBindingStub)
                          new org.vivianj.www.samples.wsm.ServiceServiceLocator().getService();
        }
        catch (javax.xml.rpc.ServiceException jre) {
            if(jre.getLinkedCause()!=null)
                jre.getLinkedCause().printStackTrace();
            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
        }
        assertNotNull("binding is null", binding);
 
        // Time out after a minute
        binding.setTimeout(60000);
 
        // Test operation

// 向服务器发送增加一个 Customer 对象的请求,参数为 Customer 实例
org.vivianj.beehive.samples.wsm.data.Customer  customer = new org.vivianj.beehive.samples.wsm.data.Customer();
customer.setNickName(“vivianj”);
customer.setPassword(“wsm”);
        binding.registerCustomer(customer);

        // TBD - validate results

             }
 
    public void test5ServiceGetCustomer() throws Exception {
        org.vivianj.www.samples.wsm.ServiceSoapBindingStub binding;
        try {
            binding = (org.vivianj.www.samples.wsm.ServiceSoapBindingStub)
                          new org.vivianj.www.samples.wsm.ServiceServiceLocator().getService();
        }
        catch (javax.xml.rpc.ServiceException jre) {
            if(jre.getLinkedCause()!=null)
                jre.getLinkedCause().printStackTrace();
            throw new junit.framework.AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
        }
        assertNotNull("binding is null", binding);
 
        // Time out after a minute
        binding.setTimeout(60000);
 
        // Test operation
        org.vivianj.beehive.samples.wsm.data.Customer value = null;
        value = binding.getCustomer(0);
        // TBD - validate results

      
       String nickname = “vivianj”;
String password = “wsm”;
assertEquals(nickname,value.getNickName());
assertEquals(password,value.get Password ());
    }
}

  2. 准备环境
  代码修改成功,还需要准备一下环境才能开始执行测试代码:因为junit不是ant的内置任务,所以你需要拷贝一份junit.jar到%ant_home%\lib目录下。
  3. 运行测试任务
现在你可以运行下面的ant任务来完成测试工作:
Ant –f client-build.xml test

3 总结
  Beehive中的Web服务开发非常简单和高效,Web服务的开发和发布过程被聚合到JWS文件的编写、编译中。
  文章中简单的介绍了beehive中Web服务开发的核心部分—JWS文件,通过一个简单的例子,模拟了Web服务提供需要面对的常用应用场景,演示了如何编写、注释JWS文件来实现Web服务的全过程。

 作者简介
icon
肖菁
肖菁 是唯J族(www.vivianj.org)创始人,BEA 杭州User Group负责人,自由撰稿人,开源项目BuildFileDesigner(buildfiledesign.sourceforge.net)和V-Security(v-security.sourceforge.net)创始人。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分

   
相关产品