An example web service in C# - works in .NET/Xamarin/Mono on Windows, Mac and Linux.
When this document mentions SOAP (Simple Object Access Protocol) it is referring to the self documeting and highly interoperable SOAP Document/Literal Wrapped format and not an the deprecated - and maligned - SOAP RPC format, which is a different pragma.
I've finally got a new macbook at work. Looking for a GUI Soap client that can read a WSDL, generate sample request based on the WSDL and let me edit.
This is an example of a cross platform web service that provides SOAP Document/Literal Wrapped web service.
Web services generated on Mono all have complete automatically documentation with example usage exposed as web pages on the server along with interactive examples (where you can submit structured objects via an HTML form and view the responses) and of course service descriptions (WSDL files) and URL endpoints are generated for you. The code used to create services on Mono runs without modification on .NET (although services built for .NET may not run with out modification on Mono).
This example is in written in C#, using Mono/Xamarin Studio IDE (available for Windows, Mac and Linux). The services are self documenting and interoperate really with well with other languages (Java, C+, PHP, Ruby, JavaScript, etc). In languages like Java and PHP it works great with the built in SOAP client - on platforms that don't have a SOAP client you can use simple HTTP/REST calls.
It's cross platform and runs on Windows, Mac, Linux and other UNIX platforms. The class libraries used can be shared between desktop, server, mobile (iOS and Android) and console platforms.
You can also use JSON or simple XML with REST for these methods, which is great for simple services - although then you don't get the benifits of automatic server-to-client exception propogation (where any exception on the server can bubble the same exception to the client) or the full benifits of type safety. As with most things, it's very dependant on the use case at hand as to if you need that level of robustness in error handling and type checking in your API.
I've used C# and Xamarin/Mono to write and deploy services on Mac, Windows, Linux, BSD and Solaris at several jobs in the past - including while working at the BBC, AOL and Sky, which were all mixed platform environments. I've consumed these services from C#, C++, Java, JavaScript, PHP, Perl, C++ in xojo (formerly RealStudio) and other scripting languages.
Many if not most of the deployed .NET services I've seen in production have been pretty badly managled - even though it's quite straight forward to get it right, especially if you use Visual Studio or Mono Project (from Xamarin) to create them. I thought I'd get round to uploading an example it is to write a good service as a reference point.
I've included some examples of sane ways to handle returning complex objects, how to do input validation, how to create WSI compliant responses and some examples of how best to handle errors.
As I update this for 2017, SOAP Document/Literal Wrapped still remains best supported on C# - largely thanks to Microsoft, the first initial proponents of the format and of course of C#. Using C# with .NET or Mono generates clients that are highly interoperable with other platforms and languages. Remarkably, there still isn't anything that's quite comparible for building services (using XML or JSON) in any other language.
If you're doing cross platform development for web services - especially for robust or enterprise web service services - and you're not using C#/Mono for them you might be missing out. It might not seem an obvious choice if your stack is normally something like Java, Node.js, Ruby, PHP or even Go or Rust, but if your work revolves around building well defined, type safe web services with robust exchange of data - especially passing objects between systems - then it's strongly worth considering as it's a remarkable platform.
Both JSON API and JSON Schema can be combined to similarly define services and APIs that use JSON, although (sadly) they are not quite as complete in scope and there are currently no tools which create generate auto-documenting, robust services from code in the same manner (though there is software that does some of the work). There are several different client libaries which all work great, however soap server libraries require quite a bit more work to create a service.
In Java you can use the Java API for XML Web Services (JAX-WS) to create SOAP services. Other alternatives for Java include Apache CXF and Apache Axis2. Currently all of these (and simlar) options for Java have their own quirks and compatiblity isusues that cause interoperability problems when consuming them from different clients.
PHP's built in SoapClient works perfectly with services written in C#, you just pass the URL of the service that gets generated and you can work with the returned object as if it was a local class. The corresponding SoapServer method to create services is, unfortunately, not as sophisticated.
Thanks to the auto-docmentation, simple human-readable and restful nature, any language can consume the services easily, even if there is no native SOAP suport, just by treating it as REST/XML - although if there is a soap client for your platform it's much easier to consume.
Feedback via me@iaincollins.com or via Twitter via @iaincollins is welcome, as are pull requests.
This section shows how to create and run these types of clients:
When you run these client examples, they will access the MyHelloService
that you deployed in Creating a Simple Web Service and Client with JAX-RPC.
This example resides in the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dynamicproxy/
directory.
The client in the preceding section uses a static stub for the proxy. In contrast, the client example in this section calls a remote procedure through a dynamic proxy, a class that is created during runtime. Although the source code for the static stub client relies on an implementation-specific class, the code for the dynamic proxy client does not have this limitation.
The DynamicProxyHello
program constructs the dynamic proxy as follows:
Service helloService =
serviceFactory.createService(helloWsdlUrl,
new QName(nameSpaceUri, serviceName));
A Service
object is a factory for proxies. To create the Service
object (helloService
), the program calls the createService
method on another type of factory, a ServiceFactory
object.
The createService
method has two parameters: the URL of the WSDL file and a QName
object. At runtime, the client gets information about the service by looking up its WSDL. In this example, the URL of the WSDL file points to the WSDL that was deployed with MyHelloService
:
http://localhost:8080/hello-jaxrpc/hello?WSDL
A QName
object is a tuple that represents an XML qualified name. The tuple is composed of a namespace URI and the local part of the qualified name. In the QName
parameter of the createService
invocation, the local part is the service name, MyHelloService
.
myProxy
) with a type of the service endpoint interface (HelloIF
): dynamicproxy.HelloIF myProxy =
(dynamicproxy.HelloIF)helloService.getPort(
new QName(nameSpaceUri, portName),
dynamicproxy.HelloIF.class);
The helloService
object is a factory for dynamic proxies. To create myProxy
, the program calls the getPort
method of helloService
. This method has two parameters: a QName
object that specifies the port name and a java.lang.Class
object for the service endpoint interface (HelloIF
). The HelloIF
class is generated by wscompile
. The port name (HelloIFPort
) is specified by the WSDL file.
Here is the listing for the HelloClient.java
file, located in the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dynamicproxy/src/
directory:
Before performing the steps in this section, you must first create and deploy MyHelloService
as described in Creating a Simple Web Service and Client with JAX-RPC.
To build and package the client, go to the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dynamicproxy/
directory and type the following:
The preceding command runs these tasks:
The generate-interface
task runs wscompile
with the -import
option. The wscompile
command reads the MyHelloService.wsdl
file and generates the service endpoint interface class (HelloIF.class
). Although this wscompile
invocation also creates stubs, the dynamic proxy client does not use these stubs, which are required only by static stub clients.
The compile-client
task compiles the src/HelloClient.java
file.
The package-dynamic
task creates the dist/client.jar
file, which contains HelloIF.class
and HelloClient.class
.
To run the client, type the following:
The client should display the following line:
This example resides in the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dii/
directory.
With the dynamic invocation interface (DII), a client can call a remote procedure even if the signature of the remote procedure or the name of the service is unknown until runtime. In contrast to a static stub or dynamic proxy client, a DII client does not require runtime classes generated by wscompile
. However, as you'll see in the following section, the source code for a DII client is more complicated than the code for the other two types of clients.
This example is for advanced users who are familiar with WSDL documents. (See Further Information.)
The DIIHello
program performs these steps:
Service service =
factory.createService(new QName(qnameService));
To get a Service
object, the program invokes the createService
method of a ServiceFactory
object. The parameter of the createService
method is a QName
object that represents the name of the service, MyHelloService
. The WSDL file specifies this name as follows:
<service name='MyHelloService'>
Service
object, creates a Call
object:QName port = new QName(qnamePort);
Call call = service.createCall(port);
Just drag and drop them to finish your design quickly. Here are some examples. Interior design software 2d luxury house plan programs for mac. All symbols are editable and sharable with dynamic scale.
A Call
object supports the dynamic invocation of the remote procedures of a service. To get a Call
object, the program invokes the Service
object's createCall
method. The parameter of createCall
is a QName
object that represents the service endpoint interface, MyHelloServiceRPC
. In the WSDL file, the name of this interface is designated by the portType
element:
<portType name='HelloIF'>
Call
object:call.setTargetEndpointAddress(endpoint);
In the WSDL file, this address is specified by the <soap:address>
element.
SOAPACTION_USE_PROPERTY
SOAPACTION_URI_PROPERTY
ENCODING_STYLE_PROPERTY
To learn more about these properties, refer to the SOAP and WSDL documents listed in Further Information.
QName QNAME_TYPE_STRING = new QName(NS_XSD, 'string');
call.setReturnType(QNAME_TYPE_STRING);
call.setOperationName(new QName(BODY_NAMESPACE_VALUE,
'sayHello'));
call.addParameter('String_1', QNAME_TYPE_STRING,
ParameterMode.IN);
To specify the return type, the program invokes the setReturnType
method on the Call
object. The parameter of setReturnType
is a QName
object that represents an XML string type.
The program designates the method name by invoking the setOperationName
method with a QName
object that represents sayHello
.
To indicate the method parameter, the program invokes the addParameter
method on the Call
object. The addParameter
method has three arguments: a String
for the parameter name (String_1
), a QName
object for the XML type, and a ParameterMode
object to indicate the passing mode of the parameter (IN
).
String[] params = { 'Murphy' };
String result = (String)call.invoke(params);
The program assigns the parameter value (Murphy
) to a String
array (params
) and then executes the invoke
method with the String
array as an argument.
Here is the listing for the HelloClient.java
file, located in the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dii/src/
directory:
Before performing the steps in this section, you must first create and deploy MyHelloService
as described in Creating a Simple Web Service and Client with JAX-RPC.
To build and package the client, go to the <INSTALL>
/j2eetutorial14/examples/jaxrpc/dii/
directory and type the following:
This build
task compiles HelloClient
and packages it into the dist/client.jar
file. Unlike the previous client examples, the DII client does not require files generated by wscompile
.
To run the client, type this command:
The client should display this line:
Unlike the stand-alone clients in the preceding sections, the client in this section is an application client. Because it's a J2EE component, an application client can locate a local Web service by invoking the JNDI lookup
method.
Here is the listing for the HelloClient.java
file, located in the <INSTALL>
/j2eetutorial14/examples/jaxrpc/appclient/src/
directory:
Before performing the steps in this section, you must first create and deploy MyHelloService
as described in Creating a Simple Web Service and Client with JAX-RPC.
To build the client, go to the <INSTALL>
/j2eetutorial14
/examples/jaxrpc/appclient/
directory and type the following:
As with the static stub client, the preceding command compiles HelloClient.java
and runs wscompile
by invoking the generate-stubs
target.
Packaging this client is a two-step process:
To create the EAR file, follow these steps:
<INSTALL>
/j2eetutorial14
/examples/jaxrpc/appclient
. To start the New Application Client wizard, select FileNewApplication Client. The wizard displays the following dialog boxes.
HelloServiceApp
.HelloClient
.<INSTALL>
/j2eetutorial14/examples/jaxrpc/appclient
directory.appclient.HelloClient
. When it invokes the lookup
method, the HelloClient
refers to the Web service as follows:
You specify this reference as follows.
service/MyJAXRPCHello
.appclient.MyHelloService
.META-INF/wsdl/MyHelloService.wsdl
.MyHelloService
.mapping.xml.
To deploy the application client, follow these steps:
<INSTALL>
/j2eetutorial14/examples/jaxrpc/appclient
To run the client follow these steps:
<INSTALL>
/j2eetutorial14
/examples/jaxrpc/appclient/
directory.appclient -client HelloServiceAppClient.jar
http://localhost:8080/hello-jaxrpc/hello
The client should display this line:
Other chapters in this book also have JAX-RPC client examples: