introduction to soap-ws

Key words: Web service, SOAP, WSIF, XML, WSDL.

Preface: I just try to introduce the web service implementation and client program methods briefly. I will organize this article on a line of SOAP profile, WSDL profile, Web Service Server, Web Service client programming and WSIF open source. So those guys who are not familiar with SOAP and Web Service can have an outline about this technology and guys who have ever touched them can get some unknown features. That is my object and my hope.

Of coz, any feedback is welcome.

 

 

1         Soap Introduction.

SOAP, standing as “Simple Object Access Protocol”, is initialized by MS, and then developed by IBM, Lotus and some other IT giants, now submitted to W3C, is widely accepted.

Someone generalizes soap as RPC+XML+HTTP. To be Simple, that is quite right. XML is its data presentation, and HTTP is its bottom communication protocol, as a message carrier, and RPC is responsible to the invocation consistency.

You have to keep this in your mind that SOAP is a kind of communication protocol, not a service, and it is developed to solve the complexity of multi-platform’s cooperation and interoperation. The main ideas to this protocol are to be simple and extensible. It is not efficient because mostly it is embedded in HTTP but HTTP is not an efficient protocol and it takes time to parse the XML doc. Maybe you can apprehend the use of xml form because xml is an open and self-descript data present protocol, but why it uses the inefficient transaction protocol HTTP? That is because it can make it simple and it can go through the firework. Repeat it one more time, it is inefficient, if your system senses the efficiency, SOAP is not a good choice, and you’d better choose RMI or CORBA.

 

You can Track the SOAP(1.1) profile in http://www.w3.org/TR/2000/NOTE-SOAP-20000508/.

 

First I want to talk about the structure of SOAP.

SOAP message conforms to the XML document standards, so the message format is much like any other legal xml documents, for instance, only one root element, name space, nested elements and so so.

A complete SOAP message contains 2 parts, one is envelop and the other is attachment.

Often, we may ignore the attachment part because in the WS we nearly use it, and I will focus on the envelop part in the following talk. As what I said, soap message can only have the envelop part, which can include soap header and soap body, of which body is mandatory and header is optional. You can image this scene just like that  you insert your text into the envelope with the right destination address and push the envelope into a mailbox.

 Header, much like the header of http, contains attribute-value couples (but in xml form). Body, taking the main data, provides a simple mechanism for exchanging the mandatory information with the ultimate recipient. It may carry no more one fault message which indicates the error code and information.

A structure diagram is shown below:

Soap message often is embedded in Http message, so that it can go through the firework and means light weight.

Now http message examples including the soap message are shown below:

Example 1 SOAP Message Embedded in HTTP Request

POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
       <m:GetLastTradePrice xmlns:m="Some-URI">
           <symbol>DIS</symbol>
       </m:GetLastTradePrice>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Following is the response message containing the HTTP message with the SOAP message as the payload:

Example 2 SOAP Message Embedded in HTTP Response

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   <SOAP-ENV:Body>
       <m:GetLastTradePriceResponse xmlns:m="Some-URI">
           <Price>34.5</Price>
       </m:GetLastTradePriceResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

(Examples provided by SOAP 1.1 profile)

 

Now I have to interpret the attribute: SOAPAction, because it will be used in WSDL file and may make you confused (because I do! Although this property is not mandatory, in fact, we always ignore it).

The definition:

soapaction= "SOAPAction" ":" [ <"> URI-reference <"> ]
URI-reference= <as defined in RFC 2396 [4]>

 

it is said that you can have three types soapaction in the http message:

soapaction:”uri”

soapaction:””

soapaction:

 

Actually, this attribute is required in http-soap message but its purpose is not clearly in the profile (there are much argument). Someone says that it can be used by the server like firework to filter the http message and redirect the soap body to the destination uri. However, I don’t encounter one instance. But to be interoperable, you’d better set its value to the value specified in the wsdl and bracket it with quotation marks like this:

SOAPAction: “http://electrocommerce.org/abc#MyMessage”.

Otherwise, some soap server may response error (apache server can work well anyway).

 

Then, I will introduce the java api and program about it.

Project: JAAS

Package: javax.xml.soap

