[R] issues with SSOAP when wsdl has ComplexTypes

Hari Krishna Dara haridara at gmail.com
Sat Nov 7 01:17:21 CET 2009


On Thu, Nov 5, 2009 at 6:28 PM, Hari Krishna Dara <haridara at gmail.com> wrote:
> I recently started trying R and SSOAP and was able to successfully try a "hello
> world" service. I am now trying to get a more complicated interface to work with
> SSOAP and so far failed miserably at that and so need any help I can
> get from here.
>
> The service I am attaching is a prototype for a full service that would
> take information to identify a data source and a query to run and
> return a tabular
> data (a sql query result or a dataframe in R).
>
> Note: If you are impatient to read the long email, you may skip to the
> description of
> "Third attempt"
>
> First attempt: I have a ServiceInfo type as part of the request, that has two
> components, a clientID that is an int and a serviceInfoType that is an enum. I
> was able to create the ServiceInfo class object and was able to make the
> function call, but I was getting an error in the toSOAP().
>
>    > sinfo = c(clientId=1, serviceType='Engine')
>    > class(sinfo) <- def at classes$`SOAP/DataService`$ServiceInfo
>    > res = def at functions$simpleQuery(sinfo, 'select 1 as One')
>    Loading required package: bitops
>    Error in toSOAP(argValues[[i]], methodCall, type = typedef,
> literal = .literal) :
>      No code yet for the toSOAP method for any object and
> ClassDefinition pair with literal = FALSE
>
> Second attempt: I then flattened the ServiceInfo such that the clientId and
> sericeType are passed inline to bypass the above error. SSOAP went past that but
> complained about a missing elType (seems to not like the enum).
>
>    > res = def at functions$simpleQuery(1, 'Engine', 'select 1 as One')
>    Error in toSOAPArray(obj, con, type = type, literal = literal, ...) :
>      no slot of name "elType" for this object of class
> "RestrictedStringDefinition"
>
> Third attmept: To bypass the above error as well, I then changed serviceType to
> string. SSOAP then actually made a successful call, and the webservice returned
> a response. However, now SSOAP failed to deserialize it with the below error
>
>    > res = def at functions$simpleQuery(1, 'Engine', 'select 1 as One')
>    Error in as(from, "QueryResultRow") :
>      no method or default for coercing "XMLInternalElementNode" to
> "QueryResultRow"
>
> I have since then created a standalone version of the service that only takes
> the query (no clientId and serviceType) and attached the code. The service is
> written in python using ZSI, and there is ZSI client code in the comments that
> shows how to use it from a python client (which btw, works as expected). The
> code doesn't actually execute the query, it simply fills in dummy data into the
> result, so all that you need to try the sample is python 2.6 and ZSI
> (http://pywebsvcs.sourceforge.net/). The comment also has sample R client code
> which I am paste below:
>
>    library(SSOAP)
>    dataService <-
> processWSDL('C:/src/tmp/python/webserv/dataService/DataService.wsdl')
>    def = genSOAPClientInterface(def = dataService, verbose = TRUE)
>    res = def at functions$simpleQuery('select 1 as One')
>
> At this point, my priority is to get the deserialization of the response
> working, as I am able to workaround the first two issues in sending request. I
> would really appreciate if anyone can help me in solving this problem.
>
> Here is some more information on getting the python sample to work.
> - Save the wsdl and py file in the same directory.
> - After installing python 2.6 and ZSI, run the below commands:
>    $ wsdl2py --complexType --file DataService.wsdl
>    $ wsdl2dispatch --file DataService.wsdl
> - Run the below command to start the service:
>    $ python DataService.py
> - Start another python shell and run the below commands to see it in action:
>    $ python
>    >>> import sys
>    >>> from DataService_services import *
>    >>> loc = DataServiceServiceLocator()
>    >>> service = loc.getDataServicePortType(tracefile=sys.stdout)
>    >>> req = DataServiceQueryRequest()
>    >>> req.Query = "select 1 as One"
>    >>> res = service.simpleQuery(req)
>    >>> print "Field names: %s" % [field.StringValue for field in
>    ...    res.Result.ResultHeading.QueryFields]
>    >>> print "Rows:"
>    >>> for i in xrange(0, len(res.Result.ResultRows)):
>    >>>     print "Row %d: %s" % (i+1, [field.StringValue or
>    ...     field.LongValue or field.DoubleValue for field in
>    ...     res.Result.ResultRows[i].QueryFields])
>
> Please let me know if you need any more information on the problem or getting
> the python sample to work.
>
> Thank you,
> Hari
>

I have been trying some more variations. I also noticed that KEGG had
a working example that had a ComplexType involving arrays and so
reworked my schema to look simialar to that (that involves
soapenc:Array). Now my return type is directly an array (which
combines the header and rows) but this also didn't workout any better.
I then simplified further by removing the second level ComplexType,
ie., change QueryResultRow.queryFields to type "string" instead of a
ComplexType, and this got the call working. Ie., if I concatenate all
fields in a row as a single string, then SSOAP is able to deserialize
it. This of course is not what I want to do, so still looking for
help. I am attaching the new samples, one that works and the other
that doesn't (gives the below error):

Error in UseMethod("xmlValue") :
  no applicable method for 'xmlValue' applied to an object of class "NULL"

Is this a known limitation in SSOAP for handling ComplexTypes that are
more than 1 level deep? I am almost out of ideas and would soon look
into using JSON as an alternative, but that is not going to be my
preference.

Thank you,
Hari


More information about the R-help mailing list