Working towards a Java client to a SOAPpy server

106 views
Skip to first unread message

Jeff

unread,
Dec 12, 2007, 11:03:26 AM12/12/07
to SWAMP Project Users
I didn't know anything about SOAP, SOAPpy, or web services before
diving into swamp. It's ridiculously easy to do SOAP with python
thanks to SOAPpy. I've googled for plenty of hits on how to make a
python SOAP client to a Java server, but not anything the other way
around. Since it's what I need, I tried it myself.

Netbeans6 (and 5.5?) has some wonderful features for consuming web
services from WSDL files. I turned on SOAPpy debugging for the
swamp_client so I could see the SOAP messages coming and going. Using
those, I tried to reverse-engineer the swamp SOAP interface into a
WSDL file. I've only attempted the "newScriptedFlow" action, but I
got rather far. Here's what I have so far for svn revision 99 of the
swamp code. A lot of this was generated from Netbeans6 WSDL wizards.

<code>
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="SwampClone" targetNamespace="http://
j2ee.netbeans.org/wsdl/SwampClone"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://
j2ee.netbeans.org/wsdl/SwampClone" xmlns:plnk="http://docs.oasis-
open.org/wsbpel/2.0/plnktype" xmlns:soap="http://schemas.xmlsoap.org/
wsdl/soap/">
<types/>
<message name="newScriptedFlow">
<part name="v1" type="xsd:string"/>
</message>
<message name="newScriptedFlowResponse">
<part name="Result" type="xsd:int"/>
</message>
<portType name="SwampClonePortType">
<operation name="newScriptedFlow">
<input name="input1" message="tns:newScriptedFlow"/>
<output name="output1"
message="tns:newScriptedFlowResponse"/>
</operation>
</portType>
<binding name="SwampCloneBinding" type="tns:SwampClonePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"/>
<operation name="newScriptedFlow">
<soap:operation style="rpc" soapAction="newScriptedFlow"/>
<input name="input1">
<soap:body use="literal" namespace="http://
j2ee.netbeans.org/wsdl/SwampClone"/>
</input>
<output name="output1">
<soap:body use="literal" namespace="http://
j2ee.netbeans.org/wsdl/SwampClone"/>
</output>
</operation>
</binding>
<service name="service1">
<port name="port1" binding="tns:SwampCloneBinding">
<soap:address location="http://localhost:28080/SOAP"/>
</port>
</service>
<plnk:partnerLinkType name="SwampClone1">
<!-- A partner link type is automatically generated when a new
port type is added. Partner link types are used by BPEL processes.
In a BPEL process, a partner link represents the interaction between
the BPEL process and a partner service. Each partner link is
associated with a partner link type.
A partner link type characterizes the conversational relationship
between two services. The partner link type can have one or two
roles.-->
<plnk:role name="SwampClonePortTypeRole"
portType="tns:SwampClonePortType"/>
</plnk:partnerLinkType>
</definitions>
</code>

The URL that is used to access the service should be pretty obvious,
but note that it is tailored to my local swamp instance. When I try
to access swamp from Java, I can see swamp get to work on my request
from the swamp log, process it, and return a valid SOAP response.
Unfortunately, the response isn't formatted the way Java is expecting.

javax.xml.ws.WebServiceException: Unexpected response element
newScriptedFlowResponse
expected: {http://j2ee.netbeans.org/wsdl/
SwampClone}newScriptedFlowResponse

It's a namespace issue. I can't seem to change the WSDL file I
created without breaking Netbean's/Java's WSDL importer, so I'm
thinking I should dive into the swamp code to use some swampy
namespace where needed.

If anyone has an idea how to get this working, please share! Thanks!

Jeff

Daniel

unread,
Dec 12, 2007, 4:49:40 PM12/12/07
to SWAMP Project Users
A while back, I took a stab at trying to define a WSDL for the SWAMP
service, but I hadn't really stabilized the API and I also got
discouraged by the heaviness of WSDL composition tools. One never
needs to specify object typing in SOAPpy, which is consistent with the
Python typing philosophy, but this makes it less obvious in terms of
interoperating with other SOAP implementations, which seem quite
focused and dependent on strict typing. The service component of
SWAMP uses a SOAPpy version packaged with twisted.web, but people seem
to use the ZSI when they care about strict typing for SOAP in
python.