SAAJ builds on the interfaces and abstract classes and many of the classes begin by invoking factory methods to create a factory such as SOAPConnectionFactory and SOAPFactory.

The most commonly used classes are:

  • SOAPMessage: Contains the message, both the XML and non-XML parts
  • SOAPHeader: Represents the SOAP header XML element
  • SOAPBody: Represents the SOAP body XML element
  • SOAPElement: Represents the other elements in the SOAP message

Other parts of the SAAJ interface include:

  • MessageContext: Contains a SOAP message and related properties
  • AttachmentPart: Represents a binary attachment
  • SOAPPart: Represents the XML part of the message
  • SOAPEnvelope: Represents the SOAP envelope XML element
  • SOAPFault: Represents the SOAP fault XML element

Then I will show you a classical code segment how to construct a soap message and send it.

public File resize(String endPoint,File file)
{
   //get a soap connection so you can send your message
   SOAPConnection connection =
      SOAPConnectionFactory.newInstance().createConnection();
   //you can construct a message in the standalone application
   SOAPMessage message = MessageFactory.newInstance().createMessage();
   SOAPPart part = message.getSOAPPart();
   SOAPEnvelope envelope = part.getEnvelope();
   SOAPBody body = envelope.getBody();
    
   //create and insert the content to the body
   SOAPBodyElement operation =
      body.addBodyElement(
         envelope.createName("resize",
                             "ps",
                             "http://psol.com/2004/ws/resize"));
   operation.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");

       
       
        
         
       
       
   DataHandler dh = new DataHandler(new FileDataSource(file));
   AttachmentPart attachment = message.createAttachmentPart(dh);
   SOAPElement source = operation.addChildElement("source",""),
               percent = operation.addChildElement("percent","");
   message.addAttachmentPart(attachment);
   source.addAttribute(envelope.createName("href"),
                       "cid:" + attachment.getContentId());
   width.addTextNode("20");
   
   //send the message
   SOAPMessage result = connection.call(message,endPoint);
   part = result.getSOAPPart();
   envelope = part.getEnvelope();
   body = envelope.getBody();
   if(!body.hasFault())
   {
      Iterator iterator = result.getAttachments();
      if(iterator.hasNext())
      {
         dh = ((AttachmentPart)iterator.next()).getDataHandler();
         String fname = dh.getName();
         if(null != fname)
            return new File(fname);
      }
   }
   return null;
}

       
       
        
         
       
       
And the message:

POST /ws/resize HTTP/1.0
Content-Type: multipart/related; type="text/xml"; 
     start="<EB6FC7EDE9EF4E510F641C481A9FF1F3>"; 
     boundary="----=_Part_0_7145370.1075485514903"
