study axis integrate spring

What is Axis?
Apache EXtensible Interaction System
SOAP is an XML-based communication protocol and encoding format for inter-application communication. Originally conceived by Microsoft and Userland software, it has evolved through several generations; the current spec is version, SOAP 1.2, though version 1.1 is more widespread. The W3C's XML Protocol working group is in charge of the specification.

Axis is essentially a SOAP engine -- a framework for constructing SOAP processors such as clients, servers, gateways, etc. The current version of Axis is written in Java, but a C++ implementation of the client side of Axis is being developed.

But Axis isn't just a SOAP engine -- it also includes:

    * a simple stand-alone server,
    * a server which plugs into servlet engines such as Tomcat,
    * extensive support for the Web Service Description Language (WSDL),
    * emitter tooling that generates Java classes from WSDL.
    * some sample programs, and
    * a tool for monitoring TCP/IP packets.

Axis is the third generation of Apache SOAP (which began at IBM as "SOAP4J"). In late 2000, the committers of Apache SOAP v2 began discussing how to make the engine much more flexible, configurable, and able to handle both SOAP and the upcoming XML Protocol specification from the W3C.

After a little while, it became clear that a ground-up rearchitecture was required. Several of the v2 committers proposed very similar designs, all based around configurable "chains" of message "handlers" which would implement small bits of functionality in a very flexible and composable manner.

After months of continued discussion and coding effort in this direction, Axis now delivers the following key features:

    * Speed. Axis uses SAX (event-based) parsing to acheive significantly greater speed than earlier versions of Apache SOAP.
    * Flexibility. The Axis architecture gives the developer complete freedom to insert extensions into the engine for custom header processing, system management, or anything else you can imagine.
    * Stability. Axis defines a set of published interfaces which change relatively slowly compared to the rest of Axis.
    * Component-oriented deployment. You can easily define reusable networks of Handlers to implement common patterns of processing for your applications, or to distribute to partners.
    * Transport framework. We have a clean and simple abstraction for designing transports (i.e., senders and listeners for SOAP over various protocols such as SMTP, FTP, message-oriented middleware, etc), and the core of the engine is completely transport-independent.
    * WSDL support. Axis supports the Web Service Description Language, version 1.1, which allows you to easily build stubs to access remote services, and also to automatically export machine-readable descriptions of your deployed services from Axis.


JWS (Java Web Service) Files:
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. Production quality web services should use Java classes with custom deployment.
To really use the flexibility available to you in Axis, you should get familiar with the Axis Web Service Deployment Descriptor (WSDD) format.


Scoped Services

Axis supports scoping service objects (the actual Java objects which implement your methods) three ways. "Request" scope, the default, will create a new object each time a SOAP request comes in for your service. "Application" scope will create a singleton shared object to service all requests. "Session" scope will create a new object for each session-enabled client who accesses your service. To specify the scope option, you add a <parameter> to your service like this (where "value" is request, session, or application):

<service name="MyService"...>
  <parameter name="scope" value="value"/>
  ...
</service>

More deployment - Handlers and Chains

Now let's start to explore some of the more powerful features of the Axis engine. Let's say you want to track how many times your service has been called. We've included a sample handler in the samples/log directory to do just this. To use a handler class like this, you first need to deploy the Handler itself, and then use the name that you give it in deploying a service. Here's a sample deploy.wsdd file (this is example 4 in samples/userguide):

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <!-- define the logging handler configuration -->
  <handler name="track" type="java:samples.userguide.example4.LogHandler">
    <parameter name="filename" value="MyService.log"/>
   </handler>

  <!-- define the service, using the log handler we just defined -->
  <service name="LogTestService" provider="java:RPC">
    <requestFlow>
      <handler type="track"/>
    </requestFlow>

    <parameter name="className" value="samples.userguide.example4.Service"/>
    <parameter name="allowedMethods" value="*"/>
  </service>
</deployment>

Remote Administration

Note that by default, the Axis server is configured to only accept administration requests from the machine on which it resides - if you wish to enable remote administration, you must set the "enableRemoteAdmin" property of the AdminService to true. To do this, find the "server-config.wsdd" file in your webapp's WEB-INF directory. In it, you'll see a deployment for the AdminService. Add an option as follows:

<service name="AdminService" provider="java:MSG">
  <parameter name="className" value="org.apache.axis.util.Admin"/>
  <parameter name="allowedMethods" value="*"/>
  <parameter name="enableRemoteAdmin" value="true"/>
</service>

WARNING: enabling remote administration may give unauthorized parties access to your machine. If you do this, please make sure to add security to your configuration!

