First Previous Next Last Development Guide  

CHAPTER 9    Generating Web Services

This chapter walks you through the basic steps and typical scenarios for using the Web Service Wizard to generate Web Services from a variety of sources. Topics include:

For more information    To learn about the steps and scenarios for using the wizard when you want a program to access Web Services, see Generating Web Service Consumers.

 
Top of page

Basics

You can use the Web Service Wizard of Workbench to develop standard (SOAP-based) Web Services that are implemented as Java remote objects (using RMI). The wizard generates Java source files based on JAX-RPC (Java API for XML-based RPC) and jBroker Web (the JAX-RPC implementation included with Novell exteNd). JAX-RPC is the J2EE specification that provides Web Service support.

The generated files include a servlet to handle access to your Web Service and its methods from HTTP SOAP requests. You can use the generated files as is or modify them when necessary. The advantage of this Java-oriented approach is that you can deal with Web Services using the familiar technologies of RMI and J2EE instead of coding lower-level SOAP APIs.

For more information    For an introduction to Web Service concepts, standards, and technologies, see Understanding Web Services.

For more information    For detailed documentation on the wizard, see the Web Service Wizard chapter in the Tools Guide.

 
Top of page

Steps

The complete development process involves:

  1. Preparing to generate

  2. Generating Web Service files

  3. Examining the generated files

  4. Editing the generated files

  5. Using the generated files

 
Top of section

Preparing to generate

To prepare for using the Web Service Wizard, you:

  1. Set up a WAR project in Workbench.

    For each Web Service you generate, the wizard creates a servlet to handle access to that Web Service (from HTTP SOAP requests). As a result, a WAR is required to package your Web Services (one or more per WAR) for deployment to a J2EE server where they will run.

    A possible variation is to set up a JAR subproject in your WAR and use that JAR to contain the servlet and other classes for a Web Service. In any case, the servlet mapping will be in the WAR's deployment descriptor (web.xml).

    (Note that the approach of using a JAR subproject is not currently supported by the Web Service Wizard when you generate a Web Service from a WSDL file. In this situation, it only supports a WAR project.)

  2. Add these files to the project:

    Files

    Details

    Source files, classes, or archives from which your Web Services are to be generated

    You can generate a Web Service from any one of the following:

    • A JavaBean or other Java class

    • An EJB session bean

    • A Java remote interface

    • A WSDL file

    No matter which one you provide, it should (at minimum) declare the methods you want your generated Web Service to expose.

    Compile your Java files    If you provide any Java files, make sure you compile them in your project before starting the Web Service Wizard (because the wizard works from compiled classes).

    Edit your WSDL bindings    If you provide any WSDL files, edit them as needed to make sure the SOAP address in the service definition specifies the correct binding URL. The Web Service Wizard will use this URL in the files it generates for your Web Service.

    Archives required by jBroker Web:

    • jbroker-web.jar, which contains the jBroker Web API classes needed at runtime

    • jaxrpc-api.jar and saaj-api.jar, which contain the Java API classes for XML-based RPC and SOAP processing

    • xerces.jar or another XML parser

    You'll find these JARs in the Workbench compilelib directory. Depending on your J2EE server configuration, you should do one of the following:

    • Add them to the WEB-INF/lib directory of your WAR project

    • Add them to the server classpath of your J2EE server

    For more information    For more information, see the chapter on archive deployment in the Tools Guide.

  3. Edit the classpath of your project so you can compile your Web Service classes once they're generated and edited. You'll need to include:

If you use SOAP message handlers (an advanced JAX-RPC feature) in your application, the project will also require the following archives: activation.jar, commons-logging.jar, dom4j.jar, jaxp-api.jar, and saaj-ri.jar. You'll find these JARs in the Workbench compilelib directory.

 
Top of section

Generating Web Service files

Once you've set up your WAR project, you're ready to use the Web Service Wizard. The wizard produces one Web Service at a time, so you'll need to use it multiple times if you have several to develop.

Each time you launch the wizard, it takes input from you about the kind of Web Service to produce. It then generates a set of source files that together make up the Web Service. Here's a summary of the process:

  1. Select File>New to display the New File dialog and go to the Web Services tab.

  2. Launch the Web Service Wizard by doing one of the following:

    To generate a Web Service from

    Select

    One of these:

    • A JavaBean or other Java class

    • An EJB session bean

    • A Java remote interface

    New Web Service

    A WSDL file

    Existing Web Service

    As its name suggests, this item is mainly used to generate Web Service consumers that access deployed Web Services (based on their WSDL files). But it can also be used to read WSDL files as blueprints and generate the matching Web Services themselves.

  3. When the wizard prompts you for project location information, specify:

    If you specify a JAR project to contain the generated Web Service files, the wizard will also ask you for a WAR project to map the Web Service's servlet.

  4. When the wizard prompts you, select the class or WSDL file to generate the Web Service from.

    The wizard then asks for additional information based on your selection:

    If you select

    The wizard prompts you to specify

    A JavaBean or other Java class

    • Which methods to expose in the generated Web Service (in contrast, when you generate from an EJB, remote interface, or WDSL file, all methods are automatically exposed)

    • Class-generation and SOAP options

    The home interface of an EJB session bean

    • Lookup information for the EJB

    • Class-generation and SOAP options

    The remote interface of an EJB session bean or the SessionBean class itself

    • The home interface of the EJB session bean

    • Lookup information for the EJB

    • Class-generation and SOAP options

    A Java remote interface

    • Class-generation and SOAP options

    A WSDL file

    • Class-generation and SOAP options

  5. When the wizard prompts you for class-generation and SOAP options, you need to choose and configure the set of source files to generate for your Web Service.

    The most important choice is whether to generate skeletons to be tie-based or not. The answer depends on the architectural model you want the implementation of your Web Service to follow. See Choosing an implementation model.

    You can choose to generate stubs (which come with a simple client application) for testing your Web Service. When generating from a Java class, you can also request a WSDL file (for publishing the Web Service to a registry) as well as specify the binding style (document or RPC) and service address (URL) for the Web Service. When generating from a WSDL file, you can specify how complex types are to be mapped.

    NOTE:   Support for jBroker Web 1.x applications is available via a backward-compatibility option. For more information, see If you choose jBroker Web 1.x compatibility.

  6. Click Finish when you're done specifying options for the Web Service.

 
Top of section

Examining the generated files

When you finish the wizard, it generates everything you've specified for your Web Service and updates other parts of your project with supporting changes:

What the wizard generates

Details

Java source file for remote interface

xxxWS.java    This file is automatically generated whenever your input to the wizard is not a remote interface (such as when you start from a JavaBean, Java class, EJB session bean, or WSDL file). That's because a remote interface (which extends java.rmi.Remote and declares the methods to expose) is required to construct your Web Service.

When you start from a WSDL file, the name of the generated remote interface is simply xxx.java.

Java source file for skeletons

xxx_ServiceSkeleton.java    Abstract servlet class that handles access to the Web Service (from HTTP SOAP requests).

In the tie model, xxx_ServiceTieSkeleton extends this class. In the skeleton model, you extend it yourself (with an implementation of your remote interface).

