web service 小结。

What is SOAP?

SOAP is an XML-based communication protocol and encoding format for inter-application communication. 

What is Axis?

Axis is essentially a SOAP engine -- a framework for constructing SOAP processors such as clients, servers, gateways, etc.

Publishing Web Services with Axis

1. JWS (Java Web Service) Files - Instant Deployment 
   copy the java file into your webapp directory, and rename it  to " *.jws"

 Important: JWS web services are intended for simple web services. You cannot use packages in the pages, and as the code is compiled at run time you can not find out about errors until after deployment.

2. Custom Deployment - Introducing WSDD

a. using the the Axis Web Service Deployment Descriptor (WSDD) define the service . generate kinds of * wsdd files 

b. using  AdminClient, or the "org.apache.axis.client.AdminClient" class to send it to an Axis server in order to actually deploy the described      service. eg: 
% java org.apache.axis.client.AdminClient deploy.wsdd
 This command has now made our service accessible via SOAP and you can access it via the following sample url:
http://localhost:8080/axis/services/MyService "test me!"

Service Styles - RPC, Document, Wrapped, and Message

There are four "styles" of service in Axis.  RPC  services use the SOAP RPC conventions, and also the SOAP "section 5" encoding.  Document  services do not use any encoding (so in particular, you won't see multiref object serialization or SOAP-style arrays on the wire) but DO still do XML<->Java databinding.  Wrapped  services are just like document services, except that rather than binding the entire SOAP body into one big structure, they "unwrap" it into individual parameters.  Message  services receive and return arbitrary XML in the SOAP Envelope without any type mapping / data binding. If you want to work with the raw XML of the incoming and outgoing SOAP Envelopes, write a message service.

Using WSDL with Axis

The Web Service Description Language is a specification authored by IBM and Microsoft, and supported by many other organizations. WSDL serves to describe Web Services in a structured way. A WSDL description of a service tells us, in a machine-understandable way, the interface to the service, the data types it uses, and where the service is located. Please see the spec (follow the link in the first sentence) for details about WSDL's format and options.

Axis supports WSDL in three ways:

  1. When you deploy a service in Axis, users may then access your service's URL with a standard web browser and by appending "?WSDL" to the end of the URL, they will obtain an automatically-generated WSDL document which describes your service.
  2. We provide a "WSDL2Java" tool which will build Java proxies and skeletons for services with WSDL descriptions.
  3. We provide a "Java2WSDL" tool which will build WSDL from Java classes.

WSDL2Java: Building stubs, skeletons, and data types from WSDL

Client-side bindings

You'll find the Axis WSDL-to-Java tool in "org.apache.axis.wsdl.WSDL2Java". The basic invocation form looks like this:

% java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)
Server-side bindings

Just as a stub is the client side of a Web Service represented in Java, a skeleton is a Java framework for the server side. To make skeleton classes, you just specify the "--server-side --skeletonDeploy true" options to WSDL2Java. For instance, using the AddressBook.wsdl as we had above:

% java org.apache.axis.wsdl.WSDL2Java --server-side
    --skeletonDeploy true AddressBook.wsdl

Java2WSDL: Building WSDL from Java

The Java2WSDL and WSDL2Java emitters make it easy to develop a new web service. The following sections describe the steps in building a web service from a Java interface.

Step 1: Provide a Java interface or class

Write and compile a Java interface (or class) that describes the web service interface. Here is an example interface that describes a web services that can be used to set/query the price of widgets (samples/userguide/example6/WidgetPrice.java):

package samples.userguide.example6;

/**
 * Interface describing a web service to set and get Widget prices.
 **/
public interface WidgetPrice {
  public void setWidgetPrice(String widgetName, String price);
  public String getWidgetPrice(String widgetName);
}

Note: If you compile your class with debug information, Java2WSDL will use the debug information to obtain the method parameter names.

Step 2: Create WSDL using Java2WSDL

Use the Java2WSDL tool to create a WSDL file from the interface above.

Here is an example invocation that produces the wsdl file (wp.wsdl) from the interface described in the previous section (entered all on one line):

% java org.apache.axis.wsdl.Java2WSDL -o wp.wsdl
    -l"http://localhost:8080/axis/services/WidgetPrice"
    -n  "urn:Example6" -p"samples.userguide.example6" "urn:Example6"
    samples.userguide.example6.WidgetPrice

Where:

  • -o indicates the name of the output WSDL file
  • -l indicates the location of the service
  • -n is the target namespace of the WSDL file
  • -p indicates a mapping from the package to a namespace. There may be multiple mappings.
  • the class specified contains the interface of the webservice.
WSDL clause Java class(es) generated
For each entry in the type section A java class
  A holder if this type is used as an inout/out parameter
For each portType A java interface
For each binding A stub class
For each service A service interface
  A service implementation (the locator)

There is an Ant Task to integrate this action with an Ant based build process.

Types

The Java class generated from a WSDL type will be named from the WSDL type. This class will typically, though not always, be a bean. For example, given the WSDL (the WSDL used throughout the WSDL2Java discussion is from the Address Book sample):

<xsd:complexType name="phone">
  <xsd:all>
    <xsd:element name="areaCode" type="xsd:int"/>
    <xsd:element name="exchange" type="xsd:string"/>
    <xsd:element name="number" type="xsd:string"/>
  </xsd:all>
</xsd:complexType>

WSDL2Java will generate:

