Web Services and the .NET Framework
Accessing a .NET Web Service using Apache/SOAP and Java

Gopalan Suresh Raj

Note
To work with any of these samples, you will need the following:
.........................................Microsoft .NET SDK or
.........................................Microsoft Visual Studio.NET Beta 2 or higher
.........................................Java JDK ver 1.3 or higher
.........................................Java Mail ver 1.2 or higher
.........................................Java Activation Framework
.........................................Apache SOAP ver 2.2 or higher
.........................................Apache Xerces (a Java XML Parser)

 

Building .NET Web Service Clients using Apache/SOAP and Java

In this example, we are going to build an Apache/SOAP Java Client to the OIDServer Web Service that we created earlier using C#/.NET. Since the Apache SOAP Toolkit is designed as a Remote Procedure Call (RPC) mechanism as opposed to a document exchange mechanism, it expects RPC encoding.

Therefore, the various steps that are involved in creating a .NET Web Service Client using Apache/SOAP and Java are as follows:

  1. Develop a Class that generates the SOAP message Body element - the ApacheMessageBody.java class file

  2. Develop a Class that parses the SOAP response - the SAXHandler.java class file

  3. Develop a Java Proxy for the .NET endpoint - the ApacheSoapProxy.java class file

  4. Develop the Actual Client - Client.java class file

  5. Build and Run

1. Develop a Class that generates the SOAP message Body element

Apache SOAP performs serialization and deserialization using a class called Body, which uses its marshall() and unmarshall() methods to perform the respective operations. While marshall() is an instance method, unmarshall() is a static class method. This means, it is not possible to just inherit from the Body class and override the unmarshall() method. However, you can change the Serialization behavior of the Body class by overriding the marshall() method as shown from Lines 30 through 51 in the code below. Depending on the number of methods that you may have, you can either create multiple Body implementations, each with their own marshall() methods, or you may choose to build one Body implementation with a single marshall()method which can choose the right code to execute based on other information.

Since ASP.NET endpoints use document/literal encoding as opposed to RPC encoding, you only need to write out the following information:

Notice that in the code below, we extend the Body class as shown on line 20

ApacheMessageBody.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
//////////////////////////////////////////////////////
/// This Class generates the SOAP message Body element
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
//////////////////////////////////////////////////////

import java.io.*;
import org.apache.soap.*;
import org.apache.soap.util.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.rpc.SOAPContext;

/**
  * This Class generates the SOAP message Body element
  * @author Gopalan Suresh Raj
  */

public class ApacheMessageBody extends Body {

  /** potential argument to the web method. */
  //public String inputString_;

  /**
    * Override the Apache default marshall method
    * and change how the SOAP Body element
    * is serialized.
    */

  public void marshall (String inScopeEncodingStyle,
                                    Writer sink,
                                    NSStack nameSpaceStack,
                                    XMLJavaMappingRegistry registry,
                                    SOAPContext context) throws IllegalArgumentException, IOException {
    // Set the Body element
    String soapEnvironmentNamespacePrefix = "SOAP-ENV";
    sink.write ('<'+soapEnvironmentNamespacePrefix+':'+
                     Constants.ELEM_BODY+'>'+
                     StringUtils.lineSeparator);

    // Write out the method name and related argument (s)
    sink.write ("<generateOID xmlns=\""http://tempuri.org/\">"+
                     //"<inputString>"+inputString_+"</inputString>"+
                     "</generateOID>");

    // Close the Body element
    sink.write ("</" + soapEnvironmentNamespacePrefix+':'+
                     Constants.ELEM_BODY+'>'+
                     StringUtils.lineSeparator);
    nameSpaceStack.popScope ();
  }
}

Now that you can send the message, you should be able to read the message. To read the message, you need a class that can handle SAX Processing for you and read the data.

2. Develop a Class that parses the SOAP Response

Whenever a message goes out and comes back, the entire SOAP response can be determined. The SAXHandler class will be used by the Proxy that we will build soon. The SAX Response Handler that we're building now is a general purpose class that can obtain any single element response. Therefore, users should be able to use the class without any other modifications. If the value is a Boolean, or other numeric, or date types, you can perform the conversion after you retrieve the result using the getResult() method to obtain the single element response. You will be required to modify the code for complex types and arrays. 

SAXHandler.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
//////////////////////////////////////////////////////
/// This Class parses the SOAP response
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
//////////////////////////////////////////////////////

import org.xml.sax.*;
import org.xml.sax.helpers.*;

/**
  * This Class parses the SOAP response. This is a
  * general purpose class  that can obtain any single
  * element response.
  *
  * @author Gopalan Suresh Raj
  */

public class SAXHandler extends DefaultHandler {

  private String indent_ = "";
  private String result_ = "";
  private String elementToSearchFor_ = "";
  private boolean foundResult_ = false;

  /** Default No argument constructor */
  public SAXHandler () {
  }

  /**
    * Retrieve the result for a single element
    * The code has to be modified as necessary
    * for more complex types and arrays
    */

  public String getResult () {
    return result_;
  }

  /** Provide the element name to search for */
  public void setElementToSearchFor (String elementName) {
    elementToSearchFor_ = elementName;
  }

  /** Retrieve the set element name */
  public String getElementToSearchFor () {
    return elementToSearchFor_;
  }

  /**
    * Overriden method of the DefaultHandler class to
    * gain notification of all SAX events
    */

  public void startElement (String namespaceURI,
                                         String localName,
                                         String qName,
                                         Attributes attributes) throws SAXException {
    if (foundResult_ == false) {
      foundResult_ = (localName.compareTo (elementToSearchFor_) == 0);
    }
  }

  /**
    * Overriden method of the DefaultHandler class to
    * gain notification of all SAX events
    */

  public void characters (char[] characters, int start, int length) throws SAXException {
    if (foundResult_ == true) {
      result_ = String.valueOf (characters, start, length);
      foundResult_ = false;
    }
  }

}

3. Develop a Java Proxy for the .NET Endpoint

Even though the IBM Web Services toolkit can produce proxies, when it comes to .NET interoperability, it is easier to build one by hand. The proxy will facilitate Client Applications to instantiate the proxy and invoke method calls on the proxy, all the while only worrying about handling SOAP faults. The proxy shown below performs the following sets of operations:

Since Apache SOAP 2.2 classes encode messages using RPC encoding, for .NET interoperability which uses document/literal encoding, you must override the code that constructs the body in addition to the code that interprets the response.

ApacheSoapProxy.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
//////////////////////////////////////////////////////
/// This Class creates a Java Proxy for the .NET endpoint
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
//////////////////////////////////////////////////////

import java.io.*;
import java.net.*;
import javax.activation.*;
import org.apache.soap.*;
import org.apache.soap.messaging.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.apache.xerces.parsers.SAXParser;

/**
  * This Class creates a Java Proxy for the .NET endpoint
  * @author Gopalan Suresh Raj
  */

public class ApacheSoapProxy {
  private URL url_ = null;
  private String soapActionUri_ = "";
  private Message message_ = new Message ();
  private Envelope envelope_ = new Envelope ();
  DataHandler soapMessage_ = null;

  /** Default No argument constructor */
  public ApacheSoapProxy () throws MalformedURLException {
    this.url_ = new URL ("http://localhost/OIDServer/OIDServer.asmx");
  }

  /** Set the End Point URL */
  public synchronized void setEndPoint (URL url) {
    this.url_ = url;
  }

  /** Retrieve the End Point URL */
  public synchronized URL getEndPoint () {
    return this.url_;
  }

  /**
    * Apache 2.2 classes encode messages differently than .NET does.
    * Therefore we have to override the piece that builds the body and
    * the pieces that interpret the response.
    */

