Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / Apache

SOAP Messages Exchange Between .NET Clients and Axis Apache Web Services

3.86/5 (4 votes)
2 Aug 2007CPOL6 min read 1   994  
.NET Client sending and receiving complex SOAP messages from Java Axis web service

Introduction

There is not much information on sending SOAP messages between .NET clients and web services written in Java and if it exists, it is based on sending and receiving primitive data information such as numbers and small text strings.

But what if we want to interchange complex objects between two platforms that in theory should interchange information in a transparent way? The fact is that a client sends a SOAP request message (SOAP provides a standard and simple way to present messages in an XML format) to a web service, the web service receives the XML document, verifies that it has the SOAP message characteristics (Envelope, Header, Body), processes the message and returns a SOAP response message.

Any object (no matter how sophisticated) will be serialized, and after that it will be incorporated in the SOAP message and sent to the web service. If the structure of the SOAP message is the same in the client as in the web service, the only thing that we would have to worry about is that there exists a correct object deserialization in the web service, in order for the message to be interpreted correctly.

The objective of this article is to show how to send and receive complex SOAP messages between .NET client and Java Axis web service and it is not to explain how the transmission of SOAP messages works in each platform. That information can be found very easily on the Web.

Using the Code

The example here consists in sending an XML document from a client written in C# to a web service written in Java. Apache Axis as implementation tool of SOAP messages in an Apache Tomcat web server. This is the structure of the XML document to send:

Screenshot - DOTNET_with_WS_APACHEAXIS_1.jpg

* Table Order Details of the base of Northwind data coming with SQL Server 2000.

The web service processes the purchase orders of the XML documents requests and returns the accumulated of the unit price multiplied by for the quantity minus the discount. The return structure is as follow:

Screenshot - DOTNET_with_WS_APACHEAXIS_2.jpg

Apache Axis Web Service