Accept: application/soap+xml, multipart/related, text/*
Host: localhost:8080
SOAPAction: ""
Content-Length: 1506005

       
       
        
         
       
       
------=_Part_0_7145370.1075485514903
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <EB6FC7EDE9EF4E510F641C481A9FF1F3>

       
       
        
         
       
       
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ps:resize 
          soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
          xmlns:ps="http://psol.com/2004/ws/resize" 
          xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
   <source href="cid:E1A97E9D40359F85CA19D1B8A7C52AA3"/>
   <percent>20</percent>
  </ps:resize>
 </sapenv:Body>
</soapenv:Envelope>

       
       
        
         
       
       
------=_Part_0_7145370.1075485514903
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Content-Id: <E1A97E9D40359F85CA19D1B8A7C52AA3>

       
       
        
         
       
       
note: binary data deleted...

       
       
        
         
       
       
------=_Part_0_7145370.1075485514903--

 

2         WSDL introduction

Abstract from w3c (http://www.w3.org/TR/wsdl):

WSDL is an XML format for describing network services as a set of endpoints operating on messages containing either document-oriented or procedure-oriented information. The operations and messages are described abstractly, and then bound to a concrete network protocol and message format to define an endpoint. Related concrete endpoints are combined into abstract endpoints (services). WSDL is extensible to allow description of endpoints and their messages regardless of what message formats or network protocols are used to communicate,

From the abstract, we can get these ideas:

1: all the WSDL files are XML doc, and conform to the XML constraint.

2: it describes the network service.

3: it is extensible.

Put all above besides, given you want to share your service to others in internet, what you should do then others may know your service and can invoke it?

1: you should expose your service position so that others outside can locate it and access it.

2: you should tell others what service you have provided. So the customer knows that if he wants to do a sum calculation, you can help him, because you provide the sum service, but if he wants to do the multiplication, then he should turn to others because you don’t support this service.

 3: you should point out that how to serialize the parameters so that you can parse them even your customer is on the heterogeneous platform.

4: you should indicate that how you return the value if needed and in what form so he can understand it. Yup, it is better if the input parameters he sends and the value he receives are consistent. That would be simple.

5: if there is an exception, so your service cannot complete his request, what you will response to him?

6: Can you identify your custom and maintain the session? If your service supports a sequent operations and the later one depends on the former one, then you have to maintain the session, or uncertainty may occur.

Let us see the solution the WSDL provides.

1: it encapsulates the service address so that you can access it.

Mostly, it is a legal URI (if it is extended to EJB or JMS, it may be the jndi name or the queue name).

2: it lists all the exposed operations. In the WS, it is called SEI, short name for Service Endpoint Interface.

3: it just tells you the parameter types (there is a mapping type between java types and XSD types) then the serialization would be done by the gateway intermediate.

4: the same to the input parameters.

5: it will indicate that what kind of exception it may throws and you can catch the fault.

6: The Web Service Server will not maintain the session, it is said that it’s stateless (in the server end). 

Now let me show you the outline of WSDL file (you can review the schema http://schemas.xmlsoap.org/wsdl/ if you are familiar with schema syntax).

A WSDL doc defines services as collections of network endpoints, or ports.

The main elements and their functions:

  • Types– a container for data type definitions using some type system (such as XSD).
  • Message– an abstract, typed definition of the data being communicated.
  • Operation– an abstract description of an action supported by the service.
  • Port Type–an abstract set of operations supported by one or more endpoints.
  • Binding– a concrete protocol and data format specification for a particular port type.
  • Port– a single endpoint defined as a combination of a binding and a network address.
  • Service– a collection of related endpoints.

It defines the data types, simple or complex

 

Types

Element

Message

Part

PortTypes

Operation

Input

Output

Bindings

Binding style

Operation

Service

Port

Address

It wraps the data type as a message

Here defines the SEI, an abstract set of operations

Make the data format and protocol concrete, e.g. the protocol is soap and the style is document/literal

Expose the services. The port is directed to the binding, and the address you can access its service.

 If you want to get the wsdl document, its address is the address uri in the port appending “?wsdl”. For example, see the service segment below:

 <service name="SvcProxyIM_ServiceProxy2">

    <port name="HelloObjectPort" binding="tns:HelloObjectBinding">

      <soap:address location="http://pek-wkst119:8080/myproxy_helloObject "/>

    </port>

  </service>

Then the wsdl address is http://pek-wkst119:8080/myproxy_helloObject?wsdl.

 

Ok, now, given you have a brief impression about the WSDL, I will paste a typical WSDL document to make you clearer.

 

Example 1 SOAP 1.1 Request/Response via HTTP

<?xml version="1.0"?>

<definitions name="StockQuote"

 

targetNamespace="http://example.com/stockquote.wsdl"

          xmlns:tns="http://example.com/stockquote.wsdl"

          xmlns:xsd1="http://example.com/stockquote.xsd"

          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

          xmlns="http://schemas.xmlsoap.org/wsdl/">

 

    <types>

       <schema targetNamespace="http://example.com/stockquote.xsd"

              xmlns="http://www.w3.org/2000/10/XMLSchema">

           <element name="TradePriceRequest">

              <complexType>

                  <all>

                      <element name="tickerSymbol" type="string"/>

                  </all>

              </complexType>

           </element>

           <element name="TradePrice">

              <complexType>

                  <all>

                      <element name="price" type="float"/>

                  </all>

              </complexType>

           </element>

       </schema>

    </types>

 

    <message name="GetLastTradePriceInput">

        <part name="body" element="xsd1:TradePriceRequest"/>

    </message>

 

    <message name="GetLastTradePriceOutput">

        <part name="body" element="xsd1:TradePrice"/>

    </message>

 

    <portType name="StockQuotePortType">

        <operation name="GetLastTradePrice">

           <input message="tns:GetLastTradePriceInput"/>

           <output message="tns:GetLastTradePriceOutput"/>

        </operation>

    </portType>

 

    <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">

        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

        <operation name="GetLastTradePrice">

           <soap:operation soapAction="http://example.com/GetLastTradePrice"/>

           <input>

               <soap:body use="literal"/>

           </input>

           <output>

               <soap:body use="literal"/>

           </output>

        </operation>

    </binding>

 

    <service name="StockQuoteService">

        <documentation>My first service</documentation>

        <port name="StockQuotePort" binding="tns:StockQuoteBinding">

           <soap:address location="http://example.com/stockquote"/>

        </port>

    </service>

 

</definitions>

 

Now, let’s go on to the next topic.

3         Web Service Server

Supposed you want to provide the web service, what should you do?

You have to provide you service in a servlet or in a stateless EJB bean. So first, you have to have a web container or an EJB application server. Of coz, you can use .Net, but I know nothing about it, so here I do not want to confuse both of us.

For Web container, Tomcat is proposed.

For EJB application server, you can choose Axis, JBoss, WebLogic and WebSphere.

 

Programming in Java, there is a principle that you should program the interface, not the class. That is a style, and you should keep it in your mind.

I emphasize this because the Web Service programming also follows this principle.

 

Now I will demo 3 programming models to build a Web Service project.

1: provide your service as a servlet on Tomcat.

2: provide your service as an Ejb on Jboss, according to EJB2.0 profile.

3: provide your service as an Ejb on Jboss, using annotation, according to EJB3.0 profile.

 

I will use a simple sample that just provides a simple service-- echo a string.

The SEI:

package ejb.com;

 

public interface MyWSI extends java.rmi.Remote {

    public java.lang.String sayHello(java.lang.String parameters) throws java.rmi.RemoteException;

}

 

Important: Eclipse3.2 with WTP is used.

 

Follow me, let is head to the first sample.

1: Servlet on Tomcat

If we just use the servlet, we don’t need to make the interface extend the Remote. Above all, all we need, is a plain java bean.

 

Step 1: Add tomcat to the Server, Window-> Preference -> Server -> Installed Runtimes -> Add…

 

 

Step 2: create a dynamic Web Project, File->New -> project -> Web -> Dynamic Web Project…

 

Step 3: Add 2 java files, one is the interface, the other is implementation class…

package com.sei;

 

public interface MyWSI {

    public String echoString(String word);

}

 

 

package com.sei;

 

public class MyService implements MyWSI {

       public String echoString(String word) {

              // TODO Auto-generated method stub

              return "hello, "+word;

       }

}

 

Step 4: build your project.

 

Step 5: Add the web service, new-> others ->Web Services -> web Service

 

Set the service implementation, and then the configuration.

Click next, next and finish.

 

Now you can see that your service has been deployed to Tomcat (from the console).

Want to make sure it?

Ok, go to your project in Eclipse, WSForTomcat ->WebContent->wsdl->MyService.wsdl, open the wsdl, copy the address at the end of the file, e.g. http://localhost:8080/WSForTomcat/services/MyService

Then try to visit http://localhost:8080/WSForTomcat/services/MyService?wsdl by appending “?wsdl” to the original address.

 

Wonderful, you get it!

Of coz, you can to have a client to test it, to test the service, but just wait a minute-- you can have the way at the next topic.

 

Now, let’s go on to the next issue, how to provide web service on EJB application.

 

2: Service on EJB Application

First, you have to know it, that only stateless session bean can be adopted to provide web service. Because for web service, individual status is hardly be kept in the session for each client, separately and distinguishing.

Supposed you have agreed on it, let’s go ahead.

 

Step 1: set XDoclet , Window-> Preferences ->XDoclet

Then you should modify the ejbdoclet if needed. Now we want to build the sample for JBoss, so make sure, the Jboss is checked in the tasks.

 

Step 2: Create the EJB project. File-> New->project->EJB->ejb project

 

 

Step 3: create a Stateless session bean, New->others->Ejb->XDoclet Enterprise JavaBean->session bean

 

After you finish the creation, XDoclet will help you to create a series of java files for you, the remote interface, the Home bean and the Util class for client.

 

Step 4:  change or add method to the Echo.java and EchoBean.java.

/*

 * Generated by XDoclet - Do not edit!

 */