Java source files for tie-based skeletons

xxx_ServiceTieSkeleton.java    Abstract servlet class that extends xxx_ServiceSkeleton.

xxxTie.java    Servlet that's used in the tie model as the front end for the Web Service. It extends xxx_ServiceTieSkeleton to handle access to the Web Service (from HTTP SOAP requests). It delegates to one of the following to process method calls for the Web Service:

  • If you start with a JavaBean, Java class, or EJB session bean, xxxTie instantiates xxxDelegate and delegates to it.

  • If you start with a Java remote interface or WSDL file, you must edit the xxxTie.java file to specify a class of your own to instantiate and delegate to.

xxxDelegate.java    This file is generated if you start with a JavaBean, Java class, or EJB session bean that implements the methods for your Web Service. xxxDelegate instantiates that implementation class and calls those methods on it.

With an EJB session bean, xxxDelegate does a lookup and create to get the remote interface object. Then it uses that object to make the method calls.

Java source files for stubs

xxxService.java    Service interface used by JAX-RPC clients to obtain the stub for the target Web Service.

xxxServiceImpl.java    Service implementation class that handles instantiation of the stub (xxx_Stub). It also supports alternative ways of accessing the target Web Service, including dynamic (stubless) calls.

(Note that when you start from a WSDL file, the names generated for the service interface and implementation class depend on your WSDL and may omit the text Service.)

xxx_Stub.java    Facilitates method calls from a Java-based consumer to the target Web Service. xxx_Stub implements the remote interface corresponding to the Web Service by sending an appropriate HTTP SOAP request for each method call.

xxxClient.java    Simple client application that works as a consumer of the target Web Service. It obtains the stub (via the Service object), then uses the stub to call Web Service methods.

You can run xxxClient from Workbench (select Project>Run Web Service Client Class) or from a command line.

WSDL file

xxx.wsdl    For use when publishing your Web Service to a registry. It describes the Web Service in a standard format.

Updates to deployment descriptor

In the tie model (when you generate tie-based skeletons), the wizard updates your WAR project's web.xml file to declare xxxTie as the servlet to handle HTTP SOAP requests for your Web Service.

In the skeleton model, you must edit web.xml yourself to declare the servlet to use (your class that extends xxx_ServiceSkeleton).

Updates to project contents

The wizard updates your project to add generated files (and other application-specific files) to it.

Updates to project classpath

The wizard updates your project classpath to include application-specific files as needed.

About generated file names

When generating file names, the Web Service Wizard follows the naming rules specified by JAX-RPC. If you start with a Java class, the resulting file names are based on the name of that class. If you start with WSDL, the resulting file names are based on the definitions in that WSDL.

For simplicity, this documentation uses xxx to represent the portion of a generated Web Service file name that's derived from a class name or WSDL definition.

Additional details of generation

Under the covers, the Web Service Wizard uses the jBroker Web compilers when generating the Web Service files listed above. In some cases, these compilers may generate additional code or files to support requirements specific to your application, such as:

For more information    For more information, see the jBroker Web help.

If you choose jBroker Web 1.x compatibility

The current version of jBroker Web provides a high degree of backward compatibility with earlier versions. However, some changes introduced to support the JAX-RPC standard may require you to modify code when upgrading an application that originated in jBroker Web 1.x. These changes involve the conventions used for:

Although it's recommended that you upgrade to the current jBroker Web and JAX-RPC conventions, it's not required. By using the jBroker Web 1.x compatibility option in the Web Service Wizard, you can generate Web Service files according to the original jBroker Web conventions for file names and stub access. This enables you to take advantage of all the other improvements in the latest version of jBroker Web without altering your existing 1.x applications.

Generated 1.x-compatible files   The following table describes the files generated when you use the jBroker Web 1.x compatibility option:

With 1.x compatibility on, you get

With 1.x compatibility off, this is named

Details

xxx_REMOTE.java

Example:

  MyObject_REMOTE.java

xxxWS.java

Example:

  MyObjectWS.java

Generated remote interface

_xxx_ServiceSkeleton.java

Example:

  _MyObject_REMOTE_ServiceSkeleton.java

xxx_ServiceSkeleton.java

Example:

  MyObjectWS_ServiceSkeleton.java

Abstract servlet class

_xxx_ServiceTieSkeleton.java

Example:

  _MyObject_REMOTE_ServiceTieSkeleton.java

xxx_ServiceTieSkeleton.java

Example:

  MyObjectWS_ServiceTieSkeleton.java

Abstract tie servlet class

xxx_TIE.java

Example:

  MyObject_TIE.java

xxxTie.java

Example:

  MyObjectWSTie.java

Servlet for the Web Service (in the tie model)

xxx_SERVICE.java

Example:

  MyObject_SERVICE.java

xxxDelegate.java

Example:

  MyObjectWSDelegate.java

Delegate class for the tie servlet

xxxService.java

Example:

  MyObjectREMOTEService.java

xxxService.java

Example:

  MyObjectWSService.java

Service interface for the stub

This class is not used in 1.x-style stub access. It is generated in case you want to upgrade your client code to the JAX-RPC approach.

xxxServiceImpl.java

Example:

  MyObjectREMOTEServiceImpl.java

xxxServiceImpl.java

Example:

  MyObjectWSServiceImpl.java

Service implementation class for the stub

This class is not used in 1.x-style stub access. It is generated in case you want to upgrade your client code to the JAX-RPC approach.

_xxx_ServiceStub.java

Example:

  _MyObject_REMOTE_ServiceStub.java

xxx_Stub.java

Example:

  MyObjectWS_Stub.java

Stub for the Web Service

xxx_CLIENT.java

Example:

  MyObject_CLIENT.java

xxxClient.java

Example:

  MyObjectWSClient.java

Client application for consuming the Web Service

The 1.x-compatible client obtains the stub directly via a JNDI lookup. In contrast, the JAX-RPC client obtains the stub indirectly via the Service object.

xxx.wsdl

Example:

  MyObject_REMOTE.wsdl

xxx.wsdl

Example:

  MyObjectWS.wsdl

WSDL file for the Web Service

 
Top of section

Editing the generated files

Follow these guidelines when editing the files generated by the Web Service Wizard:

Guideline

Details

File you may need to edit

File you must edit

Files you should not edit

  • xxx_ServiceSkeleton.java

  • xxx_ServiceTieSkeleton.java

  • xxxService.java

  • xxxServiceImpl.java

  • xxx_Stub.java

It's OK to edit any of the other generated files, but not typically required.

In some cases, completing the implementation of your Web Service may require you to add one or more manually coded files to work with the generated ones. See Creating additional files.

Editing the xxxTie.java file

The generated xxxTie.java file includes a couple of methods you may need to edit.

init() method

If you start with a JavaBean or Java class, init() is generated to call the setTarget() method of xxx_ServiceTieSkeleton and pass an instance of xxxDelegate (to delegate to it). If xxxDelegate provides an empty constructor, the generated code uses that constructor to do the instantiation.

But if no implicit or explicit empty constructor is available, you must modify the code to indicate which one to use. You may also want to modify it to use a constructor that expects an argument.