You might have a look at the ZSI documentation on
pywebsvcs.sourceforge.net . It's got a section on converting between
SOAP types and Python objects, which might be helpful. I don't know
about the namespace handling. Can you instruct the Java
implementation to be forgiving of namespace details?

-Daniel

Jeff

unread,
Dec 12, 2007, 5:34:04 PM12/12/07
to SWAMP Project Users
Fortunate or not, it turns out it has nothing to do with swamp but
rather a SOAPpy utility method used by twisted.web (which is used by
swamp.)
There was this poor message all by itself in cyberspace posted over a
year ago with the same problem.

http://twistedmatrix.com/pipermail/twisted-web/2006-November/003138.html

The bottom line is that inside SOAPpy there is a handy utility
function of sorts called buildSOAP. It takes keyword arguments, the
important ones for this error being
arg = ()
method = "someString"
namespace = "someNS"

In the case of SOAPProxy, it calls internally
buildSOAP(args = args, kw = kw, method = name, namespace = ns,
header = hd, methodattrs = ma, encoding = self.encoding,
config = self.config, noroot = self.noroot)
where all kwargs are defined as something. Inside the soap body:
-there is one tag for each arg, ex) <v1...>val</v1...>
-there is one tag/val pair for each keyword, ex) <key...>val</key...>
-if method is given, it is the first and only child of the soap body,
with args and kw nested within iti
-if namespace is given, it is attached to the first child of the soap
body IF AND ONLY IF method is also given

That last line is the key point. Namespace is ignored if there is no
method name string.

In the case of swamp I get lost. In swamp_soapinterface.py, there's a
"soapi" class that wraps the functions exposed via soap. I tried
overriding the _gotResult method of the SOAPPublisher in the
WrapperTemplate, but I kept getting errors. The newScriptedFlow
method would fire off running, but the client would always receive a
soap fault in response.

Since I likely don't understand enough of why swamp wraps it's soap
interface methods instead of inheriting from SOAPPublisher directly,
that's why I'm going to try next. Perhaps I won't get that nasty
exception...

On Dec 12, 8:03 am, Jeff <jeffrey.da...@gmail.com> wrote:

Daniel

unread,
Dec 13, 2007, 1:13:37 PM12/13/07
to SWAMP Project Users
The class that inherits from SOAPPublisher is built dynamically
according to configuration. Originally, the class was parse-time
defined, but this seemed like a better way of isolating the logic from
the SOAP publishing interface.

-Daniel

Jeff

unread,
Dec 13, 2007, 1:53:09 PM12/13/07
to SWAMP Project Users
The SOAPPublisher from the twisted.web.soap package was a rather
simple implementation of a twisted.web Resource - so I wrote my own
SOAPPublisher that is essentially the same thing as the original
except for how it handles namespaces in the buildSOAP call during the
response callback. I used this custom SOAPPublisher in swamp rather
than the original. All is well in python land. swamp never knows the
difference.

On the Java side, however, I've still got problems. This might be
outside the scope of this user forum, but I'll continue. The WSDL
that I defined previously still compiles fine when consumed as a web
service by Netbeans6. I no longer receive the error

javax.xml.ws.WebServiceException: Unexpected response element
newScriptedFlowResponse
expected: {http://j2ee.netbeans.org/wsdl/
SwampClone}newScriptedFlowResponse

since I changed how the response is generated by SOAPPublisher. Now I
get a NullPointerException, with a virtually non-existent stack trace.

java.lang.NullPointerException
at $Proxy22.newScriptedFlow(Unknown Source)
at swampservicecloneclient.Main.main(Main.java:34)

I'm about ready to throw up my hands. It shouldn't be this hard.
Isn't that what SOAP is for? Interoperability with web services?
The worst part is that the NPE is not within my Main method code, but
somewhere I can't see thanks to the "Unknown Source". I give up.
Reply all
Reply to author
Forward
0 new messages