[R] Qualified parameters in SOAP body using .SOAP

Olivier Cailloux mlsmg at ulb.ac.be
Thu Jun 25 01:43:45 CEST 2009


Hi Duncan,

Thanks for this useful answer. See below.

Duncan Temple Lang a écrit :
>
> Hi Olivier
>
> Olivier Cailloux wrote:
>> Hello,
>>
>> I am trying to reach a web service using the SOAP package. I 
>> succeeded calling the web service, but not sending parameters to it. 
>> After much research and tries, I think I found that the problem lies 
>> in the namespace including the parameters in the SOAP body.
>
> There's no doubt that the SSOAP package doesn't cover all possible cases
> from the SOAP specification. But before adding support for additional
> types of server, can you point me to where in the specification or
> in the research you did that indicates what the namespace should
> be for this situation. That would be helpful.
I must say I am not an expert in SOAP specs, but after more research I 
am now pretty much convinced that the body sent by the .SOAP call does 
not correctly match the provided WSDL, which itself is IMHO correct. 
FWIW the WSDL file is automatically generated by the jboss server when 
deploying my J2EE application on it.

The reasoning is as follows. The WSDL file does not include an 
elementFormDefault in the schema tag, and no elemenFormDefault defaults 
to "UNQUALIFIED". Thus, the targetNamespace attribute only applies to 
the global elements and not to the local ones. This is a legal way to 
define a schema, AFAIU. The other way is to specify elementFormDefault 
as QUALIFIED (or specifying a form attribute in each or some elements), 
to make the elements qualified. (By qualified here I mean defined in the 
same namespace as the schema.)
> Now, as for an easy solution to the problem....
> You can cause the writeSOAPBody() method to avoid defining
> a default namespace on the <greetMe> node in the body of the message.
> You do this by putting a name on the character vector giving the 
> namespaces, e.g.
>
>      xmlns = c(x = "http://web2.web")
>
> in the call.  So
>
> contentGreet <- .SOAP(server=smg8TestService, method="greetMe",
>                       arg0="Olivier", action="",
>                       xmlns=c(x = "http://web2.web/"),
>                       .convert=FALSE)
>
> works just fine.
Great. That solves the problem indeed and produce a SOAP body which 
respects, AFAIU, the specs. Including this example and explanation in 
the SSOAP user manual would be very helpful, because it took plenty of 
time for me to understand and solve this issue, and most likely other 
users will have that problem as the setup I described is the default 
J2EE WSDL generation mode. To make things worse, jboss says nothing 
about that element it does not use in the SOAP body received from R, it 
just silently ignores it when its namespace is incorrect. So the user 
has no clue about why the parameter does not reach the web service.

FYI, an other way to solve the problem for me was to include in the java 
code annotations like @WebParam(targetNamespace = "http://web2.web/") 
before each parameter to force the generated WSDL file to include 
qualified elements.

While we are there, something which could still be improved in SSOAP: in 
the provided example, I have to use .convert = FALSE apparently because 
of a problem at the end of the .SOAP function implementation, when 
dealing with .convert. I don't quite understand what it is all doing, 
but in my case all what it should do is
 > convertFromSOAP(SOAPResult(contentGreet$content, 
contentGreet$header), "string")
which provides the expected answer. Calling .SOAP with .convert = TRUE 
(the default) returns NULL and with .verbose = TRUE, produces:
 > contentGreet <- .SOAP(server=smg8TestService, method="greetMe", 
.soapArgs=list(name="Olivier"), action="", 
xmlns=c(web="http://web2.web/"), .verbose=TRUE)
Error in UseMethod("xmlValue") : no applicable method for "xmlValue"


Please note I have slightly changed the web service definition, you can 
now call it using
 > smg8TestService <- SOAPServer("smg8.ulb.ac.be", "/web2/TestService", 
8080)
 > contentGreet <- .SOAP(server=smg8TestService, method="greetMe", 
.soapArgs=list(name="Olivier"), action="", 
xmlns=c(web="http://web2.web/"), .convert=FALSE)
 > convertFromSOAP(SOAPResult(contentGreet$content, 
contentGreet$header), "string")

Anyway, what I was trying to do now works and I have to thank you for 
that SSOAP package. To give a general feedback, I'd say I found it a bit 
difficult to use and have struggled to make it work, as a beginner in 
web services and in R (hard to know if the error is in your client, the 
server, your service code, some configuration...) but I think it is only 
a matter of improving a few functionalities (more meaningful error 
messages would be great) and adding more user doc to make that package 
really enjoyable. (Please note I understand the open source spirit and I 
am not blaming your work or suggesting you have to do all this, I only 
make some hopefully constructive remarks after having discovered and 
used this package.) Also I must say that being a beginner in both web 
services and R language probably accounted for the most part of the 
difficulties.
Olivier
>
>
>  D.
>
>
>
>>
>> In short, my question is: how can I send unqualified parameters in 
>> the SOAP body of a call produced through the SOAP package? Details of 
>> what I try to do follow.
>>
>> The SOAP package sends this soap envelope to my test web service 
>> (wsdl here [http://smg8.ulb.ac.be:8080/web2?wsdl]).
>> <SOAP-ENV:Envelope 
>> xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
>> xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
>> xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
>> SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
>>  <SOAP-ENV:Body>
>>    <greetMe xmlns="http://web2.web/">
>>      <arg0 xsi:type="xsd:string">Olivier</arg0>
>>    </greetMe>
>>  </SOAP-ENV:Body>
>> </SOAP-ENV:Envelope>
>>
>> The R commands used are:
>> library("SSOAP")
>> smg8TestService <- SOAPServer("smg8.ulb.ac.be", "/web2/TestService", 
>> 8080)
>> contentGreet <- .SOAP(server=smg8TestService, method="greetMe", 
>> arg0="Olivier", action="", xmlns="http://web2.web/", .convert=FALSE)
>>
>> But, AFAIU, the arg0 tag should NOT be qualified, according to the 
>> WSDL. Hence, my web service implementation never receives the 
>> "Olivier" argument and rather receives "null" as the string parameter.
>>
>> When calling the web service using an other client (eclipse Web 
>> services explorer), I see it generates the following body:
>> <soapenv:Envelope 
>> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
>> xmlns:q0="http://web2.web/" 
>> xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
>>  <soapenv:Body>
>>    <q0:greetMe>
>>      <arg0>Olivier-from-eclipse</arg0>
>>    </q0:greetMe>
>>  </soapenv:Body>
>> </soapenv:Envelope>
>>
>> Thus with the "arg0" tag being unqualified (i.e. not in the 
>> "http://web2.web/" namespace). And that works: my web service 
>> implementation indeed receives the "Olivier-from-eclipse" parameter 
>> as string.
>>
>> Can anyone confirm that my understanding of what happens and why my 
>> web service implementation, when called by the R client, does not see 
>> the parameters, seems correct?
>>
>> If it seems correct, then how can I send unqualified parameters in 
>> the SOAP body using the SOAP package? Thanks for any help!
>> Olivier
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide 
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.




More information about the R-help mailing list