The wizard automatically generates calls to setTarget() for every public constructor of xxxDelegate. Each line is commented out—except the one that uses the empty constructor (if available). Uncomment the line with the constructor you want and make any related changes:

  //super.setTarget( new MyObjectWSDelegate(  java.lang.String arg0) );
  //super.setTarget( new MyObjectWSDelegate(  java.lang.String arg0, java.lang.String arg1) );
  super.setTarget( new MyObjectWSDelegate( ) );

If you start with a Java remote interface or WSDL file, init() is always generated with the setTarget() call commented out. In this case, you must provide a class of your own to instantiate and delegate to:

  //super.setTarget(new CONSTRUCT_YOUR_SERVICE_OBJECT_HERE);

If you start with an EJB session bean, you shouldn't need to edit the generated init() method.

doGet() method

This method is generated to handle HTTP GET requests sent to your Web Service. It returns the WSDL file for the Web Service, if available. Otherwise, it notifies the user that GET requests are not supported.

If you want to implement your own HTTP GET behavior, you can customize the doGet() code. If you want to use the default SOAP behavior, you can remove this code or comment it out.

Editing the xxxClient.java file

Before you can test your Web Service with xxxClient, you must edit the generated xxxClient.java file to call one or more methods of the Web Service. Look for the process() method in this file and you'll find comments listing all of the possible method calls:

  // System.out.println("Test Result = " + remote.getString());
  // System.out.println("Test Result = " + remote.setString(java.lang.String));
  // System.out.println("Test Result = " + remote.sayHello());

Uncomment the method call(s) you want to test and supply appropriate argument values, as needed:

  // System.out.println("Test Result = " + remote.getString());
  System.out.println("Test Result = " + remote.setString(args[0]));
  System.out.println("Test Result = " + remote.sayHello());

For more information    For additional changes you may want to make to the generated xxxClient.java file, see Generating Web Service Consumers.

Creating additional files

In many scenarios, once the wizard finishes generating, you'll have all of the Java source files you need for your Web Service. But there are cases where you must code additional classes yourself:

In this case

You must add

When using the skeleton model

A class that extends the generated servlet xxx_ServiceSkeleton and implements the remote interface for your Web Service. You'll use this manually coded class as the servlet for the Web Service.

When using the tie model and starting with a Java remote interface or WSDL file

A class that implements the remote interface for your Web Service. You must edit the generated xxxTie.java file to instantiate this manually coded class and delegate to it.

 
Top of section

Using the generated files

To use the Web Service files generated by the wizard, you:

  1. Update the deployment descriptor, if necessary.

    When you use the tie model, the wizard automatically updates the WAR project's web.xml file with the appropriate servlet mapping for your Web Service. But with the skeleton model, you must edit web.xml yourself to supply this information.

    In the following example, MyService is the servlet class that the developer has coded for the Web Service MyRemote:

      <servlet>
         <servlet-name>MyService</servlet-name>
         <servlet-class>com.exsamp.rem.MyService</servlet-class>
      </servlet>
      
      <servlet-mapping>
         <servlet-name>MyService</servlet-name>
         <url-pattern>MyRemote</url-pattern>
      </servlet-mapping>
    
  2. Update the project, if necessary.

    As the wizard works, it automatically adds files to your project classpath and contents, as needed. But you should also check yourself to make sure the project has everything it requires to compile and run.

    For instance, if your Web Service accesses an EJB session bean, the EJB-client JAR file should be on your project's classpath.

    For more information    For details on setting up the required classpath and contents for your project (including what jBroker Web needs), see Preparing to generate.

  3. Build and archive the project.

    When you complete this step, you'll have a WAR file containing the Web Service(s) you've generated.

  4. Set up for deployment to your J2EE server.

    Prepare the server-specific deployment information required to deploy the WAR to your J2EE server. For example, if you're going to deploy to the Novell exteNd Application Server, create an exteNd deployment plan file.

    If you're going to deploy from Workbench, you should also set up a server profile for your J2EE server.

  5. Deploy the WAR to your J2EE server.

    When you complete this step, each Web Service in the WAR will be accessible as a servlet that can respond to standard HTTP SOAP requests for your exposed methods.

  6. Test your Web Service(s) running on the J2EE server.

    If you've generated, edited, and compiled the xxxClient class for a Web Service, you can use it for a quick test of your method calls. To run xxxClient from Workbench, select Project>Run Web Service Client Class. The Web Service Wizard Client Runner displays, offering you a list of client classes from the current project to choose from.

    You can also run xxxClient from a command line (providing that you include the appropriate directories and archives on your system classpath).

    For more information    For further details on running xxxClient, see Generating Web Service Consumers.

 
Top of page

Choosing an implementation model

There are two basic implementation models you can choose from when developing with the Web Service Wizard. This section explores these choices to help you select the one that's most appropriate for the Web Services you generate:

 
Top of section

Tie model

Here's an overview of the tie model and when to use it:

Topic

Details

Typical use

The tie model is typically used when you have an implementation class to provide as input to the Web Service Wizard. That might be a JavaBean, Java class, or EJB session bean that already implements the methods you want to expose as a Web Service.

How it works

The tie model uses a delegation approach to hand off method calls from the generated Web Service classes (which handle the HTTP SOAP processing for your Web Service) to your implementation class (which handles the method processing).

Advantages

The tie model enables you to keep your implementation class (business logic) separate from the generated infrastructure classes that support your Web Service. A related benefit is that you can reuse existing implementation classes currently accessible via other protocols.

How to generate it

When you specify class-generation and SOAP options in the Web Service Wizard, check both of these items:

  • Generate skeletons

  • Tie-based

Files generated

If you start with a JavaBean, Java class, or EJB session bean, the wizard generates:

  • xxxWS.java (remote interface)

  • xxxDelegate.java

  • xxxTie.java

  • xxx_ServiceTieSkeleton.java

  • xxx_ServiceSkeleton.java

It's possible (but not as common) to use the tie model when you have only a Java remote interface or WSDL file to provide as input to the Web Service Wizard. In this case, the wizard output leaves the delegation part of the model for you to complete later. You'll then need to code an implementation class and edit the generated tie class to instantiate it and delegate to it.

 
Top of section

Skeleton model

Here's an overview of the skeleton model and when to use it:

Topic

Details

Typical use

The skeleton model is typically used when you know the methods you want to expose as a Web Service, but don't yet have an implementation of them. In this case, you tell the Web Service Wizard about these methods by providing a Java remote interface or WSDL file as input, then implement them later in the context of the generated Web Service files.

How it works

In the skeleton model, you implement your Web Service methods by subclassing the servlet that the wizard generates to handle HTTP SOAP processing. As a result, the same class that supports the logistics of your Web Service also processes the method calls.

Advantages

The skeleton model is relatively simple, involving fewer classes to understand and maintain. At runtime, having less object overhead may also offer performance benefits.

How to generate it

When you specify class-generation and SOAP options in the Web Service Wizard, check both of these items:

  • Generate skeletons

  • Not tie-based

Files generated

If you start with a Java remote interface, the wizard generates:

  • xxx_ServiceSkeleton.java

If you start with a WSDL file, the wizard generates:

  • xxx.java (remote interface)

  • xxx_ServiceSkeleton.java