package com.sei;

 

/**

 * Remote interface for Echo.

 * @generated

 * @wtp generated

 */

public interface Echo

   extends javax.ejb.EJBObject

{

   /**

    * <!-- begin-xdoclet-definition -->

    * @generated //TODO: Must provide implementation for bean method stub    */

   public java.lang.String EchoString( java.lang.String param )

      throws java.rmi.RemoteException;

 

}

 

 

/**

 *

 */

package com.sei;

 

 

/**

 *

 * <!-- begin-user-doc -->

 * A generated session bean

 * <!-- end-user-doc -->

 * *

 * <!-- begin-xdoclet-definition -->

 * @ejb.bean name="Echo"     

 *           description="An EJB named Echo"

 *           display-name="Echo"

 *           jndi-name="Echo"

 *           type="Stateless"

 *           transaction-type="Container"

 *

 * <!-- end-xdoclet-definition -->

 * @generated

 */

 

public abstract class EchoBean implements javax.ejb.SessionBean {

 

       /**

        *

        * <!-- begin-xdoclet-definition -->

        * @ejb.create-method view-type="remote"

        * <!-- end-xdoclet-definition -->

        * @generated

        *

        * //TODO: Must provide implementation for bean create stub

        */

       public void ejbCreate() {

       }

 

       /**

        *

        * <!-- begin-xdoclet-definition -->

        * @ejb.interface-method view-type="remote"

        * <!-- end-xdoclet-definition -->

        * @generated

        *

        * //TODO: Must provide implementation for bean method stub

        */