Standard mappings from WSDL to Java
xsd:base64Binary byte[]
xsd:boolean boolean
xsd:byte byte
xsd:dateTime java.util.Calendar
xsd:decimal java.math.BigDecimal
xsd:double double
xsd:float float
xsd:hexBinary byte[]
xsd:int int
xsd:integer java.math.BigInteger
xsd:long long
xsd:QName javax.xml.namespace.QName
xsd:short short
xsd:string java.lang.String


What Axis can not send via SOAP
如果运行时报错:No deserializer defined for array type
很有可能就是这个问题了
Arbitrary Objects without Pre-Registration

You cannot send arbitrary Java objects over the wire and expect them to be understood at the far end. With RMI you can send and receive Serializable Java objects, but that is because you are running Java at both ends. Axis will only send objects for which there is a registered Axis serializer. This document shows below how to use the BeanSerializer to serialize any class that follows the JavaBean pattern of accessor and mutator. To serve up objects you must either register your classes with this BeanSerializer, or there must be serialization support built in to Axis.

解决办法:
在SERVER-CONFIG.WSDD中的SERVICE标签中添加:
<beanMapping languageSpecificType="java:test.StudentBean" qname="ns1:StudentBean"
         xmlns:ns1="urn:StudentBeanService"/>

或者
<typeMapping qname="ns1:StudentBean" xmlns:ns1="urn:StudentBeanService"     languageSpecificType="java:test.StudentBean"     serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"     deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"     encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

The <beanMapping> tag is really just shorthand for a <typeMapping> tag

在客户端调用CALL方法前使用registerTypeMapping方法:
QName qStudent = new QName("urn:StudentBeanService","StudentBean");
call.registerTypeMapping(StudentBean.class, qStudent,
new BeanSerializerFactory(StudentBean.class, qStudent),
new BeanDeserializerFactory(StudentBean.class, qStudent));

Deploying array mappings - the <arrayMapping> tag

nother variation around typeMapping is arrayMapping. The arrayMapping tag is useful for advanced users wanting to exatly control how their arrays are serialized throught the wire.

<arrayMapping qname="ns:ArrayOfthingy" xmlns:ns="someNamespaceURI"
             languageSpecificType="java:my.java.array.thingy[]"
innerType="ns2:thingy" xmlns:ns2="anotherNamespaceURI"
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

No need here to specify a serializer/deserializer couple, the arrayMapping tag is only about arrays (no List, ...). The added attribute (innerType) is used to tell Axis what precisely is the item type of the Array.

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.

?WSDL: Obtaining WSDL for deployed services

When you make a service available using Axis, there is typically a unique URL associated with that service. For JWS files, that URL is simply the path to the JWS file itself. For non-JWS services, this is usually the URL "http://<host>/axis/services/<service-name>".

If you access the service URL in a browser, you'll see a message indicating that the endpoint is an Axis service, and that you should usually access it using SOAP. However, if you tack on "?wsdl" to the end of the URL, Axis will automatically generate a service description for the deployed service, and return it as XML in your browser (try it!). The resulting description may be saved or used as input to proxy-generation, described next. You can give the WSDL-generation URL to your online partners, and they'll be able to use it to access your service with toolkits like .NET, SOAP::Lite, or any other software which supports using WSDL.

You can also generate WSDL files from existing Java classes (see Java2WSDL: Building WSDL from Java).
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)

This will generate only those bindings necessary for the client. Axis follows the JAX-RPC specification when generating Java client bindings from WSDL. For this discussion, assume we executed the following:

% cd samples/addr
% java org.apache.axis.wsdl.WSDL2Java AddressBook.wsdl

The generated files will reside in the directory "AddressFetcher2". They are put here because that is the target namespace from the WSDL and namespaces map to Java packages. Namespaces will be discussed in detail later.
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() {...}
}

Mapping XML to Java types : Metadata

Notice in the mapping above, the XML type name is "phone" and the generated Java class is "Phone" - the capitalization of the first letter has changed to match the Java coding convention that classes begin with an uppercase letter. This sort of thing happens a lot, because the rules for expressing XML names/identifiers are much less restrictive than those for Java. For example, if one of the sub-elements in the "phone" type above was named "new", we couldn't just generate a Java field called "new", since that is a reserved word and the resultant source code would fail to compile.

To support this kind of mapping, and also to enable the serialization/deserialization of XML attributes, we have a type metadata system which allows us to associate Java data classes with descriptors which control these things.

When the WSDL2Java tool creates a data bean like the Phone class above, it notices if the schema contains any attributes, or any names which do not map directly to Java field/property names. If it finds any of these things, it will generate a static piece of code to supply a type descriptor for the class. The type descriptor is essentially a collection of field descriptors, each of which maps a Java field/property to an XML element or attribute.

