An alternative and excellent source of information when you are having problems
is the Apache soap-user mailing list searchable archive. If your problem pertains to Apache SOAP for Java
then odds are someone has had the same problem as you and there is a solution in the archive.
General Concepts
What is SOAP?
SOAP is an XML-based messaging protocol. It defines a set of rules for structuring
messages that can be used for simple one-way messaging but is particularly useful for
performing RPC-style (Remote Procedure Call) request-response dialogues. It is not
tied to any particular transport protocol though HTTP is popular. Nor is it tied to
any particular operating system or programming language so theoretically the clients
and servers in these dialogues can be running on any platform and written in any
language as long as they can formulate and understand SOAP messages. As such it is
an important building block for developing distributed applications that exploit
functionality published as services over an intranet or the internet.
You can Read more...
What are Web Services?
A Web Service is a method that is callable remotely across a network
(such as a corporate intranet or the internet itself). Such web services
differ from traditional content-based internet services in that Content-Based
Services serve up web pages (whether static or dynamically generated) for
human consumption whereas Web Services serve up data for computers.
Read more...
What is the Service Web?
The entirety of web services available on the internet as a whole is termed
the Service Web.
Read more...
What do SOAP Messages/Dialogues look like?
Refer to this SOAP Dialogue to view an
example SOAP request message and its respective response message.
Read More...
What is the difference between a fault and exception in Apache SOAP?
[Nicholas Quaine, 19 December 2000]
The difference lies in where the error occurs - on the client side (during the
generation of the soap request or the unmarshalling the response) - or on the
server side (when unmarshalling the request, processing the message or
marshalling the response). The client side raises an exception whereas the server
side sends a SOAP response to the client indicating an error occured on the server side
(ie. you get a SOAP fault).
For example, sending a SOAP encoded request for a method that does not exist results in a
SOAP fault whereas if the server sends a response with a field that does not exist in a
client side class a SOAP exception will be raised.
If you think about it it makes a lot of sense, as the server is the only entity
that can realise the existence of server side errors but cannot raise exceptions
client side, so instead sends a SOAP encoded message reporting the error. You
can of course code into your client side to raise an exception in the case where
you receive a server side fault. Here is the code (where you have pre-defined
SoapClientException to contain 2 strings - the fault code and the fault string
description):
//setup the call
Call call = new Call();
call.setSOAPMappingRegistry(mySmr);
call.setTargetObjectURI(myServiceName);
call.setMethodName(myMethodName);
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
call.setParams(myParams);
//invoke the call
Response resp = call.invoke(new URL(myServletURLName), "");
if (resp.generatedFault())
throw new SoapClientException(
resp.getFault().getFaultCode(),
resp.getFault().getFaultString() );
Server-Side Setup
What software elements must be assembled to build a SOAP Server?
You will need an Appserver (such as Tomcat), a SOAP package (such as Apache SOAP for Java) and
your service methods. This Server-Side System Element
Diagram shows how they are assembled.
Read More...
How do I setup an Apache SOAP Server?
Please refer to the Server-Side Tutorial.
How can I setup initialization code for a service (ie. code
that runs once only to prep a database connection for example)?
[Nicholas Quaine, 26 March 2001]
One way to achieve this is to install another servlet which runs at your
servlet engine startup time.
This means that all initialization gets done at startup so you trap any errors
before your services get called and the first client to call the soap service is
not penalized in the case where your startup code is heavy (this can be the case
if you need to do a database login for example).Taking tomcat as an example in
the $TOMCAT_HOME/webapps/soap/WEB-INF directory
you will see web.xml which will already contain your soap rpcrouter servlet -
just add another servlet which will call a class that runs your initialization
code. Ensure that the <load-on-startup> specifies "1" for true. Note that you
can also specifiy parameters to pass to your initialization class so you do not
have to hardcode anything (like database names for example). Example web.xml
file is below.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
<servlet>
<servlet-name>
rpcrouter
</servlet-name>
<servlet-class>
org.apache.soap.server.http.RPCRouterServlet
</servlet-class>
<init-param>
<param-name>ServicesStore</param-name>
<param-value>DeployedServices.ds</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>
myStartupServlet
</servlet-name>
<servlet-class>
com.mycompany.myproject.mypackagename.MyInitializationCodeClass
</servlet-class>
<init-param>
<param-name>-X</param-name>
<param-value>myStartupParameterValue1</param-value>
<param-name>-Y</param-name>
<param-value>myStartupParameterValue2</param-value>
<param-name>-Z</param-name>
<param-value>myStartupParameterValue3</param-value>
</init-param>
<load-on-startup>
1
</load-on-startup>
</servlet>
</web-app>
My SOAP Service needs to make external connections to
other sites but it is behind a proxy server. How do I configure this?
[Francis Ho, 29 September 2001]
Note: See also the FAQ answer on setting up a client behind a proxy
below.
Suppose your proxy server is called "proxy.foo.com" and it is on port 9999.
There are a couple of ways of configuring Apache to use a proxy. Solution A1, using
the JVM capabilities to deal with proxies:
System.getProperties().put("proxySet","true");
System.getProperties().put("proxyHost","proxy.foo.com");
System.getProperties().put("proxyPort","9999");
Solution A2, for socks:
System.getProperties().put("socksProxyHost","socks.foo.com");
System.getProperties().put("socksProxyPort","1080");
Solution B1 (similar to solution A, except that you are telling TOMCAT to
the proxying via the variable TOMCAT_OPTS), for HTTP proxies:
set TOMCAT_OPTS="-DproxyHost=proxy.foo.com -DproxyPort=9999"
Solution B2, for socks:
set TOMCAT_OPTS="-DsocksProxyHost=socks.foo.com -DsocksProxyPort=1080"
Client-Side Setup
What software elements must be assembled to build a SOAP Client?
You will need a SOAP package and your client code. This
Client-Side System Element Diagram shows how they interact.
Read More...
How do I write a SOAP Client using Apache SOAP for Java?
Please refer to the relevant Client-Side Tutorial.
How do I write a SOAP Client using Perl?
Please refer to the relevant Client-Side Tutorial.
How do I write a SOAP Client using the Microsoft SOAP Toolkit?
Please refer to the relevant Client-Side Tutorial.
I upgraded from Microsoft SOAP version 2.0 beta 1 to beta 2 (or later)
and my client no longer works. What could be the problem?
[Nicholas Quaine, 03 August 2001]
In beta 2 and later you should use HttpConnector rather than SoapConnector as your Connector.
Where you have the following in the beta 1 client:
Dim Connector As SoapConnector
Set Connector = New WinInetConnector
You should have the following in the beta 2 client:
Dim Connector As SoapConnector
Set Connector = New HttpConnector
I want to write a SOAP Client using Apache SOAP for Java
but am behind a proxyserver. How can I make the SOAP call? And what do I do if the proxy
requires authentication?
[Francis Ho, 29 September 2001]
For SOAP clients, you can tell the soap connection object to use a proxy
host and port. You can then set your call object to use this connection.
Suppose your proxy server is called "proxy.foo.com" and it is on port 9999.
Here is a snippet of code to do this:
1. SOAPHTTPConnection conn = new SOAPHTTPConnection();
2. conn.setProxyHost("proxy.foo.com"); // specifying the proxy server
3. conn.setProxyPort(9999); // specifying the port used by the proxy
4. Call call = new Call(); // getting a new call object
5. call.setSOAPTransport(conn); // use the proxy
If the proxy requires authentication use the code above but add the
following lines:
3.1. conn.setProxyUserName("my proxy id");
3.2. conn.setProxyPassword("my secret password");
Tools
What tools are available for debugging my services?
[Nicholas Quaine, 03 August 2001]
If you run your appserver within an IDE you can put breakpoints in the service code
(refer to Section 4 of Server-Side SOAP
for more detail). You can do a similar trick for the client side code. One very useful tool
is a TCP-IP tunnel that you can put between the client and the server to monitor
the SOAP dialogues. One is the TcpTunnelGUI that comes with
Apache SOAP for Java.
Another is the Trace Utility that comes with the
Microsoft SOAP Toolkit.
Interoperability
I am trying to get Microsoft SOAP version 2.0 beta 1
to talk to Apache 2.1 and am having schema problems. The request message
doesn't include type information. What is the solution?
[Nicholas Quaine, 26 March 2001]
If using the high level API there is a trick that you can employ on the apache
side so that it can handle the lack of type info supplied by ms. It is explained
here
(you basically need extra entries in your deployment descriptor).
You will need ms soap toolkit 2.0 beta 2 or later (as beta 1 cannot handle the";charset=utf-8"
in the header returned by apache).
If using the low level API then you can add the type information to the envelope
yourself here is an example (with a single input parameter, type String) ...
Private Const URL = "http://myserver:8080/soap/servlet/rpcrouter"
Private Const ENC = "http://schemas.xmlsoap.org/soap/encoding/"
Private Const XSI = "http://www.w3.org/1999/XMLSchema-instance"
Private Const XSD = "http://www.w3.org/1999/XMLSchema"
Private Sub runMyMethod(ByVal imntType As String)
Dim Connector As SoapConnector
Dim Serializer As SoapSerializer
Dim Reader As SoapReader
Set Connector = New HttpConnector
Set Serializer = New SoapSerializer
Set Reader = New SoapReader
URI = "urn:myServices"
Method = "myMethod"
Connector.Property("EndPointURL") = URL
Call Connector.Connect(Nothing)
Connector.Property("SoapAction") = URI & "#" & Method
Call Connector.BeginMessage(Nothing)
Serializer.Init Connector.InputStream
Serializer.startEnvelope , ENC
Serializer.SoapNamespace "xsi", XSI
Serializer.SoapNamespace "SOAP-ENC", ENC
Serializer.SoapNamespace "xsd", XSD
Serializer.startBody
Serializer.startElement Method, URI, , "method"
Serializer.startElement "ns1"
Serializer.SoapAttribute "type", , "xsd:string", "xsi"
Serializer.writeString "myInputParameterValue"
Serializer.endElement
Serializer.endElement
Serializer.endBody
Serializer.endEnvelope
Connector.EndMessage
Reader.Load Connector.OutputStream
If Not Reader.Fault Is Nothing Then
MsgBox Reader.faultstring.Text, vbExclamation
Else
'Response is in Reader.DOM - just parse it
End If
End Sub
I am trying to get a Microsoft Client talk to Apache but it
seems to require a WSDL file on the server. Is this the case even if I am running
Apache on the server? None of the Apache examples seem to require this file
(or the WSML file). If I want a Microsoft soap client to talk to an Apache
soap server, do I *have* to have these files, or is there a way around it?
[Nicholas Quaine, 13 March 2001]
Apache server side does not require or use a WSDL file. You only need a wsdl file
if you want to use the high level API of the MS Soap Toolkit on the client side.
The WSDL file will then serve as a method descriptor so that the soap toolkit
can encode your requests. If you use the low level API then you can call services on
apache or any other soap service without any WSDL file. There are examples in the microsoft
toolkit help on the low level API. A typical client looks something like the below.
Dim Serializer As SoapSerializer
Dim Reader As SoapReader
Dim ResultElm As IXMLDOMElement
Dim FaultElm As IXMLDOMElement
Dim Connector As SoapConnector
Set Connector = New HttpConnector
Connector.Property("EndPointURL") = END_POINT_URL
Connector.Connect Nothing
Connector.Property("SoapAction") = "uri:" & Method
Connector.BeginMessage Nothing
Set Serializer = New SoapSerializer
Serializer.Init Connector.InputStream
Serializer.startEnvelope
Serializer.startBody
Serializer.startElement Method, CALC_NS, , "m"
Serializer.startElement "A"
Serializer.writeString CStr(A)
Serializer.endElement
Serializer.startElement "B"
Serializer.writeString CStr(B)
Serializer.endElement
Serializer.endElement
Serializer.endBody
Serializer.endEnvelope
Connector.EndMessage
Set Reader = New SoapReader
Reader.Load Connector.OutputStream
If Not Reader.Fault Is Nothing Then
MsgBox Reader.faultstring.text, vbExclamation
Else
Execute = CDbl(Reader.RPCResult.text)
End If
Copyright © 2001-2007 Nicholas Quaine. All rights reserved.