       public String EchoString(String param) {

              return "hello, "+param;

       }

}

 

Step 5: build your project.

In fact, now, you can deploy your project to jboss and run it.

But now it is just an ejb, and you can not access it through web service.

 

Step 6: create a EAP application. File->New->project->J2EE-> Enterprise Application Project

 

Click next and add WSEjbProject as its dependent module.

Now we have to register the web service to the EAP.

 

Step 6: create an interface similar to the Echo.java, but extends the Remote interface, not the EjbObject. Remember to move this file to the src folder under the WSEjbProject.

package com.sei;

import java.rmi.*;

public interface EchoIntf

   extends Remote

{

 

   public java.lang.String EchoString( java.lang.String param )

      throws java.rmi.RemoteException;

 

}

 

Step 7: compile the java file: EchoIntf.java

 

Step 8: use the wstools (provide in $Jboss_Home/bin) to generate wsdl file, mapping file and webservice.xml.

 

Java-wsdl.xml:

<configuration>   

    <java-wsdl>

      <service name="EchoService" style="document" parameter-style="bare"

        endpoint="com.sei.EchoIntf" />

   

      <namespaces target-namespace="http://sei.com"

         type-namespace="http://sei.com"/>

   

       <mapping file="jaxrpc-mapping.xml"/>

        <webservices ejb-link="Echo"/>

 

    </java-wsdl>   

  </configuration>

 

Caution: endpoint is the SEI class path. The ejb-link should be the jndi of Echo bean.

 

Step 9: copy those generated files to WSEjbProject.

New a folder under META-INFO, named wsdl, and move the EchoService.wsdl here.

Move jaxrpc-mapping.xml and webservice.xml to META-INFO.

 

Step 10: Verify the webservice.xml

Step 11: add service endpoint to the ejb-jar.xml

Add a property under ejb-jar/enterprise-beans/session: <service-endpoint>com.sei.EchoIntf</service-endpoint>

The value is the sei.

Step 12: build the project and application.

 

Step 13: deploy the application(EAR package) to server Jboss.

 

Make sure you have add jboss to the server, similar to adding the tomcat server.

Run the application on server, and then select the jboss as its server.

During the deployment, maybe you will get some errors or warnings, ignore them.

 

Ok, you can visit: http://localhost:8080/jbossws/services

Then you will see the Registered Service Endpoints.

 

Let’s go on!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值