To see an example of this kind of metadata, look at the "test.encoding.AttributeBean" class in the Axis source, or generate your own bean from XML which uses attributes or names which would be illegal in Java.
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 a proxy (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);
  }
}

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

You will see that WSDL2Java generates all the classes that were generated before for the client, but it generates a few new files:
WSDL clause Java class(es) generated
For each binding A skeleton class
An implementation template class
For all services One deploy.wsdd file
One undeploy.wsdd file

If you don't specify the "--skeletonDeploy true" option, a skeleton will not be generated. Instead, the generated deploy.wsdd will indicate that the implementation class is deployed directly. In such cases, the deploy.wsdd contains extra meta data describing the operations and parameters of the implementation class. Here is how you run WSDL2Java to deploy directly to the implementation:

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

And here are the server side files that are generated:
WSDL clause Java class(es) generated
For each binding An implementation template class
For all services One deploy.wsdd file with operation meta data
One undeploy.wsdd file
Bindings
Skeleton Description (for Skeleton Deployment)

The skeleton class is the class that sits between the Axis engine and the actual service implementation. Its name is the binding name with suffix "Skeleton". For example, for the AddressBook binding, WSDL2Java will generate:

public class AddressBookSOAPBindingSkeleton implements AddressBook,
    org.apache.axis.wsdl.Skeleton {
  private AddressBook impl;

  public AddressBookSOAPBindingSkeleton() {
    this.impl = new AddressBookSOAPBindingImpl();
  }

  public AddressBookSOAPBindingSkeleton(AddressBook impl) {
    this.impl = impl;
  }

  public void addEntry(java.lang.String name, Address address)
      throws java.rmi.RemoteException {
    impl.addEntry(name, address);
  }
}

(The real skeleton is actually much richer. For brevity we just show you the basic skeleton.)

The skeleton contains an implementation of the AddressBook service. This implementation is either passed into the skeleton on construction, or an instance of the generated implementation is created. When the Axis engine calls the skeleton's addEntry method, it simply delegates the invocation to the real implementation's addEntry method.
Implementation Template Description

WSDL2Java also generates an implementation template from the binding:

public class AddressBookSOAPBindingImpl implements AddressBook {
  public void addEntry(String name, Address address)
      throws java.rmi.RemoteException {
  }
}

This template could actually be used as a test implementation but, as you can see, it doesn't do anything. It is intended that the service writer fill out the implementation from this template.

When WSDL2Java is asked to generate the implementation template (via the --server-side flag), it will ONLY generate it if it does not already exist. If this implementation already exists, it will not be overwritten.
Services

The tool also builds you a "deploy.wsdd" and an "undeploy.wsdd" for each service for use with the AdminClient. These files may be used to deploy the service once you've filled in the methods of the Implementation class, compiled the code, and made the classes available to your Axis engine.
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:

% 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 thelocation 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.

The output WSDL document will contain the appropriate WSDL types, messages, portType, bindings and service descriptions to support a SOAP rpc, encoding web service. If your specified interface methods reference other classes, the Java2WSDL tool will generate the appropriate xml types to represent the classes and any nested/inherited types. The tool supports JAX-RPC complex types (bean classes), extension classes, enumeration classes, arrays and Holder classes.

The Java2WSDL tool has many additional options which are detailed in the reference guide. There is an Ant Task to integrate this action with an Ant based build process.
Step 3: Create Bindings using WSDL2Java

Use the generated WSDL file to build the appropriate client/server bindings for the web service (see WSDL2Java):

% java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true
    -Nurn:Example6 samples.userguide.example6 wp.wsdl

This will generate the following files:

    * WidgetPriceSoapBindingImpl.java : Java file containing the default server implementation of the WidgetPrice web service.
      You will need to modify the *SoapBindingImpl file to add your implementation (see samples/userguide/example6/WidgetPriceSoapBindingImpl.java).
    * WidgetPrice.java: New interface file that contains the appropriate java.rmi.Remote usages.
    * WidgetPriceService.java: Java file containing the client side service interface.
    * WidgetPriceServiceLocator.java: Java file containing the client side service implementation class.
    * WidgetPriceSoapBindingSkeleton.java: Server side skeleton.
    * WidgetPriceSoapBindingStub.java: Client side stub.
    * deploy.wsdd: Deployment descriptor
    * undeploy.wsdd: Undeployment descriptor
    * (data types): Java files will be produced for all of the other types and holders necessary for the web service. There are no additional files for the WidgetPrice web service.

Now you have all of the necessary files to build your client/server side code and deploy the web service!

你可能感兴趣的:(java,apache,spring,Web,SOAP)