public class Phone implements java.io.Serializable {
  public Phone() {...}
  public int getAreaCode() {...}
  public void setAreaCode(int areaCode) {...}
  public java.lang.String getExchange() {...}
  public void setExchange(java.lang.String exchange) {...}
  public java.lang.String getNumber() {...}
  public void setNumber(java.lang.String number) {...}
  public boolean equals(Object obj) {...}
  public int hashCode() {...}
}
Holders

This type may be used as an inout or out parameter. Java does not have the concept of inout/out parameters. In order to achieve this behavior, JAX-RPC specifies the use of holder classes. A holder class is simply a class that contains an instance of its type. For example, the holder for the Phone class would be:

package samples.addr.holders;

public final class PhoneHolder implements javax.xml.rpc.holders.Holder {
  public samples.addr.Phone value;

  public PhoneHolder() {
  }

  public PhoneHolder(samples.addr.Phone value) {
    this.value = value;
  }
}

A holder class is only generated for a type if that type is used as an inout or out parameter. Note that the holder class has the suffix "Holder" appended to the class name, and it is generated in a sub-package with the "holders".

The holder classes for the primitive types can be found in javax.xml.rpc.holders.

PortTypes

The Service Definition Interface (SDI) is the interface that's derived from a WSDL's portType. This is the interface you use to access the operations on the service. For example, given the WSDL:

<message name="empty">
<message name="AddEntryRequest">
  <part name="name" type="xsd:string"/>
  <part name="address" type="typens:address"/>
</message>
<portType name="AddressBook">
  <operation name="addEntry">
    <input message="tns:AddEntryRequest"/>
    <output message="tns:empty"/>
  </operation>
</portType>

WSDL2Java will generate:

public interface AddressBook extends java.rmi.Remote {
  public void addEntry(String name, Address address) throws
      java.rmi.RemoteException;
}

A note about the name of the SDI. The name of the SDI is typically the name of the portType. However, to construct the SDI, WSDL2Java needs information from both the portType and the binding. (This is unfortunate and is a topic of discussion for WSDL version 2.)

JAX-RPC says (section 4.3.3): "The name of the Java interface is mapped from the name attribute of the wsdl:portType element. ... If the mapping to a service definition interface uses elements of the wsdl:binding ..., then the name of the service definition interface is mapped from the name of the wsdl:binding element."

Note the name of the spec. It contains the string "RPC". So this spec, and WSDL2Java, assumes that the interface generated from the portType is an RPC interface. If information from the binding tells us otherwise (in other words, we use elements of the wsdl:binding), then the name of the interface is derived instead from the binding.

Why? We could have one portType - pt - and two bindings - bRPC and bDoc. Since document/literal changes what the interface looks like, we cannot use a single interface for both of these bindings, so we end up with two interfaces - one named pt and another named bDoc - and two stubs - bRPCStub (which implements pt) and bDocStub (which implements bDoc).

Ugly, isn't it? But you can see why it's necessary. Since document/literal changes what the interface looks like, and we could have more than one binding referring to a single portType, we have to create more than one interface, and each interface must have a unique name.

Bindings

A Stub class implements the SDI. Its name is the binding name with the suffix "Stub". It contains the code which turns the method invocations into SOAP calls using the Axis Service and Call objects. It stands in as aproxy (another term for the same idea) for the remote service, letting you call it exactly as if it were a local object. In other words, you don't need to deal with the endpoint URL, namespace, or parameter arrays which are involved in dynamic invocation via the Service and Call objects. The stub hides all that work for you.

Given the following WSDL snippet:

<binding name="AddressBookSOAPBinding" type="tns:AddressBook">
  ...
</binding>

WSDL2Java will generate:

public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub
    implements AddressBook {
  public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault {...}

  public AddressBookSOAPBindingStub(URL endpointURL,
      javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...}

  public AddressBookSOAPBindingStub(javax.xml.rpc.Service service)
      throws org.apache.axis.AxisFault {...}

  public void addEntry(String name, Address address)
      throws RemoteException {...}
}
Services

Normally, a client program would not instantiate a stub directly. It would instead instantiate a service locator and call a get method which returns a stub. This locator is derived from the service clause in the WSDL. WSDL2Java generates two objects from a service clause. For example, given the WSDL:

<service name="AddressBookService">
  <port name="AddressBook" binding="tns:AddressBookSOAPBinding">
    <soap:address location="http://localhost:8080/axis/services/AddressBook"/>
  </port>
</service>

WSDL2Java will generate the service interface:

public interface AddressBookService extends javax.xml.rpc.Service {
  public String getAddressBookAddress();

  public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException;

  public AddressBook getAddressBook(URL portAddress)
      throws javax.xml.rpc.ServiceException;
}

WSDL2Java will also generate the locator which implements this interface:

public class AddressBookServiceLocator extends org.apache.axis.client.Service
    implements AddressBookService {
  ...
}

The service interface defines a get method for each port listed in the service element of the WSDL. The locator is the implementation of this service interface. It implements these get methods. It serves as a locator for obtaining Stub instances. The Service class will by default make a Stub which points to the endpoint URL described in the WSDL file, but you may also specify a different URL when you ask for the PortType.

A typical usage of the stub classes would be as follows:

public class Tester {
  public static void main(String [] args) throws Exception {
    // Make a service
    AddressBookService service = new AddressBookServiceLocator();

    // Now use the service to get a stub which implements the SDI.
    AddressBook port = service.getAddressBook();

    // Make the actual call
    Address address = new Address(...);
    port.addEntry("Russell Butek", address);
  }
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值