Start by building a web service with a method that receives an XML document as a parameter. Previously, we needed to install Tomcat Apache and the necessary files in order for the Axis Apache to work (for example the JAVA JRE and JDK). Building an Axis web service is very simple. We have to follow the steps given below:

  1. First, deploy the web service through a describer file. To do this, create the following document and name it deploy.wsdd.
    XML
    <deployment xmlns="http ://xml.apache.org/axis/wsdd/"
            xmlns:java="http ://xml.apache.org/axis/wsdd/providers/java"
            xmlns:xsi="http ://www.w3.org/2000/10/XMLSchema - instance">
        <service name="wsOrderSummary" provider="java:RPC">
            <parameter name="className" value="wsOrderSummary">
            <parameter name="allowedMethods" value="*">
            <operation name="getOrderSummary">
              <parameter name="XMLdoc" mode="IN">
            </operation>
        </service>
    </deployment>
  2. Next, execute the deploy file to update the Axis server. Execute the following code in a DOS command window. Perhaps you'll have to change the paths and jar files versions, if it's necessary.
    java - classpath "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\axis.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\axis-ant.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\jaxrpc.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\commons,logging,1.0.4.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\commons,discovery,0.2.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\saaj.jar";
    "C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\lib\activation.jar" 
    org.apache.axis.client.AdminClient deploy.wsdd
  3. Then, build the following two classes in Java. The first class will be named WsOrderSummary, that it's the web service in Java properly. Add the following method to your wsOrderSummary class:
    Java
    // The Axis Web Method
    public Document getOrderSummary(Document XMLdoc )
    {
        try  
        {
            NodeList XMLrows = XMLdoc.getElementsByTagName("row");
            ClassOrderSummary  array = 
    		new ClassOrderSummary[1];  // Adding one empty item
                
    
            for( int row=0; row < XMLrows.getLength() ; row++) 
            {
                NodeList XMLcolumns = XMLrows.item( row ).getChildNodes();
                    
                // OrderId 
                int orderId = Integer.parseInt
    		(XMLcolumns.item(0).getTextContent().trim());
                // unitPrice 
                float unitPrice = Float.valueOf
    		(XMLcolumns.item(2).getTextContent().trim()).floatValue();
                // quantity 
                int Quantity=Integer.parseInt
    		(XMLcolumns.item(3).getTextContent().trim());
                // Discount 
                float Discount = Float.valueOf
    		(XMLcolumns.item(4).getTextContent().trim()).floatValue();
                // Total 
                float Total = (unitPrice*Quantity)*( 1 - Discount);
                    
                // Searching in the array 
                int idx=existsOrder( array, orderId );
                if( idx >= 0) 
                {
                    // found it!
                    array[idx].OrderTotal += Total;
                }
                else 
                {
                    // if not exists, creates a new one 
                    array[array.length-1] = new ClassOrderSummary();
                    array[array.length-1].OrderID = orderId;
                    array[array.length-1].OrderTotal = total;
                    array=(ClassOrderSummary ) resizeArray( array, array.length + 1);
                }
            }
    
            array=(ClassOrderSummary ) resizeArray
    		( array, array.length -1);  // Dropping last empty item
            //System.out.println ( array.length );
            Document XMLResponse = createXMLOrders( array );
            return(XMLResponse );
        }
        catch(Exception ex )
        {
            System.out.println ( " error:" + ex.getMessage ());
            ex.printStackTrace ();
            return( null );
        }
    }

    And the second class will be used to build the XML SOAP response. This class will be named ClassOrderSummary. See ClassOrderSummary.java file:

    Java
    public class ClassOrderSummary {
        public int OrderID;
        public float OrderTotal;
        
        public ClassOrderSummary() 
        {
        }
    }
  4. After we have the two Java files, compile them by using the Java JDK compiler. Execute the following code in a DOS command window. Don't forget to modify javac.exe path file if it's necessary, also the two Java class files.
    C:\Program Files\Java\jdk1.5.0_05\bin\javac.exe 
    wsOrderSummary.java ClassOrderSummary.java
  5. To finish the deploy, the compiler creates 2 class files, copy those files to the axis' classes folder:
    C:\Program Files\Foundation software Apache\
    Tomcat 5.5\webapps\axis\WEB-INF\classes
  6. Restart the Tomcat Apache service. Test the web service opening a web browser on the following URL http://localhost:8080/axis/services/wsOrderSummary?wsdl. Change the server name if the web service isn't on your local host machine. If you have an IDE (eclipse, JDeveloper, etc.), one of the recover steps mentioned will be carried out by the IDE.

    JAVA Tools used
    TypeVersion
    JRE1.5.0.06
    JDK1.5.0.05
    Apache Tomcat5.5
    Apache Axis1.4

C# Client

To send a SOAP message in the .NET Framework, we use WSE (Web Services Enhancements) 3.0. We start by analyzing the SOAP message structure that the Axis web service publishes.

XML
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
        xmlns:impl="http://localhost:8080/axis/services/wsOrderSummary" 
        xmlns:apachesoap="http://xml.apache.org/xml-soap">
  <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <impl:getOrderSummary>
      <XMLdoc xsi:type="apachesoap:Document"></XMLdoc>
    </impl:getOrderSummary>
  </soap:Body>
</soap:Envelope>