File you add

When the wizard is done, you must code a class that extends the generated servlet xxx_ServiceSkeleton and implements the remote interface for your Web Service. You'll use this manually coded class as the servlet for the Web Service.

 
Top of page

Scenario: starting with a Java class

In this scenario, you'll see how the Web Service Wizard can be used to generate a Web Service based on an existing Java class that implements the methods to expose:

Implementation model   This scenario illustrates use of the tie model. For an overview of that architecture, see Choosing an implementation model.

 
Top of section

Project setup

The WAR project for this scenario is set up as follows:

 
Top of section

Input to the wizard

Here's the input provided to the Web Service Wizard for this scenario:

MyObject class

MyObject is an existing Java class from which the Web Service is to be generated. It implements the methods to expose. MyObject.java contains the following code (which must be compiled before you start the wizard):

  package com.exsamp.obj;
  
  public class MyObject {
  
      private String s;
  
      public MyObject() {
      }
  
      public MyObject(String xxx) {
      }
  
      public MyObject(String xxx, String yyy) {
      }
  
      public String getString() {
          return s;
      }
  
      public boolean setString(String s) {
          this.s = s;
          return true;
      }
  
      public String sayHello() {
          return "Hello there, I am on the server";
      }
  }

Project location panel

This wizard panel is completed as follows:

GWSs1projloc

Class selection panel

This wizard panel is completed as follows:

GWSs1objsel

Method selection panel

This wizard panel is completed as follows:

GWSs1methsel

Class-generation and SOAP options panel

This wizard panel is completed as follows:

GWSs1objgen

 
Top of section

Generated files for the Web Service

Based on the input provided for this scenario, the Web Service Wizard generates these files to implement the Web Service:

MyObjectWS.java

MyObjectWS is the remote interface for the Web Service. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import java.rmi.Remote;
  import java.rmi.RemoteException;
  
  public interface MyObjectWS extends Remote
  {
      public java.lang.String getString( )
          throws RemoteException;
  
      public boolean setString( java.lang.String arg0 )
          throws RemoteException;
  
      public java.lang.String sayHello( )
          throws RemoteException;
  }

MyObjectWS_ServiceSkeleton.java

MyObjectWS_ServiceSkeleton is the abstract servlet class that handles access to the Web Service. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  
  import java.rmi.RemoteException;
  import java.util.Properties;
  import com.sssw.jbroker.web.encoding.TypeMappingRegistry;
  import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
  
  public abstract class MyObjectWS_ServiceSkeleton
      extends com.sssw.jbroker.web.portable.ServletSkeleton
      implements MyObjectWS
  {
      private static final com.sssw.jbroker.web.QName _portType =
          new com.sssw.jbroker.web.QName("urn:com.exsamp.obj.MyObject", "MyObjectWS");
      
      public MyObjectWS_ServiceSkeleton()
      {
          super(_portType);
          _setProperty("xmlrpc.schema.uri", "http://www.w3.org/2001/XMLSchema");
          _setProperty("version", "1.1");
      }
      
      private static java.util.Dictionary _atable = new java.util.Hashtable();
      static {
          _atable.put("\"urn:com.exsamp.obj.MyObject/setString\"", new java.lang.Integer(0));
          _atable.put("\"urn:com.exsamp.obj.MyObject/getString\"", new java.lang.Integer(1));
          _atable.put("\"urn:com.exsamp.obj.MyObject/sayHello\"", new java.lang.Integer(2));
      }
      
      private static java.util.Dictionary _mtable = new java.util.Hashtable();
      static {
          _mtable.put("setString", new java.lang.Integer(0));
          _mtable.put("getString", new java.lang.Integer(1));
          _mtable.put("sayHello", new java.lang.Integer(2));
      }
      
      public com.sssw.jbroker.web.portable.ServerResponse 
        _invoke(com.sssw.jbroker.web.portable.ServerRequest in) throws java.io.IOException
      {
          com.sssw.jbroker.web.portable.ServerResponse out = null;
          String soapEncURI = "soap";
          String literalURI = "literal";
          
          try {
              
              java.lang.Integer _m = null;
              String sac = in.getAction();
              if (sac != null) _m = (java.lang.Integer) _atable.get(sac);
              
              if (_m == null) {
                  sac = "\"" + sac + "\"";
                  _m = (java.lang.Integer) _atable.get(sac);
              }
              
              if (_m == null) {
                  String methodName = in.getMethod();
                  if (methodName != null) _m = (java.lang.Integer) _mtable.get(methodName);
              }
              
              if (_m == null) throw new 
                com.sssw.jbroker.web.ServiceException("unable to dispatch SOAP request");
              
              switch(_m.intValue()) {
                  
                  // setString
                  case 0: {
                      in.setEncodingStyleURI(soapEncURI);
                      java.lang.String _arg0 = null;
                      try {
                          _arg0 = (java.lang.String)
                          in.readObject(java.lang.String.class, "arg0");
                      } catch (java.io.EOFException eofExc) {
                          _arg0 = null;
                      }
                      boolean result = setString(_arg0);
                      //create reply
                      out = in.createReply();
                      //set the content type
                      java.lang.Object arg = null;
                      arg = new java.lang.Boolean(result);
                      out.writeObject(arg, "result");
                      break;
                  }
                  
                  // getString
                  case 1: {
                      in.setEncodingStyleURI(soapEncURI);
                      java.lang.String result = getString();
                      //create reply
                      out = in.createReply();
                      //set the content type
                      java.lang.Object arg = null;
                      arg = result;
                      out.writeObject(arg, "result");
                      break;
                  }
                  
                  // sayHello
                  case 2: {
                      in.setEncodingStyleURI(soapEncURI);
                      java.lang.String result = sayHello();
                      //create reply
                      out = in.createReply();
                      //set the content type
                      java.lang.Object arg = null;
                      arg = result;
                      out.writeObject(arg, "result");
                      break;
                  }
              }
              
          } catch (java.lang.Throwable ex) {
              if (System.getProperty("SOAP_DEBUG") != null) ex.printStackTrace();
              out = in.createExceptionReply();
              out.writeException(ex, "exception");
          }
          
          return out;
      }
      
      public boolean isDocument(String action)
      {
          return false;
      }
      
      
      private static Properties _rootHeaders = new Properties();
      static {
          _rootHeaders.setProperty("content-type", "text/xml; charset=UTF-8");
          _rootHeaders.setProperty("content-id", "<soapbody>");
      }
  }

MyObjectWS_ServiceTieSkeleton.java

MyObjectWS_ServiceTieSkeleton is an abstract class that extends MyObjectWS_ServiceSkeleton to support the tie model. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  
  import java.rmi.RemoteException;
  import java.util.Properties;
  import com.sssw.jbroker.web.encoding.TypeMappingRegistry;
  import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
  
  public abstract class MyObjectWS_ServiceTieSkeleton
      extends com.exsamp.obj.MyObjectWS_ServiceSkeleton
      implements com.sssw.jbroker.web.portable.TieSkeleton
  {
      private MyObjectWS _target;
      
      public void setTarget(java.rmi.Remote target)
      {
          _target = (MyObjectWS) target;
      }
      
      public java.rmi.Remote getTarget()
      {
          return _target;
      }
      
      public boolean setString(java.lang.String _arg0) 
          throws java.rmi.RemoteException
      {
          return _target.setString(_arg0);
      }
      
      public java.lang.String getString() 
          throws java.rmi.RemoteException
      {
          return _target.getString();
      }
      
      public java.lang.String sayHello() 
          throws java.rmi.RemoteException
      {
          return _target.sayHello();
      }
  }

