WSO2 SOA Enablement Server can interoperate with Microsoft .NET either as a client or a server, using Java primitive types, .NET Common Types System types and XML schema (2001 W3C recommendation). The format of a SOAP message on the wire varies, based on the two attributes of the binding element in the service's WSDL document.
The value of the style attribute is either document or rpc, denoting the style of exchanges. Document-style exchanges mean that the client and server want to send and receive the message as plain XML documents. RPC-style is when the XML message uses method call syntax.
The value of the use attribute is either literal or encoded. Literal use means that the XML message must adhere strictly to the XML Schema that describes its structure. In the encoded mode, these messages can transgress the Schema, according to SOAP Encoding rules, allowing more flexibility to serialize complex data structures, such as cyclic graphs and arrays.
The following list outlines the software and service packs that you need to compile and run C# clients and access the features of ASP.NET:
Microsoft .NET Framework and .NET Framework SDK
IIS with the latest security updates (must be installed prior to installing the .NET Framework and .NET Framework SDK)
Administrative rights on the computer
Example 250 shows how a WSO2 SOA Enablement Server Web service can be invoked from a .NET client using Document-style messaging. It contains just one echo operation. This returns the Boolean variable with which it is called.
Example 250. NET to WSO2 SOA Enablement Server Echo
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.dotNetToWasp; public class Service { public boolean EchoBoolean(boolean in) { return in; } }
Before creating the .NET client, start the WSO2 SOA Enablement Server and deploy this service to it. You must create the C# Web service proxy first. The following command will do so for the dotNetToWasp example, located at WASP_HOME\src\example\applicationIntegration\dotNetIntegration\dotNetToWasp:
wsdl.exe /out:dotNetToWaspProxy.cs http://localhost:6060/dotNetToWasp
This command tells the Web services Description Language Utility to generate proxy code for XML Web service clients from a WSDL file. Example 251 shows the generated proxy:
Example 251. .NET Service Autogenerated Proxy Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 1.0.3705.288 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ // // This source code was autogenerated by wsdl, Version=1.0.3705.288. // using System.Diagnostics; using System.Xml.Serialization; using System; using System.Web.Services.Protocols; using System.ComponentModel; using System.Web.Services; /// <remarks/> // CODEGEN: The optional WSDL extension element 'java-operation' from namespace // 'http://wso2.com/mapping/' was not handled. [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute( Name = "Service", Namespace ="http://wso2.com/wsdl/example/applicationIntegration/" + "dotNetIntegration/dotNetToWasp/")] public class JavaService : System.Web.Services.Protocols.SoapHttpClientProtocol { public instance instanceValue; /// <remarks/> public JavaService() { this.Url = "http://localhost:6060/dotNetToWasp"; } /// <remarks/> [System.Web.Services.Protocols.SoapHeaderAttribute("instanceValue", Direction = System.Web.Services.Protocols.SoapHeaderDirection.InOut, Required = false)] [System.Web.Services.Protocols.SoapDocumentMethodAttribute( "http://wso2.com/wsdl/example/applicationIntegration" + "/dotNetIntegration/dotNetToWasp/Service#EchoBoolean#KFopWg==", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Bare)] [return : System.Xml.Serialization.XmlElementAttribute("boolean_Response", Namespace = "http://wso2.com/xsd/SchemaTypes/")] public boolean EchoBoolean( [System.Xml.Serialization.XmlElementAttribute( Namespace = "http://wso2.com/xsd/SchemaTypes/")] bool p0) { object[] results = this.Invoke("EchoBoolean", new object[] { p0 }); return ((bool) (results[0])); } /// <remarks/> public System.IAsyncResult BeginEchoBoolean( bool p0, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke( "EchoBoolean", new object[] { p0 }, callback, asyncState); } /// <remarks/> public bool EndEchoBoolean(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((bool) (results[0])); } } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace = "http://idoox.com/interface")] [System.Xml.Serialization.XmlRootAttribute( Namespace = "http://idoox.com/interface", IsNullable = false)] public class instance : SoapHeader { /// <remarks/> [System.Xml.Serialization.XmlElementAttribute("id", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("setId", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("notFound", typeof(string))] [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] public string Item; /// <remarks/> [System.Xml.Serialization.XmlIgnoreAttribute()] public ItemChoiceType ItemElementName; } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace = "http://idoox.com/interface", IncludeInSchema = false)] public enum ItemChoiceType { /// <remarks/> id, /// <remarks/> setId, /// <remarks/> notFound, }
The .NET client program creates an instance of the WSO2 SOA Enablement Server Web service proxy, invokes the EchoBoolean() method, and displays the string that is returned. This is shown in Example 252.
Example 252. .NET Client Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. using System; namespace dotNetToWaspClient { class Client { [STAThread] static void Main(string[] args) { try { JavaService ws = new JavaService(); ws.Url = "http://localhost:6060/dotNetToWasp"; Console.WriteLine(".NET Client to WASP Service - Doc / Lit\n"); Console.WriteLine("WASP Service url: " + ws.Url + "\n"); Console.WriteLine("WASP is great product, isn't it!\n"); Console.WriteLine(".NET says: It is " + ws.EchoBoolean(true)); } catch (Exception err) { Console.WriteLine(err.Message); } finally { Console.ReadLine(); } } } }
To build this .NET client, execute the following command line:
csc.exe /out:Client.exe /t:exe Client.cs dotNetToWaspProxy.cs
Here is the .NET client output:
Client.exe .NET Client to WSO2 SOA Enablement Server Service - Doc / Lit WSO2 SOA Enablement Server Service URL: http://localhost:6060/dotNetToWasp WSO2 SOA Enablement Server is a great product, isn't it. NET says: It is True
This section provides a quick reference for mapping data types between different systems. There are four tables that describe mappings between:
![]() | Caution |
---|---|
In this last case, .NET throws an exception if you try to send a null value from Java. This problem is addressed in the LongObject demo. We strongly recommend reading the Readme.txt file for this demo. |
Table 43. Java Primitive Types and Their Mapping to CTS Types
Java Primitive Type | CTS Type (C# Type) |
---|---|
boolean | Boolean(bool) |
byte | SByte(sbyte) |
char | String(string) |
double | Double(Double) |
float | Single(Single) |
int | Int32(int) |
long | Int64(long) |
short | Int16(short) |
Table 44. Supported XSD Schema Types and Their Mapping to Java Types
XMLSchema Type | Java Type |
---|---|
anyURI | java.lang.String |
base64Binary | byte[] |
boolean | boolean |
byte | byte |
date | org.idoox.wasp.serialization.xsdbuiltin.Date |
dateTime | java.util.Date |
decimal | java.math.BigDecimal |
double | double |
duration | org.idoox.wasp.serialization.xsdbuiltin.Duration |
ENTITIES | java.lang.String |
ENTITY | java.lang.String |
float | float |
gDay | org.idoox.wasp.serialization.xsdbuiltin.GDay |
gMonth | org.idoox.wasp.serialization.xsdbuiltin.GMonth |
gMonthDay | org.idoox.wasp.serialization.xsdbuiltin.GMonthDay |
gYear | org.idoox.wasp.serialization.xsdbuiltin.GYear |
gYearMonth | org.idoox.wasp.serialization.xsdbuiltin.GYearMonth |
hexBinary | org.idoox.wasp.serialization.xsdbuiltin.HexBinary |
ID | java.lang.String |
IDREF | java.lang.String |
IDREFS | java.lang.String |
int | int |
integer | java.math.BigInteger |
language | java.lang.String |
long | long |
Name | java.lang.String |
NCName | java.lang.String |
negativeInteger | java.math.BigInteger |
NMTOKEN | java.lang.String |
NMTOKENS | java.lang.String |
nonNegativeInteger | java.math.BigInteger |
nonPositiveInteger | java.math.BigInteger |
normalizedString | org.idoox.wasp.serialization.xsdbuiltin.NormalizedString |
NOTATION | java.lang.String |
positiveInteger | java.math.BigInteger |
QName | javax.xml.rpc.namespace.QName |
short | short |
string | java.lang.String |
time | org.idoox.wasp.serialization.xsdbuiltin.Time |
token | org.idoox.wasp.serialization.xsdbuiltin.Token |
unsignedByte | java.lang.Short |
unsignedInt | java.lang.Long |
unsignedLong | java.math.BigInteger |
unsignedShort | java.lang.Integer |
Table 45. CTS Types and Their Mapping to Java Types
CTS type (C# type) | Java Type |
---|---|
Boolean(bool) | boolean |
Byte(byte) | java.lang.Short |
Char(char) | java.lang.Integer |
Decimal(decimal) | java.math.BigDecimal |
Double(double) | double |
Single(float) | float |
Int32(int) | int |
Int64(long) | long |
SByte(sbyte) | byte |
Int16(short) | short |
UInt32(uint) | java.lang.Long |
UInt64(ulong) | java.math.BigInteger |
UInt16(ushort) | java.lang.Integer |
Table 46. Java Objects that are Mapped to .NET Primitive Types
Java Object | .NET Primitive Type |
---|---|
java.lang.Integer | int |
java.lang.Long | long |
java.lang.Date | date |
![]() | Caution |
---|---|
.NET throws an exception if you try to send a null value from a Java object that is mapped to a .NET primitive type. This problem is addressed in our LongObject demo. We strongly recommend reading the Readme.txt file for this demo. |
WSO2 SOA Enablement Server can easily be used as a .NET client. In this section, we will demonstrate the process of invoking a .NET service. The source code that will be used here can be found at %WASP_HOME%\src\example\applicationIntegration\dotNetIntegration\waspToDotNet.
Example 253 shows the .NET service source file. The service defines a single GetStockInfo() web method, which returns the variable with which it is called.
Example 253. .NET Web Service Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. <%@ WebService Language="C#" Class="examples.Service" %> using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; namespace examples { [WebService(Namespace="http://wso2.com/.NET/")] public class Service : System.Web.Services.WebService { [WebMethod] public string GetStockInfo (string title) { return title + " is rapidly growing!"; } } }
To deploy this .NET Web service to Microsoft IIS, you have to create a virtual folder in IIS following these steps:
Click the Windows Start button, select Control Panel-> and then open Internet Services Manager.
In the left pane, right-click Default Web Site, choose , and then click Virtual Directory.
In the first screen of the Virtual Directory Creation Wizard, click Next, type the alias for the site: waspToDotNet and click Next.
In the third screen, click Browse. Browse to %WASP_HOME%\src\example\applicationIntegration\dotNetIntegration\waspToDotNet. Click Next.
In the fourth screen, click Next.
Click Finish to complete the wizard.
Close Internet Services Manager.
The .NET service in Example 253 is now available at http://localhost/waspToDotNet/Service.asmx. To create the client-side bindings, use the WSDL2Java utility to generate the Java interface from the .NET WSDL file. The command line for using this utility to generate the Java interface is:
WSDL2Java -p example.applicationIntegration.dotNetIntegration.waspToDotNet --url http://localhost/waspToDotNet/Service.asmx?WSDL Processing http://localhost/waspToDotNet/Service.asmx?WSDL... done.
The generated interface is displayed in Example 254 :
Example 254. .NET Service Interface Source
package example.applicationIntegration.dotNetIntegration.waspToDotNet; /** */ public interface ServiceSoap { /** */ example.applicationIntegration.dotNetIntegration.waspToDotNet.GetStockInfoResponse GetStockInfo( example.applicationIntegration.dotNetIntegration.waspToDotNet.GetStockInfo parameters); /** * Asynchronous 'begin' version of operation GetStockInfo */ org.systinet.wasp.async.AsyncConversation beginGetStockInfo( example.applicationIntegration.dotNetIntegration.waspToDotNet.GetStockInfo parameters); /** * Asynchronous 'end' version of operation GetStockInfo */ example.applicationIntegration.dotNetIntegration.waspToDotNet.GetStockInfoResponse endGetStockInfo( org.systinet.wasp.async.AsyncConversation conversation); }
The client uses this interface to bind to the .NET Web service. It then invokes GetStockInfo() and displays the string that is returned. The client source code is shown in Example 255 .
Example 255. The Client Source Code
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.waspToDotNet; import org.systinet.wasp.webservice.Registry; public class Client { public static void main(String[] args) throws Exception { String wsdlURI = "http://localhost/waspToDotNet/Service.asmx?wsdl"; // lookup service ServiceSoap service = (ServiceSoap) Registry.lookup(wsdlURI, ServiceSoap.class); // call method System.out.println("\nWASP Client to .NET Service\n"); GetStockInfo request = new GetStockInfo(); request.title = "WSO2"; GetStockInfoResponse response = service.GetStockInfo(request); System.out.println(response.GetStockInfoResult); } }
To compile the client code, execute these commands:
mkdir build mkdir build\classes javac -classpath c:\WSO2 SOA Enablement Server\lib\wasp.jar -d build\classes ServiceSoap.java Client.java
The client can be run now. Here is the WSO2 SOA Enablement Server client output:
java -classpath build\classes; c:\WSO2 SOA Enablement Server\lib\wasp.jar example.applicationIntegration.dotNetIntegration.waspToDotNet.Client WSO2 SOA Enablement Server Client to .NET Service - Rpc / Enc WSO2 SOA Enablement Server Service url: http://localhost/waspToDotNet/Service.asmx Systinet is rapidly growing!
WSO2 SOA Enablement Server offers wide support for all basic types of Java collections. WSO2 SOA Enablement Server includes pre-generated XML Schemas for collections. Schemas were composed especially to be compatible with .NET. Thanks to this, WSO2 SOA Enablement Server is able to interoperate with .NET over all the types of these collections.
Example 256 shows a Java interface representing a Web service that simply echoes all the known types of collections.
Example 256. Example Interface
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.javaCollections; public interface CollectionsService { java.util.List echoList(java.util.List list); java.util.ArrayList echoArrayList(java.util.ArrayList arrayList); java.util.LinkedList echoLinkedList(java.util.LinkedList linkedList); java.util.Vector echoVector(java.util.Vector vector); java.util.Set echoSet(java.util.Set set); java.util.HashSet echoHashSet(java.util.HashSet hashSet); java.util.SortedSet echoSortedSet(java.util.SortedSet sortedSet); java.util.TreeSet echoTreeSet(java.util.TreeSet treeSet); java.util.Map echoMap(java.util.Map map); java.util.HashMap echoHashMap(java.util.HashMap hashMap); java.util.SortedMap echoSortedMap(java.util.SortedMap sortedMap); java.util.TreeMap echoTreeMap(java.util.TreeMap TreeMap); java.util.Hashtable echoHashtable(java.util.Hashtable hashtable); java.util.Iterator echoIterator(java.util.Iterator iterator); java.util.Enumeration echoEnumeration(java.util.Enumeration enumeration); }
The following sequence of commands was used to generate the .NET proxy and structures for C#.
>javac Collections.java >Java2WSDL Collections >wsdl.exe Definitions
The output should resemble the following:
Microsoft (R) Web Services Description Language Utility [Microsoft (R) .NET Framework, Version 1.0.3705.0] Copyright (C) Microsoft Corporation 1998-2001. All rights reserved. Warning: one or more optional WSDL extension elements were ignored. Warnings were encountered. Review generated source comments for more details. Writing file 'JavaService.cs'.
Table 4 lists the C# classes generated by the .NET wsdl tool. Each class corresponds to a Java Container interface. Although the name or namespace of the .NET class can be changed, its structure should always remain the same. The generated .NET proxy classes have the same structure regardless of whether the service uses rpc/encoded or document/literal style exchanges.
Table 47. .NET Structures for Java Collections
Java Class Name | .NET Structure |
---|---|
java.util.List | public class List { public object[] Items; } |
java.util.Set | public class Set { public object[] Items; } |
java.util.Map | public class Map { public object[] Keys; public object[] Values; } |
java.util.Iterator | public class Iterator { public object[] Data; } |
java.util.Enumeration | public class Enumeration { public object[] Data; } |
There are many implementations in Java of these classes. Different implementations may have different properties. Here are a few examples of implementations used by WSO2 SOA Enablement Server:
Java class | Use in WSO2 SOA Enablement Server |
---|---|
java.util.ArrayList | Default implementation of List used by WSO2 SOA Enablement Server. Uses a dynamically extending array. |
java.util.TreeSet | Set requiring elements to be the same type. When iterating over items, elements will be ordered. |
java.util.Hashtable | Synchronized implementation of Map interface. |
For more information about Java collections, see Default Serialization: Java Collections.
For representation of Java Collections in XML Schema for rpc/encoded style, see .NET-Compatible Containers for SOAP Encoded.
For document/literal style, see .NET-Compatible Containers for SOAP Literal.
The only standard collections that can be sent via SOAP are:
ArrayList from the System.Collections namespace
StringCollection from the System.Collections.Specialized namespace.
WSO2 SOA Enablement Server on the client side follows .NET style and translates these structures into arrays.
Representations of collections in XML Schema differ between rpc/encoded and document/literal Web services. To see the difference between these two types of message transmission, consider a Web service with four echo methods: one for ArrayList and one for StringCollection using an rpc/encoded exchange, and one for each of these two methods using document/literal. Using the WSO2 SOA Enablement Server WSDL2Java tool, a Java interface for the service is generated, including the collection structures. This interface is shown in Example 257 .
Example 257. Generated Service Interface
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.dotNetCollections; /** */ public interface CollectionsSoap { /** */ example.applicationIntegration.dotNetIntegration.dotNetCollections.EchoArrayListDOCResponse EchoArrayListDOC( example.applicationIntegration.dotNetIntegration.dotNetCollections.EchoArrayListDOC parameters); /** */ java.lang.Object[] EchoArrayListRPC(java.lang.Object[] arr); /** */ example.applicationIntegration.dotNetIntegration.dotNetCollections.EchoStringCollectionDOCResponse EchoStringCollectionDOC( example.applicationIntegration.dotNetIntegration.dotNetCollections.EchoStringCollectionDOC parameters); /** */ java.lang.String[] EchoStringCollectionRPC(java.lang.String[] scoll); }
As expected, in the rpc/encoded methods, each collection is a simple array of Objects or Strings. The document/literal methods, however, create a new class for each type of collection. These custom classes contain an array of Objects or Strings.
Example 258 lists the custom classes that are generated using document/literal exchanges.
Example 258. ArrayList and StringCollection for Java in Document/literal
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.dotNetCollections; /** * */ public class EchoArrayListDOC { public java.lang.Object[] arr; } // Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.dotNetCollections; /** * */ public class EchoStringCollectionDOC { public java.lang.String[] scoll; } // Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.dotNetCollections; /** * */ public class EchoStringCollectionDOC { public java.lang.String[] scoll; }
WSO2 SOA Enablement Server is compatible with .NET using Http Basic Authentication and SSL mechanisms. Http Basic Authentication is when a user's passwords and username are encoded using Base64 encoding and sent over HTTP. SSL is the technology that is used to encrypt and decrypt messages sent between the client and server. SSL encrypts a message from the client, then sends it to the server. When the message is received by the server, SSL decrypts it and verifies that it came from the correct sender.
We shall take a look at both of these mechanisms, with respect to WSO2 SOA Enablement Server and .NET interoperability, in detail.
A Web service hosted on WSO2 SOA Enablement Server and using HTTP basic authentication does not need any special setting to be interoperable with a .NET client. It is just as easy for a WSO2 SOA Enablement Server client to invoke a .NET service. In this section, we will discuss both situations.
We will now walk through the process of .NET client invocation of a secure WSO2 SOA Enablement Server Web service, to learn about their interoperability using HTTP Basic Authentication. The Web service contains only one operation, which returns a string variable. A user is authenticated via the Basic Authentication mechanism. Example 259 shows the source code for the HelloWorld Service.
Example 259. WSO2 SOA Enablement Server Web Service Source Code
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.security. basicDotNetToWasp; public class HelloWorldImpl implements HelloWorld { public String GetSecureInfo() { return "Secret Hello"; } }
As mentioned before, there are not any security settings in the source code. All the steps needed to make the service secure are done using WSO2 SOA Enablement Server tools:
Set HttpBasic as the security provider for the service using the ProvidersManager tool.
Create a username + password identity in the Userstore with the UserStore tool. The .NET client then uses this identity to authenticate to WSO2 SOA Enablement Server.
Before creating the .NET client, start the WSO2 SOA Enablement Server and deploy the service in Example 259 to it. You have to create the WSO2 SOA Enablement Server Web service proxy first.
wsdl.exe /out:dotNetToWaspSecureProxy.cs http://localhost:6060/secure/hello/dnet/
This command tells the .NET Web services Description Language Utility to generate code for Web service clients from a service WSDL file. Example 260 shows the generated proxy:
Example 260. .NET Service Autogenerated Proxy Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 1.0.3705.288 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ // // This source code was autogenerated by wsdl, Version=1.0.3705.288. // using System.Diagnostics; using System.Xml.Serialization; using System; using System.Web.Services.Protocols; using System.ComponentModel; using System.Web.Services; /// <remarks/> // CODEGEN: The optional WSDL extension element 'java-operation' from namespace // 'http://wso2.com/mapping/' was not handled. [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute( Name="HelloWorld", Namespace="http://wso2.com/wsdl/example/applicationIntegration/" + "dotNetIntegration/security/basicDotNetToWasp/")] public class JavaService : System.Web.Services.Protocols.SoapHttpClientProtocol { public instance instanceValue; /// <remarks/> public JavaService() { this.Url = "http://localhost:6060/secure/hello/dotNet/"; } /// <remarks/> [System.Web.Services.Protocols.SoapHeaderAttribute("instanceValue", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut, Required=false)] [System.Web.Services.Protocols.SoapDocumentMethodAttribute( "http://wso2.com/wsdl/example/applicationIntegration/" + "dotNetIntegration/security/basicDotNetToWasp/HelloWorldImpl" + "#GetSecureInfo#KClMamF2YS9sYW5nL1N0cmluZzs=", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)] [return: System.Xml.Serialization.XmlElementAttribute("string_Response", Namespace="http://wso2.com/xsd/SchemaTypes/", IsNullable=true)] public string GetSecureInfo() { object[] results = this.Invoke("GetSecureInfo", new object[0]); return ((string)(results[0])); } /// <remarks/> public System.IAsyncResult BeginGetSecureInfo(System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("GetSecureInfo", new object[0], callback, asyncState); } /// <remarks/> public string EndGetSecureInfo(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((string)(results[0])); } } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace="http://idoox.com/interface")] [System.Xml.Serialization.XmlRootAttribute( Namespace="http://idoox.com/interface", IsNullable=false)] public class instance : SoapHeader { /// <remarks/> [System.Xml.Serialization.XmlElementAttribute("id", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("setId", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("notFound", typeof(string))] [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] public string Item; /// <remarks/> [System.Xml.Serialization.XmlIgnoreAttribute()] public ItemChoiceType ItemElementName; } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace="http://idoox.com/interface", IncludeInSchema=false)] public enum ItemChoiceType { /// <remarks/> id, /// <remarks/> setId, /// <remarks/> notFound, }
The .NET client program creates an instance of a WSO2 SOA Enablement Server Web service proxy, gets the credentials from the user, invokes the GetSecureInfo() method, and finally displays the string that is returned. Example 261 is the client program.
Example 261. .NET Client Source Code
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. using System; using System.Net; namespace SecurityBasicClient { class Client { [STAThread] static void Main(string[] args) { JavaService ws = new JavaService(); ws.Url = "http://localhost:6060/secure/hello/dotNet/"; Console.Write("User:"); string strUser = Console.ReadLine(); Console.Write("Password:"); string strPassword = Console.ReadLine(); ICredentials credentials = new NetworkCredential(strUser, strPassword); try { ws.Credentials = credentials; Console.WriteLine(ws.GetSecureInfo()); } catch (Exception err) { Console.WriteLine(err.Message); } finally { Console.ReadLine(); } } } }
To build this .NET client, execute the following command:
csc.exe /out:Client.exe /t:exe Client.cs dotNetToWaspSecureProxy.cs
This command tells the C# compiler to compose an executable file called client.exe with the /out:client.exe argument. The type of file produced is a Win32 console application, as indicated by /t:exe , the target option.
The output that occurs when the .NET client invokes the secure Hello Service is shown below .
Client.exe User: HelloClient Password: password Secret Hello
WSO2 SOA Enablement Server can easily be used as a .NET client as well. In this section, we will go through the process of invoking a secure .NET RPC-style service.
Example 262 shows the .NET service source file. The service is flagged as an RPC service using the [SoapRpcService] property and defines a single GetSecureInfo() web method, which returns a string variable.
Example 262. Secure .NET Web Service Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. using System; <%@ WebService Language="C#" Class="SecureInfoService.Service" %> using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; namespace SecureInfoService { [WebService(Namespace="http://wso2.com/.NET/Security/")] [SoapRpcService] public class Service : System.Web.Services.WebService { [WebMethod] [SoapRpcMethod] public string GetSecureInfo () { return "Shh, this is top secret!"; } } }
To deploy this .NET Web service to Microsoft IIS you have to create a virtual folder in IIS by taking these steps:
Click the Windows Start button, point to Programs, select , and then click Internet Services Manager.
In the left pane, right-click Default Web Site, point to , and then click Virtual Directory.
In the first screen of the Virtual Directory Creation Wizard, click Next and type the alias for the site: basicWaspToDotNet. Then click Next.
In the third screen, click Browse. Browse to %WASP_HOME%\src\example\applicationIntegration\dotNetIntegration\security\basicWaspToDotNet. Click Next.
In the fourth screen, click Next.
Click Finish to complete the wizard.
In the left pane, right-click Directory Security, and then click the Edit button in the Anonymous access and authentication control section.
, point to , selectUncheck Anonymous access and Integrated Windows authentication and check Basic authentication (Note that the password is sent in clear text). Click the Yes button and the OK buttons in the previous dialogs.
Close Internet Services Manager.
The .NET service is now available at http://localhost/basicWaspToDotNet/Service.asmx.
The WSO2 SOA Enablement Server for Java client accesses a secure service published by the .NET server the same way as it accesses a service hosted by the WSO2 SOA Enablement Server. First, it authenticates using the username, password and HttpBasic Security Provider. Then, it looks up and invokes the service. See Example 263.
Example 263. WSO2 SOA Enablement Server Client Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.security. basicWaspToDotNet; import org.idoox.security.Credentials; import org.idoox.wasp.WaspSecurity; import org.systinet.wasp.webservice.ServiceClient; import java.util.HashMap; import java.util.Map; /** * Secure version of HelloWorld. */ public class Client { public static void main(String[] args) throws Exception { String USERNAME = "user"; String PASSWORD = "changeit"; String definitionURI = "http://localhost/basicWaspToDotNet/Service.asmx?WSDL"; // IIS requires authentication for accessing WSDL Map map = new HashMap(2); map.put(WaspSecurity.HTTP_BASIC_USER_NAME, USERNAME); map.put(WaspSecurity.HTTP_BASIC_PASSWORD, PASSWORD); // create a service client ServiceClient serviceClient = ServiceClient.create(definitionURI, map); // acquire client credentials Credentials credentials = WaspSecurity.acquireClientCredentials(USERNAME, PASSWORD, "HttpBasic"); // associate credentials with the service client WaspSecurity.setCredentials(serviceClient, new Credentials[]{credentials}); // create a service proxy HelloWorld hello = (HelloWorld) serviceClient.createProxy(HelloWorld.class); // method call System.out.println(hello.GetSecureInfo()); } }
WSO2 SOA Enablement Server and .NET are also interoperable using the Secure Sockets Layer (SSL). We will take the same approach to this section as in the previous, by running through examples of a:
.NET client to a WSO2 SOA Enablement Server service
WSO2 SOA Enablement Server client to a .NET service
This section is devoted to showing how a secure WSO2 SOA Enablement Server Web service can be invoked from a .NET client. This Web service contains just one operation, which returns a string variable. The service uses Secure Sockets Layer (SSL) and requires client certificates.
![]() | Note |
---|---|
You must attach a server certificate to the service to use the SSL features. |
The service source code that is accessed via SSL is the same as that used for HttpBasic Authentication (see Example 259 ). As in that situation, the ProvidersManager tool is used to set SSL as the security provider for the service.
You must export a certificate to be used by the WSO2 SOA Enablement Server server during the SSL handshake with the client. The PStore tool is used for this purpose. This certificate is created during security installation and is saved in the KeyStore with the default alias sslalias. The exported certificate must be saved as a trusted certificate authority on the .NET client side.
If client authentication is required, use the WSO2 SOA Enablement Server Administration Console to set the HTTPS transport attribute needsClientAuth to true. Note that this flag is global and is valid for all services hosted by a WSO2 SOA Enablement Server.
Before creating the .NET client, start the WSO2 SOA Enablement Server and deploy the previously mentioned service to it. You need to create the Web service proxy first. Execute the following commands to create the Web service proxy:
wsdl.exe /out:dotNetToWaspSecureProxy.cs https://localhost:6443/secure/hello/dnet/
This command tells the Web service's Description Language Utility to generate code for the Web service client from the WSDL file. Example 264 shows the generated proxy.
Example 264. .NET Service Autogenerated Proxy
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 1.0.3705.288 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ // // This source code was autogenerated by wsdl, Version=1.0.3705.288. // using System.Diagnostics; using System.Xml.Serialization; using System; using System.Web.Services.Protocols; using System.ComponentModel; using System.Web.Services; /// <remarks/> // CODEGEN: The optional WSDL extension element 'java-operation' from namespace // 'http://wso2.com/mapping/' was not handled. [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="HelloWorld", Namespace="http://wso2.com/wsdl/example/applicationIntegration/" + "dotNetIntegration/security/basicDotNetToWasp/")] public class JavaService : System.Web.Services.Protocols.SoapHttpClientProtocol { public instance instanceValue; /// <remarks/> public JavaService() { this.Url = "http://localhost:6060/secure/hello/dotNet/"; } /// <remarks/> [System.Web.Services.Protocols.SoapHeaderAttribute("instanceValue", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut, Required=false)] [System.Web.Services.Protocols.SoapDocumentMethodAttribute( "http://wso2.com/wsdl/example/applicationIntegration/" + "dotNetIntegration/security/basicDotNetToWasp/HelloWorldImpl" + "#GetSecureInfo#KClMamF2YS9sYW5nL1N0cmluZzs=", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)] [return: System.Xml.Serialization.XmlElementAttribute("string_Response", Namespace="http://wso2.com/xsd/SchemaTypes/", IsNullable=true)] public string GetSecureInfo() { object[] results = this.Invoke("GetSecureInfo", new object[0]); return ((string)(results[0])); } /// <remarks/> public System.IAsyncResult BeginGetSecureInfo(System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("GetSecureInfo", new object[0], callback, asyncState); } /// <remarks/> public string EndGetSecureInfo(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((string)(results[0])); } } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace="http://idoox.com/interface")] [System.Xml.Serialization.XmlRootAttribute( Namespace="http://idoox.com/interface", IsNullable=false)] public class instance : SoapHeader { /// <remarks/> [System.Xml.Serialization.XmlElementAttribute("id", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("setId", typeof(string))] [System.Xml.Serialization.XmlElementAttribute("notFound", typeof(string))] [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] public string Item; /// <remarks/> [System.Xml.Serialization.XmlIgnoreAttribute()] public ItemChoiceType ItemElementName; } /// <remarks/> [System.Xml.Serialization.XmlTypeAttribute( Namespace="http://idoox.com/interface", IncludeInSchema=false)] public enum ItemChoiceType { /// <remarks/> id, /// <remarks/> setId, /// <remarks/> notFound, }
The .NET client program creates a WSO2 SOA Enablement Server Web service proxy, sets the client certificate to the proxy instance, invokes the GetSecureInfo() method, and displays the string that is returned.
Example 265. Using security in .NET
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. using System; using System.Net; namespace SecurityBasicClient { class Client { [STAThread] static void Main(string[] args) { JavaService ws = new JavaService(); ws.Url = "http://localhost:6060/secure/hello/dotNet/"; Console.Write("User:"); string strUser = Console.ReadLine(); Console.Write("Password:"); string strPassword = Console.ReadLine(); ICredentials credentials = new NetworkCredential(strUser, strPassword); try { ws.Credentials = credentials; Console.WriteLine(ws.GetSecureInfo()); } catch (Exception err) { Console.WriteLine(err.Message); } finally { Console.ReadLine(); } } } }
To build the .NET client execute the following command:
csc.exe /out:Client.exe /t:exe Client.cs dotNetToWaspSecureProxy.cs
The .NET client output is as follows:
Client.exe Secret Hello
In this section, we will dissect the process of invoking a secure .NET rpc-style service.
Example 266 shows the .NET service source file. The service is flagged as an RPC service using the [SoapRpcService] and defines a single GetSecureInfo() web method, which returns a string variable.
Example 266. Secure .NET Web Service Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. using System; <%@ WebService Language="C#" Class="SecureInfoService.Service" %> using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; namespace SecureInfoService { [WebService(Namespace="http://wso2.com/.NET/Security/")] [SoapRpcService] public class Service : System.Web.Services.WebService { [WebMethod] [SoapRpcMethod] public string GetSecureInfo () { return "Shh, this is top secret!"; } } }
To deploy this .NET Web service to Microsoft IIS, a virtual folder must be created in IIS through these steps:
Click the Windows Start button, point to Programs, select , and then click Internet Services Manager.
In the left pane, right-click Virtual Directory.
, select , and then clickIn the first screen of the Virtual Directory Creation Wizard, click Next and type the alias for the site: sslWaspToDotNet. Then click Next.
In the third screen, click Browse. Browse to %WASP_HOME%\src\example\applicationIntegration\dotNetIntegration\security\sslWaspToDotNet. Click Next.
In the fourth screen, click Next.
Click Finish to complete the wizard.
In the left pane, right-click sslWaspToDotNet, select , select Directory Security, and then click the Edit button in the Secure communications section.
Check Require secure channel (SSL) and Require 128-bit encryption. Click Require client certificates. Click the OK button on each of the previous dialogs.
Close the Internet Services Manager.
The .NET service is now available at https://localhost/sslWaspToDotNet/Service.asmx.
On the client side, the WSO2 SOA Enablement Server client authenticates the server using the user name and password and the SSL security provider. The client then looks up the service and invokes it. Example 267 shows these steps in the WSO2 SOA Enablement Server client source code.
Example 267. WSO2 SOA Enablement Server Client Source
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.dotNetIntegration.security. sslWaspToDotNet; import org.idoox.security.Credentials; import org.idoox.wasp.WaspSecurity; import org.systinet.wasp.webservice.ServiceClient; /** * Secure version of HelloWorld. */ public class Client { public static void main(String[] args) throws Exception { String USERNAME = "user"; String PASSWORD = "changeit"; String definitionURI = "https://localhost/sslWaspToDotNet/Service.asmx?WSDL"; // create a service client ServiceClient serviceClient = ServiceClient.create(); // acquire credentials Credentials credentials = WaspSecurity.acquireClientCredentials(USERNAME, PASSWORD, "SSL"); // associate credentials with the service client WaspSecurity.setCredentials(serviceClient, new Credentials[]{credentials}); // set wsdl location serviceClient.setWSDLLocation(definitionURI); // create a service proxy HelloWorld hello = (HelloWorld) serviceClient.createProxy(HelloWorld.class); // method call System.out.println(hello.GetSecureInfo()); } }
Before running the client, the certificate used by the IIS for the SSL handshake must be imported as trusted to the client KeyStore. The PStore tool handles importing the trusted certificate.
The WSDLs of secure services published by the IIS are protected by the same mechanism as their services. In this case, the lookup operation issued by a WSO2 SOA Enablement Server client without previous authentication fails. So an authentication operation must be performed before the lookup operation takes place. For details about client authentication, see the Client-Side Security in Security.
WSO2 SOA Enablement Server for Java's J2EE features enable the use of J2EE components, services and resources from other platforms, such as Microsoft .NET or Microsoft SOAP Toolkit. These integration features are accessible by SOAP messaging, so every SOAP client can access them. More information about WSO2 SOA Enablement Server J2EE integration is located in the chapter J2EE Integration.
To appreciate the power of WSO2 SOA Enablement Server for Java and J2EE integration, see the demo located in the WASP_HOME\demo\interop\msInterop\j2ee directory. In the demo, an Excel worksheet invokes an EJB service over SOAP under JTA user transactions.