There are two important namespaces, the first one is "xmlns:impl" that qualifies the name space for this particular web service and the second one is "xmlns:apachesoap" that identifies Java special class types. Inside the Body is the method "impl:getOrderSummary", which we want to invoke. Inside this method is the parameter named "XMLDoc" that it's an "apachesoap:Document" type. It's equivalent to the XmlDocument object in .NET.

  1. First, create a console application. After this, create a derived class from the SoapClient object, in order to access its properties and mainly to invoke the SendRequestResponse method, it permits sending and receiving SOAP messages. It will be named ClassSoapClient.
    Java
    public class ClassSoapClient : SoapClient
    {
        private String soapAction;
        public ClassSoapClient(string soapAction, EndpointReference ref1) : base(ref1)
        {
            this.soapAction = soapAction;
        }
    
        public SoapEnvelope SendEnvelope(XmlDocument xmlDoc)
        {
            SoapEnvelope soapRequest = new SoapEnvelope();
            soapRequest.CreateBody();
    
            soapRequest.Body.AppendChild
    		(soapRequest.ImportNode(xmlDoc.DocumentElement, true));
            return base.SendRequestResponse(soapAction, soapRequest);
        }
    }

    Note that SendEnvelope method receives an XML document as a parameter; it has inside an object serialized that we want to send to the Java web service. It inserts the XML document in SoapEnvelope (part of WSE) type object. Next, it calls SendRequestResponse method which sent the SOAP message through a protocol that usually is HTTP. SendRequestResponse won't return the control until an answer message is received or timeout is reached. Then the answer message is returned as a SoapEnvelope object again.

  2. Next, update the Program class that is in the file Program.cs, which is part of the console application that it has created previously.
    Java
    static void Main( string args )
    {
        Run();
    }

    In the Run method, write the following:

    Java
    String _UrlWebService = 
    	"http://localhost:8080/axis/services/wsOrderSummary"; 	// Change the web 
    						// service's URL here
    String _pathFiles = "C:\\NET_with_WS_AXIS\\DotNetClient\\Xml\\";// Change the XML 
    							// local path here
    int _minutes = 3;

    "_UrlWebservice" is the URL of the location of the web service; the variable "_pathFiles" is the path in which the XML for sending is found and where we save the soap message received from the Java web service. Create an instance of ClassSoapClient class and set the timeout in 3 minutes, also create the Address object, which represents a URL object from where the web service will send the SOAP message.

    Java
    ClassSoapClient sc = new ClassSoapClient
    	("http ://inApacheAxisSoapActionDoesnotCare.org",
    					// new Uri(_UrlWebService ));
    sc.Timeout = _minutes * 60000;
    sc.Destination.Address = new Microsoft.Web.Services3.Addressing.Address
    			(new Uri(_UrlWebService));
  3. Next create and load the XML document for sending.
    Java
    XmlDocument docXML = new XmlDocument();
    docXML.Load ( _pathFiles + " Orders.xml ");
    

    It's necessary to serialize the method and the parameter of the web service that we want to access. Without this, the SendEnvelope method doesn't know which method to access. It loads all this in an XmlDocument object adding as a child parameter of the method the previous XML document with the orders purchase information.

    Java
    // This is the web service method and its parameter in xml format
    String soapString = "<impl:getOrderSummary xmlns:
    xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
         " xmlns:impl=\"http://localhost:8080/axis/services/wsOrderSummary\" >" +
         "<XMLdoc xsi:type=\"apachesoap:Document\" />" +
         "</impl:getOrderSummary>";
    
    XmlDocument requestXML = new XmlDocument();
    requestXML.LoadXml(soapString);
    requestXML.FirstChild.FirstChild.AppendChild(requestXML.ImportNode
    (docXML.DocumentElement, true));
    
  4. Finally, the SOAP Request is sent, the method gets back the SOAP Response, the SOAP Response is saved into a file for later analysis. Also we extract the "ORDERS" node; it contains the answer from the web service. At this point, we can deserialize this XML document in an object, for example load it into a Dataset object or save it into a database.
    Java
    SoapEnvelope soapResponse = new SoapEnvelope();
    // Call Axis web service and get soap response
    soapResponse = sc.SendEnvelope(requestXML);
    
    // saving soap response
    soapResponse.Save(_pathFiles + "soapResponse.xml");
    docXML.InnerXml = soapResponse.Body.GetElementsByTagName
    ("ORDERS")[0].ParentNode.InnerXml;
    
    // Finally we get orders summary XML ready for deserialize
    docXML.Save(_pathFiles + "OrdersSummary.xml");
    

    .NET Tools used
    TypeVersion
    Microsoft.NET Framework2.0
    WSE3.0
    IDEMicrosoft Visual C# 2005 Express Edition

History

  • 2nd August, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)