MyObjectWSTie.java

MyObjectWSTie extends the abstract servlet classes to function as the front end for the Web Service. To process requests (method calls) it receives, this servlet instantiates and delegates to MyObjectWSDelegate. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.io.*;
  
  public class MyObjectWSTie extends MyObjectWS_ServiceTieSkeleton
  {
  
      public void init() throws ServletException
      {
          try
          {
              super.init();
  
              // The following are all public constructors for the implemented service
              // class. IMPORTANT NOTE: If available, the empty constructor has been
              // implemented by default. If no implicit or explicit empty constructor
              // is available, you *must* select one from the list below and uncomment
              // it in order to construct the generated service implementation.
  
              //super.setTarget( new MyObjectWSDelegate(  java.lang.String arg0) );
              //super.setTarget( new MyObjectWSDelegate(  java.lang.String arg0, java.lang.String arg1) );
              super.setTarget( new MyObjectWSDelegate( ) );
          }
          catch (Exception _e)
          {
              throw new ServletException(_e);
          }
      }
  
  
      // The following method may be freely modified to provide custom behavior
      // when an HTTP GET request is made. Comment-out or remove this method to
      // provide default SOAP doGet functionality.
      public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException
      {
          try
          {
              StringBuffer sb = new StringBuffer(1024);
              OutputStream out = null;
              InputStream in = null;
              String path = "/MyObjectWS.wsdl";
  
              try
              {
                  // Try to load the WSDL file.
                  in = getServletConfig().getServletContext().getResourceAsStream(path);
                  if (in == null)
                  {
                      // If it can't be found, return a default message.
                      sendDefaultMsg(response);
                  }
                  else
                  {
                      // Try to determine the WSDL file's character encoding for content-type.
                      byte[] buf = new byte[512];
                      int read = in.read(buf);
  
                      if (read <= 0)
                          sendDefaultMsg(response);
  
                      String cs = getXMLEncoding(buf);
                      StringBuffer ct = new StringBuffer(64);
                      ct.append("text/xml");
                      if (cs != null)
                      {
                          ct.append("; charset=");
                          ct.append(cs);
                      }
  
                      // Return the WSDL file.
                      response.setContentType(ct.toString());
                      out = response.getOutputStream();
                      do
                      {
                          out.write(buf, 0, read);
                      } while ((read = in.read(buf)) >= 0);
                  }
              }
              catch (Exception _e)
              {
                  throw new ServletException("Exception trying to return " + path, _e);
              }
              finally
              {
                  if (out != null)
                      out.close();
                  if (in != null) 
                      in.close();
              }
          }
          catch (Exception _e)
          {
              throw new ServletException(_e);
          }
      }
  
  
  
      // Try to determine the character encoding of this XML document.
      public static String getXMLEncoding(byte[] bytes)
      {
          String lsLine = "";
          String lsEncoding = "UTF-8";
  
          if (bytes.length >=2 && bytes[0]==0xFE && bytes[1]==0xFF)
              return "UTF-16";
          String lsState = "";
          int liDeclStart = 0;
          int liDeclLength = 0;
  
          for (int i=0; i < bytes.length; i++) 
          {
              if (lsState.equals("") && bytes[i] == '<' && bytes[i+1] == '?') 
              {
                  lsState = "<?";
              }
              else
              {
                  if (lsState.equals("<?") && bytes[i] == 'x' && bytes[i+1] == 'm'
                      && bytes[i+2] == 'l' && bytes[i+3] == ' ')
                  {
                      liDeclStart = i;
                      lsState = "xml";
                  }
                  else
                  {
                      if (lsState.equals("xml") && bytes[i] == '?' && bytes[i+1] == '>')
                      {
                          liDeclLength = i - liDeclStart;
                          break;
                      }
                  }
              }
          }
  
          lsLine = new String(bytes, liDeclStart, liDeclLength);
  
          int liPos = lsLine.indexOf("encoding");
          if (liPos > 0) 
          {
              lsLine = lsLine.substring(liPos + 8);
              int liEncStart = lsLine.indexOf('"');
              int liEncEnd = lsLine.indexOf('"', liEncStart +1);
              if (liEncStart < 0 && liEncEnd < 0)
              {
                  liEncStart = lsLine.indexOf("'");
                  liEncEnd = lsLine.indexOf("'", liEncStart +1 );
              }
  
              if (liEncStart >= 0 && liEncEnd >= 0)
                  lsEncoding = lsLine.substring(liEncStart + 1, liEncEnd);
          }
  
          return lsEncoding;
      }
  
  
  
      static private final String DEFAULT_MESSAGE = 
      "<html><head><title>Novell exteNd Web Service</title>" +
      "</head><body><h3 align=\"center\">Novell exteNd Web Service</h3>" +
      "By default, SOAP servers do not communicate via HTTP GET requests. The Novell " +
      "exteNd Web Service Wizard has generated an overloaded version of the " +
      "<i>doGet()</i> method for your convience. This method, found in your " +
      "generated _TIE code, is producing this message. If the WSDL file for this Web Service " +
      "is available in the root of your Web Service WAR, this method will return the WSDL instead " +
      "of this default message. You may add any custom code you like in your generated _TIE's " +
      "<i>doGet()</i> method to handle HTTP GET support.</body></html>";
  
      private void sendDefaultMsg(HttpServletResponse response) throws IOException
      {
          PrintWriter out = null;
  
          try 
          {
              response.setContentType("text/html"); 
              response.setContentLength(DEFAULT_MESSAGE.length());
              out = response.getWriter();
              out.print(DEFAULT_MESSAGE);
          }
          finally 
          {
              if (out != null) out.close();
          }
      }
  }

MyObjectWSDelegate.java

MyObjectWSDelegate instantiates the implementation class (MyObject) and makes the requested method calls against that instance. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import java.rmi.Remote;
  import java.rmi.RemoteException;
  
  public class MyObjectWSDelegate implements MyObjectWS
  {
      private MyObject m_objMyObject;
  
      public MyObjectWSDelegate( java.lang.String arg0 )
      {
          m_objMyObject = new MyObject( arg0 );
      }
  
      public MyObjectWSDelegate( java.lang.String arg0, java.lang.String arg1 )
      {
          m_objMyObject = new MyObject( arg0, arg1 );
      }
  
      public MyObjectWSDelegate( )
      {
          m_objMyObject = new MyObject(  );
      }
  
      public java.lang.String getString( )
          throws RemoteException
      {
          return m_objMyObject.getString(  );
      }
  
      public boolean setString( java.lang.String arg0 )
          throws RemoteException
      {
          return m_objMyObject.setString( arg0 );
      }
  
      public java.lang.String sayHello( )
          throws RemoteException
      {
          return m_objMyObject.sayHello(  );
      }
  }