  public synchronized String generateOID () throws SOAPException {
    String returnValue = "";

    if (this.url_ == null) {
      throw new SOAPException (Constants.FAULT_CODE_CLIENT,
                                               "A URL must be specified through "+
                                               "ApacheSoapProxy.setEndPoint(URL)");
    }
    // Get this from the soapAction attribute on the
    // soap:operation element that is found within the SOAP
    // binding information in the WSDL
    this.soapActionUri_ = "http://icommware.com/generateOID";
    ApacheMessageBody ourBody = new ApacheMessageBody ();

    // Set the argument
    //theBody.inputString_ = "";

    // Replace the default body with our own
    this.envelope_.setBody (ourBody);
    message_.send (this.getEndPoint(), this.soapActionUri_, this.envelope_);

    try {
      // Since the Body.unmarshall() handler is static, we can't
      // replace the basic machinery easily. Instead, we must obtain
      // and parse the message on our own.
      this.soapMessage_ = this.message_.receive();
      XMLReader reader = (XMLReader)Class.forName("org.apache.xerces.parsers.SAXParser").newInstance();
      SAXHandler handler = new SAXHandler();
      handler.setElementToSearchFor ("generateOIDResult");

      // Set the Content Handler
      reader.setContentHandler (handler);

      // Parse the file
      reader.parse ( new InputSource (new StringReader (this.soapMessage_.getContent().toString() )));

      // If we reached here, the result has been parsed and
      // stored in the handler instance.
      returnValue = handler.getResult ();
    }
    catch (Exception exception) {
      exception.printStackTrace ();
    }
    return returnValue;
  }

}

4. Develop the Actual Client

Notice that on Line 23, we instantiate the Proxy, and on line 26, we call the web method on the proxy.

Client.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
//////////////////////////////////////////////////////
/// The following example illustrates a Client to a
/// WebService developed using C# and the .NET Framework.
///
/// author: Gopalan Suresh Raj
/// Copyright (c), 2002. All Rights Reserved.
/// URL: https://gsraj.tripod.com/
/// email: gopalan@gmx.net
//////////////////////////////////////////////////////

import java.io.*;

/**
  * Web Service Client Class
  * @author Gopalan Suresh Raj
  */

public class Client {

  /** Entry Point to this Application */
  public static void main(String[] args) {
    try {
      // Create a proxy
      ApacheSoapProxy proxy = new ApacheSoapProxy ();

      // Invoke generateOID() over SOAP and get the new OID
      String result = proxy.generateOID ();

      // Print out the value
      System.out.println ("The new OID is :"+result);
    }
    catch (java.net.MalformedURLException exception) {
      exception.printStackTrace ();
    }
    catch (org.apache.soap.SOAPException exception) {
      exception.printStackTrace ();
    }
  }
}

5. Compile the classes

Compile the classes as shown below: 

Command Prompt
C:\MyProjects\Cornucopia\WebService\javaSoapClient>javac -classpath .;C:\java\soap-2_2\lib\soap.jar;C:\java\jaf-1.0.1\activation.jar;C:\java\javamail-1.2\mail.jar;C:\java\xerces-1_4_3\xerces.jar ApacheSoapProxy.java Client.java SAXHandler.java ApacheMessageBody.java

C:\MyProjects\Cornucopia\WebService\javaSoapClient>

6. Run the Client

Command Prompt
C:\MyProjects\Cornucopia\WebService\javaSoapClient>java -cp .;C:\java\xerces-1_4_3\xerces.jar;C:\java\soap-2_2\lib\soap.jar;C:\java\jaf-1.0.1\activation.
jar;C:\java\javamail-1.2\mail.jar; Client
The new OID is :0d70d55a-b57e-4402-9e2e-1c51f20469b3

C:\MyProjects\Cornucopia\WebService\javaSoapClient>

 

 

Building a complete Web Service component using C# and .NET
Building a Web Service Client using C# and .NET
Accessing a .NET Web Service using Apache/SOAP and Java

 

Download the entire source code as a zip file.

 

click here to go to
My Advanced C#/.NET Tutorial Page...

About the Author...
Gopalan Suresh Raj is a Software Architect, Developer and an active Author. He has co-authored a number of books including "Professional JMS", "Enterprise Java Computing-Applications and Architecture" and "The Awesome Power of JavaBeans". His expertise spans enterprise component architectures and distributed object computing. Visit him at his Web Cornucopia© site (https://gsraj.tripod.com/) or mail him at gopalan@gmx.net.

 


Go to the Component Engineering Cornucopia page

This site was developed and is maintained by Gopalan Suresh Raj

This page has been visited times since January 9, 2002.

Last Updated : Jan 09, '02

If you have any questions, comments, or problems regarding this site, please write to me I would love to hear from you.


Copyright (c) 1997-2002, Gopalan Suresh Raj - All rights reserved. Terms of use.

All products and companies mentioned at this site are trademarks of their respective owners.