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@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.

______________________________________________
R-help@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.

Reply via email to