MyObjectWS.wsdl

This generated file describes the Web Service in standard WSDL format (useful when publishing to a registry):

  <?xml version="1.0" encoding="UTF-8"?>
  <definitions name="MyObjectWSService"
   targetNamespace="urn:com.exsamp.obj.MyObject"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:tns="urn:com.exsamp.obj.MyObject"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <types/>
   <message name="setStringRequest">
    <part name="arg0" type="xsd:string"/>
   </message>
   <message name="setStringResponse">
    <part name="result" type="xsd:boolean"/>
   </message>
   <message name="getStringRequest"/>
   <message name="getStringResponse">
    <part name="result" type="xsd:string"/>
   </message>
   <message name="sayHelloRequest"/>
   <message name="sayHelloResponse">
    <part name="result" type="xsd:string"/>
   </message>
   <portType name="MyObjectWS">
    <operation name="setString" parameterOrder="arg0">
     <input message="tns:setStringRequest"/>
     <output message="tns:setStringResponse"/>
    </operation>
    <operation name="getString">
     <input message="tns:getStringRequest"/>
     <output message="tns:getStringResponse"/>
    </operation>
    <operation name="sayHello">
     <input message="tns:sayHelloRequest"/>
     <output message="tns:sayHelloResponse"/>
    </operation>
   </portType>
   <binding name="MyObjectWSBinding" type="tns:MyObjectWS">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="setString">
     <soap:operation soapAction="urn:com.exsamp.obj.MyObject/setString"/>
     <input>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </input>
     <output>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </output>
    </operation>
    <operation name="getString">
     <soap:operation soapAction="urn:com.exsamp.obj.MyObject/getString"/>
     <input>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </input>
     <output>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </output>
    </operation>
    <operation name="sayHello">
     <soap:operation soapAction="urn:com.exsamp.obj.MyObject/sayHello"/>
     <input>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </input>
     <output>
      <soap:body
       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       namespace="urn:com.exsamp.obj.MyObject" use="encoded"/>
     </output>
    </operation>
   </binding>
   <service name="MyObjectWSService">
    <port binding="tns:MyObjectWSBinding" name="MyObjectWSPort">
     <soap:address location="http://localhost/WebServiceSampleDB/WebServiceSample/MyObject"/>
    </port>
   </service>
  </definitions>

 
Top of section

Generated files for testing

Based on the input provided for this scenario, the Web Service Wizard generates these files so you can test the Web Service once it's deployed:

MyObjectWSService.java

MyObjectWSService is the service interface that's used in JAX-RPC to help clients obtain the stub for the Web Service. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import javax.xml.rpc.ServiceException;
  
  public interface MyObjectWSService extends javax.xml.rpc.Service
  {
      public MyObjectWS_Stub getMyObjectWSPort()
          throws ServiceException;
  }

MyObjectWSServiceImpl.java

MyObjectWSServiceImpl is the service implementation class that handles instantiation of the stub (MyObjectWS_Stub). The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import java.io.FileNotFoundException;
  import java.util.Iterator;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.ArrayList;
  import java.net.URL;
  import java.net.MalformedURLException;
  import javax.xml.rpc.Call;
  import javax.xml.rpc.ParameterMode;
  import javax.xml.namespace.QName;
  import javax.xml.rpc.ServiceException;
  import com.sssw.jbroker.web.Binding;
  import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
  
  public class MyObjectWSServiceImpl
      extends com.sssw.jbroker.web.xml.rpc.ServiceImpl 
      implements MyObjectWSService
  {
      public MyObjectWSServiceImpl()
      {
          try {
              createCalls();
          } catch (ServiceException ex) {
              throw new javax.xml.rpc.JAXRPCException("failed to create the call objects: " + ex.getMessage());
          }
      }
      
      public QName getServiceName() { return _serviceName; }
      
      public Iterator getPorts() { return _portMapping.keySet().iterator(); }
      
      public void setProxyMode(boolean proxy) { _proxy = proxy; }
      
      public boolean getProxyMode() { return _proxy; }
      
      public URL getWSDLDocumentLocation()
      {
          return null;
      }
      
      public java.rmi.Remote getPort(Class serviceDefInterface)
          throws ServiceException
      {
          if (serviceDefInterface == null)
              throw new ServiceException("No Service class specified.");
          if (!java.rmi.Remote.class.isAssignableFrom(serviceDefInterface))
              throw new ServiceException("Class is not a valid Interface.");
          
          String stubName = (String) _intfMapping.get(serviceDefInterface);
          Binding binding = (Binding) _intfBinding.get(serviceDefInterface);
          
          if (stubName == null)
              return getPort(serviceDefInterface, binding, 
                  _classInfo, _typeMappingRegistry, null);
          else
              return getPort(stubName, binding, _typeMappingRegistry);
      }
      
      public java.rmi.Remote getPort(QName portName, Class serviceDefInterface) 
          throws ServiceException
      {
          return getPort(portName, serviceDefInterface, getProxyMode());
      }
      
      public java.rmi.Remote getPort(QName portName, Class serviceDefInterface, boolean proxy) 
          throws ServiceException
      {
          if (((proxy==false) || (serviceDefInterface == null)) && 
              (portName != null)) {
              String stubName = (String) _portMapping.get(portName);
              Binding binding = (Binding) _portBinding.get(portName);
              
              if (stubName == null) return getPort(null, serviceDefInterface);
              
              try {
                  return getPort(stubName, binding, portName,
                     _typeMappingRegistry);
              } catch (Exception ex) {
                  return getPort(null, serviceDefInterface);
              }
          } else {
              if (serviceDefInterface == null)
                  throw new ServiceException("No Service class specified.");
              if (!java.rmi.Remote.class.isAssignableFrom(serviceDefInterface))
                  throw new ServiceException("Class is not a valid Interface.");
              
              Binding binding = (Binding) _intfBinding.get(serviceDefInterface);
              String uri = (portName == null) ? null : portName.getNamespaceURI();
              return getPort(serviceDefInterface, binding, _classInfo,
                 _typeMappingRegistry, uri);
          }
      }
      
      public Call[] getCalls(QName portName)
          throws ServiceException
      {
          ArrayList callslist = (ArrayList) _calls.get(portName);
          if (callslist == null) return null;
          Call[] calls = new Call[callslist.size()];
          return (Call[]) callslist.toArray(calls);
      }
      
      private void addCall(QName portName, Call call)
      {
          ArrayList callslist = (ArrayList) _calls.get(portName);
          if (callslist == null) {
              callslist = new ArrayList();
              _calls.put(portName, callslist);
          }
          callslist.add(call);
      }
      
      public MyObjectWS_Stub getMyObjectWSPort()
          throws ServiceException
      {
          try {
              return (MyObjectWS_Stub) getPort(new QName(
                  "urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), null, false);
          } catch (Exception ex) {
              return (MyObjectWS_Stub) getPort(com.exsamp.obj.MyObjectWS.class);
          }
      }
      
      private void createCalls()
          throws ServiceException
      {
          Call call = null;
          
          call = createCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), 
            new QName("urn:com.exsamp.obj.MyObject", "setString"));
          call.addParameter("arg0", new QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class, ParameterMode.IN);
          call.addParameter("result", new QName("http://www.w3.org/2001/XMLSchema", "boolean"), boolean.class, ParameterMode.OUT);
          call.setReturnType(new QName("http://www.w3.org/2001/XMLSchema", "boolean"), boolean.class);
          call.setProperty(Call.OPERATION_STYLE_PROPERTY, "rpc");
          call.setProperty(Call.SOAPACTION_URI_PROPERTY, "\"urn:com.exsamp.obj.MyObject/setString\"");
          call.setTargetEndpointAddress("http://localhost/WebServiceSampleDB/WebServiceSample/MyObject");
          addCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), call);
          
          call = createCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), 
            new QName("urn:com.exsamp.obj.MyObject", "getString"));
          call.addParameter("result", new QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class, ParameterMode.OUT);
          call.setReturnType(new QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class);
          call.setProperty(Call.OPERATION_STYLE_PROPERTY, "rpc");
          call.setProperty(Call.SOAPACTION_URI_PROPERTY, "\"urn:com.exsamp.obj.MyObject/getString\"");
          call.setTargetEndpointAddress("http://localhost/WebServiceSampleDB/WebServiceSample/MyObject");
          addCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), call);
          
          call = createCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), 
            new QName("urn:com.exsamp.obj.MyObject", "sayHello"));
          call.addParameter("result", new QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class, ParameterMode.OUT);
          call.setReturnType(new QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class);
          call.setProperty(Call.OPERATION_STYLE_PROPERTY, "rpc");
          call.setProperty(Call.SOAPACTION_URI_PROPERTY, "\"urn:com.exsamp.obj.MyObject/sayHello\"");
          call.setTargetEndpointAddress("http://localhost/WebServiceSampleDB/WebServiceSample/MyObject");
          addCall(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), call);
          
      }
      
      static boolean _proxy = true;
      static final QName _serviceName;
      static final Hashtable _intfMapping = new Hashtable();
      static final Hashtable _intfBinding = new Hashtable();
      static final Hashtable _portBinding = new Hashtable();
      static final Hashtable _portMapping = new Hashtable();
      static final Hashtable _classInfo = new Hashtable();
      private final Hashtable _calls = new Hashtable();
  
      static {
          _serviceName = new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSService");
          
          _intfBinding.put(MyObjectWS.class, new Binding("soap", "http://localhost/WebServiceSampleDB/WebServiceSample/MyObject"));
          _portBinding.put(new QName("urn:com.exsamp.obj.MyObject", "com.exsamp.obj.MyObjectWSPort"), 
            new Binding("soap", "http://localhost/WebServiceSampleDB/WebServiceSample/MyObject"));
          _intfMapping.put(MyObjectWS.class, "com.exsamp.obj.MyObjectWS_Stub");
          _portMapping.put(new QName("urn:com.exsamp.obj.MyObject",
          "com.exsamp.obj.MyObjectWSPort"), "com.exsamp.obj.MyObjectWS_Stub");
          
          Hashtable _methodInfo;
          Hashtable _paramInfo;
          Properties _props;
          
          _methodInfo = new Hashtable();
          _paramInfo = new Hashtable();
          _props = new Properties();
          _props.setProperty("jbroker.web.soap.action","\"urn:com.exsamp.obj.MyObject/setString\"");
          _paramInfo.put("Properties", _props);
          _props = new Properties();
          _props.setProperty("jbroker.web.parameter.name", "arg0");
          _props.setProperty("jbroker.web.parameter.inout", "1");
          _paramInfo.put("Param0", _props);
          _props = new Properties();
          _props.setProperty("jbroker.web.parameter.name", "result");
          _props.setProperty("jbroker.web.parameter.inout", "2");
          _paramInfo.put("Result", _props);
          _methodInfo.put("setString", _paramInfo);
          _paramInfo = new Hashtable();
          _props = new Properties();
          _props.setProperty("jbroker.web.soap.action","\"urn:com.exsamp.obj.MyObject/getString\"");
          _paramInfo.put("Properties", _props);
          _props = new Properties();
          _props.setProperty("jbroker.web.parameter.name", "result");
          _props.setProperty("jbroker.web.parameter.inout", "2");
          _paramInfo.put("Result", _props);
          _methodInfo.put("getString", _paramInfo);
          _paramInfo = new Hashtable();
          _props = new Properties();
          _props.setProperty("jbroker.web.soap.action","\"urn:com.exsamp.obj.MyObject/sayHello\"");
          _paramInfo.put("Properties", _props);
          _props = new Properties();
          _props.setProperty("jbroker.web.parameter.name", "result");
          _props.setProperty("jbroker.web.parameter.inout", "2");
          _paramInfo.put("Result", _props);
          _methodInfo.put("sayHello", _paramInfo);
          _classInfo.put("com.exsamp.obj.MyObjectWS", _methodInfo);
      }
  }

MyObjectWS_Stub.java

MyObjectWS_Stub is used by clients as a proxy for accessing the Web Service. This stub class implements the remote interface (MyObjectWS) to handle the logistics of each method call. The wizard generates this source code for it:

  package com.exsamp.obj;
  
  
  import java.util.Properties;
  import com.sssw.jbroker.web.core.Constants;
  import com.sssw.jbroker.web.encoding.TypeMappingRegistry;
  import com.sssw.jbroker.web.encoding.DefaultTypeMappingRegistry;
  
  public class MyObjectWS_Stub
      extends com.sssw.jbroker.web.portable.Stub
      implements MyObjectWS
  {
      private static com.sssw.jbroker.web.QName _portType =
          new com.sssw.jbroker.web.QName("urn:com.exsamp.obj.MyObject", "MyObjectWS");
      
      private static final com.sssw.jbroker.web.Binding[] _bindings = 
          new com.sssw.jbroker.web.Binding[] {
              new com.sssw.jbroker.web.Binding("soap", "http://localhost/WebServiceSampleDB/WebServiceSample/MyObject"),
      };
      
      public MyObjectWS_Stub()
      {
          this(null);
      }
      
      public MyObjectWS_Stub(DefaultTypeMappingRegistry tmr)
      {
          super(_portType, _bindings);
          _setProperty("xmlrpc.schema.uri", (Object) "http://www.w3.org/2001/XMLSchema".intern());
          _setProperty("version", (Object) "1.1");
          TypeMappingRegistry _tm = null;
          try {
              if (tmr != null)
                  _tm = tmr;
              else {
                  _tm = new DefaultTypeMappingRegistry();
              }
              _setTypeMappingRegistry(_tm);
          } catch (Exception ex) {
              throw new javax.xml.rpc.JAXRPCException("failed to initialize type mapping registry: " + ex.getMessage());
          }
      }
      
      public boolean setString(java.lang.String _arg0) 
          throws java.rmi.RemoteException
      {
          com.sssw.jbroker.web.portable.ClientResponse in = null;
          
          try {
              // create an output stream
              _getDelegate().setProperty("xmlrpc.soap.operation.name", 
                new com.sssw.jbroker.web.QName("urn:com.exsamp.obj.MyObject", "setString"));
              //create request
              com.sssw.jbroker.web.portable.ClientRequest out = 
                  _request("setString", true, "soap", false, "\"urn:com.exsamp.obj.MyObject/setString\"");
              _getDelegate().setProperty("soapAction", (Object) "\"urn:com.exsamp.obj.MyObject/setString\"");
              _getDelegate().setProperty(Constants.HTTP_CONTENT_TYPE, (Object) "text/xml; charset=utf-8");
              out._setProperties(_getDelegate().getProperties());
              Object arg = null;
              
              // marshal the parameters
              arg = _arg0;
              out.writeObject(arg, "arg0");
              
              // do the invocation
              in = _invoke(out);
              // unmarshal the results
              
              // return
              java.lang.Boolean retWrapper = (java.lang.Boolean)in.readObject(boolean.class, "result");
              boolean ret = retWrapper.booleanValue();
              return ret;
              
          } catch (java.lang.Throwable t) {
              
              // map to remote exception
              throw com.sssw.jbroker.web.ServiceException.mapToRemote(t);
          }
      }
      
      public java.lang.String getString() 
          throws java.rmi.RemoteException
      {
          com.sssw.jbroker.web.portable.ClientResponse in = null;
          
          try {
              // create an output stream
              _getDelegate().setProperty("xmlrpc.soap.operation.name", 
                new com.sssw.jbroker.web.QName("urn:com.exsamp.obj.MyObject", "getString"));
              //create request
              com.sssw.jbroker.web.portable.ClientRequest out = 
                  _request("getString", true, "soap", false, "\"urn:com.exsamp.obj.MyObject/getString\"");
              _getDelegate().setProperty("soapAction", (Object) "\"urn:com.exsamp.obj.MyObject/getString\"");
              _getDelegate().setProperty(Constants.HTTP_CONTENT_TYPE, (Object) "text/xml; charset=utf-8");
              out._setProperties(_getDelegate().getProperties());
              Object arg = null;
              
              // do the invocation
              in = _invoke(out);
              // unmarshal the results
              
              // return
              java.lang.String ret = null;
              try {
                  ret = (java.lang.String)
                  in.readObject(java.lang.String.class, "result");
              } catch (java.io.EOFException eofExc) {
                  ret = null;
              }
              return ret;
              
          } catch (java.lang.Throwable t) {
              
              // map to remote exception
              throw com.sssw.jbroker.web.ServiceException.mapToRemote(t);
          }
      }
      
      public java.lang.String sayHello() 
          throws java.rmi.RemoteException
      {
          com.sssw.jbroker.web.portable.ClientResponse in = null;
          
          try {
              // create an output stream
              _getDelegate().setProperty("xmlrpc.soap.operation.name", 
                new com.sssw.jbroker.web.QName("urn:com.exsamp.obj.MyObject", "sayHello"));
              //create request
              com.sssw.jbroker.web.portable.ClientRequest out = 
                  _request("sayHello", true, "soap", false, "\"urn:com.exsamp.obj.MyObject/sayHello\"");
              _getDelegate().setProperty("soapAction", (Object) "\"urn:com.exsamp.obj.MyObject/sayHello\"");
              _getDelegate().setProperty(Constants.HTTP_CONTENT_TYPE, (Object) "text/xml; charset=utf-8");
              out._setProperties(_getDelegate().getProperties());
              Object arg = null;
              
              // do the invocation
              in = _invoke(out);
              // unmarshal the results
              
              // return
              java.lang.String ret = null;
              try {
                  ret = (java.lang.String)
                  in.readObject(java.lang.String.class, "result");
              } catch (java.io.EOFException eofExc) {
                  ret = null;
              }
              return ret;
              
          } catch (java.lang.Throwable t) {
              
              // map to remote exception
              throw com.sssw.jbroker.web.ServiceException.mapToRemote(t);
          }
      }
      
      
      private static Properties _rootHeaders = new Properties();
      static {
          _rootHeaders.setProperty("content-type", "text/xml; charset=UTF-8");
          _rootHeaders.setProperty("content-id", "<soapbody>");
      }
  }

MyObjectWSClient.java

MyObjectWSClient is a simple client application that accesses the Web Service by:

  1. Instantiating MyObjectWSService via JNDI lookup

  2. Using the MyObjectWSService object to obtain the stub (MyObjectWS_Stub)

  3. Calling Web Service methods via the MyObjectWS_Stub object

The wizard generates this source code for it:

  package com.exsamp.obj;
  
  import javax.naming.*;
  
  public class MyObjectWSClient
  {
      public void process(String[] args) throws Exception
      {
          MyObjectWS remote = getRemote(args);
  
          // The following code has been generated for your testing convenience. In
          // order to successfully test your Web Service, you must uncomment one or
          // more of these lines and supply meaningful arguments where necessary.
          // Once you have modified the test method(s) below, compile this class and
          // execute it from a command line with your class path set appropriately.
  
          // System.out.println("Test Result = " + remote.getString());
          // System.out.println("Test Result = " + remote.setString(java.lang.String));
          // System.out.println("Test Result = " + remote.sayHello());
  
      }
  
  
      public MyObjectWS getRemote(String[] args) throws Exception
      {
          InitialContext ctx = new InitialContext();
          
          String lookup = "xmlrpc:soap:com.exsamp.obj.MyObjectWSService";
          MyObjectWSService service = (MyObjectWSService)ctx.lookup(lookup);
          MyObjectWS remote = (MyObjectWS)service.getMyObjectWSPort();
              
          return remote;
      }
  
  
      public static void main(String[] args)
      {
          try
          {
              MyObjectWSClient client = new MyObjectWSClient();
              client.process(args);
          }
          catch (Exception _e)
          {
              System.out.println("*** Error Executing Generated Test Client ***");
              _e.printStackTrace();
          }
      }
  
  }

Modifications needed   The process() method of the generated MyObjectWSClient.java file must be edited to uncomment the Web Service method call to be tested. Here's the change:

  // System.out.println("Test Result = " + remote.getString());
  // System.out.println("Test Result = " + remote.setString(java.lang.String));
  System.out.println("Test Result = " + remote.sayHello());

 
Top of section

Deployment descriptor

Because this scenario uses the tie model, the Web Service Wizard automatically updates the web.xml file to declare MyObjectWSTie as the servlet class to handle requests for the MyObject Web Service:

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
                           "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
  <web-app>
      <servlet>
          <servlet-name>MyObject</servlet-name>
          <servlet-class>com.exsamp.obj.MyObjectWSTie</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>MyObject</servlet-name>
          <url-pattern>MyObject</url-pattern>
      </servlet-mapping>
  </web-app>

 
Top of section

Runtime test result

Once this project is built and the WAR file is created and deployed to the J2EE server, the MyObject Web Service is ready for a test run. Here's the result of using the Client Runner in Workbench to execute the MyObjectWSClient application:

GWSs1runner

    First Previous Next Last Development Guide  

Copyright © 2001, 2002, 2003 SilverStream Software, LLC, a wholly owned subsidiary of Novell, Inc. All rights reserved.