WebService's SoapMarshaler not recocnizing xsi:type= specs?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
I'm not a Soap no-it-all, but I'm pretty sure the following XML source:

    <result>
        <done>true</done>
        <queryLocator xsi:nil="true"></queryLocator>
        <records xsi:type="sf:Contact">
            <sf:FirstName>Rose</sf:FirstName>
            <sf:LastName>Gonzalez</sf:LastName>
        </records>
        <records xsi:type="sf:Contact">
            <sf:FirstName>Sean</sf:FirstName>
            <sf:LastName>Forbes</sf:LastName>
        </records>
        <...>
        <size>20</size>
    </result>

Should return a collection of Contact instances rather than SObject
instances.  For some reason the Marshaler doesn't take
xsi:type="sf:Contact" and return instances of SForce:Contact (I used the
wizard and specified a namespace so I wouldn't have
class-naming-collisions).

I'd love to reduce this to an easy example that breaks but like I said,
I'm unsure how to do that at this point.  I'm debugging inside
WebServices.MarshalingContext trying to figure it out now.

--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

RE: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Kogan, Tamara
>
> Should return a collection of Contact instances rather than SObject
> instances.  For some reason the Marshaler doesn't take
> xsi:type="sf:Contact" and return instances of SForce:Contact (I used the
> wizard and specified a namespace so I wouldn't have
> class-naming-collisions).

The framework is using the smalltalkClass attribute from XML to object binding to create object instances
<object name="AuthenticationToken" smalltalkClass="AuthenticationToken">

> xsi:type inline type is used if the X2O binding defines mapping as "anyType" or the smalltalkClass attribute is an abstract class.

Tamara

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Jason Rogers-4
Thomas (et al),

I have tried many times to set up a workspace against Salesforce,
always ending in frustration.

Could you share with the list your steps once you have the kinks
worked out (or even before, and I will be happy to try to work out
kinks).

Thanks.

Jason

On 11/16/07, Kogan, Tamara <[hidden email]> wrote:

> >
> > Should return a collection of Contact instances rather than SObject
> > instances.  For some reason the Marshaler doesn't take
> > xsi:type="sf:Contact" and return instances of SForce:Contact (I used the
> > wizard and specified a namespace so I wouldn't have
> > class-naming-collisions).
>
> The framework is using the smalltalkClass attribute from XML to object binding to create object instances
> <object name="AuthenticationToken" smalltalkClass="AuthenticationToken">
>
> > xsi:type inline type is used if the X2O binding defines mapping as "anyType" or the smalltalkClass attribute is an abstract class.
>
>
> Tamara
>
>


--
Jason Rogers

"I am crucified with Christ: nevertheless I live;
yet not I, but Christ liveth in me: and the life
which I now live in the flesh I live by the faith of
the Son of God, who loved me, and gave
himself for me."
    Galatians 2:20

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
In reply to this post by Kogan, Tamara
    "xsi:type inline type is used if the X2O binding defines mapping as
    "anyType" or the smalltalkClass attribute is an abstract class."


Tamara, can you explain that another way?  It almost sounds like you're
saying I can get it to work if I do something different with the Wizard
or edit the WSDL or something like that....


Kogan, Tamara wrote:

>
> The framework is using the smalltalkClass attribute from XML to object binding to create object instances
> <object name="AuthenticationToken" smalltalkClass="AuthenticationToken">
>
>  
>> xsi:type inline type is used if the X2O binding defines mapping as "anyType" or the smalltalkClass attribute is an abstract class.
>>    
>
> Tamara
>
>
>
>  

--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
In reply to this post by Jason Rogers-4
Jason, with one small change to the class library (already discussed)
this is the workspace I've been able to get working.  I borrowed
liberally from the Java example
<http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_quickstart_steps.htm#step_4_walk_through_the_sample_code>

    client := SForce.SoapWsdlClient new.

    "Services invocation"
       
        arg1 := SForce.Login new
            username: ('[hidden email]');
            password: ('what did you expect?');
            yourself.
        [
            value := client login: arg1.
            loginResult := value first result.
        ]
        on: (ExceptionSet
            with: SForce.LoginFault
            with: SForce.UnexpectedErrorFault
            with: SForce.InvalidIdFault)
        do: [ :exception | Dialog warn: exception errorString ].

        client port address: loginResult serverUrl.

        ( client headerFor: #SessionHeader)
            value: ( SForce.SessionHeader new
                    sessionId: loginResult sessionId;
                    yourself).

            arg1 := SForce.DescribeGlobal new.
        [
            value := client describeGlobal: arg1.
            describeResult := value first result.
        ]
        on: SForce.UnexpectedErrorFault
        do: [ :exception | Dialog warn: exception errorString ].

        describeResult types do: [ :sobject |
            arg1 := SForce.DescribeSObject new sObjectType: sobject;
    yourself.
            [
                value := client describeSObject: arg1.
                describeResult := value first result.
                describeResult fields do: [ :field |
                    Transcript cr;
                        nextPutAll: describeResult name;
                        nextPut: $.;
                        nextPutAll: field name
                ]
            ]
            on: SForce.UnexpectedErrorFault
            do: [ :exception | Dialog warn: exception errorString ]
        ].

        qo := SForce.QueryOptions new.
        qo batchSize: 200.
        (client headerFor: #QueryOptions) value: qo.

        mru := SForce.MruHeader new.
        mru updateMru: false.
        (client headerFor: #MruHeader) value: mru.

        arg1 := SForce.Query new queryString: 'select FirstName,
    LastName from Contact'; yourself.
        [
            self halt.
            value := client query: arg1.
            queryResult := value first result.
            queryResult records do: [ :contact |
    "
    this is where I'm having problems.  The children inside 'records'
    aren't Contract objects as they need to be
    "
            ]

        ]
        on: SForce.UnexpectedErrorFault
        do: [ :exception | Dialog warn: exception errorString ].


--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
In reply to this post by Thomas Gagné-2
Jan, setting "Allow marshaling derived types in relations" in the
XMLObject Marshaling section of settings did the trick.  Of course, it
caused another error:

    Unhandled exception: No marshaler for: 'SoapHeaderStruct:
    {#MruHeader->SoapHeaderEntry ( mustUnderstand: true;  value:
    aSForce.MruHeader) #SessionHeader->SoapHeaderEntry ( mustUnderstand:
    true;  value: a SForce.SessionHeader) #QueryOptions
    ->SoapHeaderEntry ( mustUnderstand: true;  value: a
    SForce.QueryOptions)}'
    WebServices.WsdlBinding(WebServices.XMLObjectBinding)>>notifyNoMarshalerFor:text:
    WebServices.WsdlBinding(WebServices.XMLObjectBinding)>>notifyNoMarshalerFor:
    WebServices.SoapMarshalingManager(WebServices.XMLObjectMarshalingManager)>>notifyNoMarshalerFor:
    WebServices.MarshalingContext>>notifyNoMarshalerFor:
    WebServices.RelationMarshaler>>marshalDerivedValueFrom:
    WebServices.RelationMarshaler>>privateMarshalFrom:
    optimized [] in [] in
    WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
    XML.XPathChildNode(XML.XPathStep)>>marshalFrom:do:
    XML.XPathChildNode(XML.XPathStep)>>setNodeAndMarshalFrom:do:
    WebServices.XMLMarshalerProxy>>setNodeAndMarshalFrom:do:
    [] in WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
    WebServices.OneRelation>>marshalFrom:do:
    WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
    WebServices.MarshalingContext>>setNodeAndMarshal
    WebServices.RelationMarshaler>>marshalAspectFrom:implementation:
    optimized [] in WebServices.ObjectMarshaler>>marshalElement:from:

But hitting "proceed" from the debugger pop-up continues fine.  The WSDL
doesn't define a complex type for MruHeader, but interestingly this
message isn't raised while trying to read a message from Salesforce,
it's raised while /creating/ a message to SalesForce.

--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

RE: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Kogan, Tamara
Use the fix:

ObjectMarshaler>>acceptClass: theClass

        ^self aspectImplementation isStruct
                or: [self smalltalkClass notNil
                and: [ theClass == self smalltalkClass ]]


With this fix I got UHE
'UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService'

It should be more settings than that:
        ( client headerFor: #'QueryOptions')
                value: ( QueryOptions new
                                batchSize: 100;
                                yourself).

        ( client headerFor: #'SessionHeader')
                value: ( SessionHeader new
                                sessionId:'exgAzYjzlrgCW';
                                yourself).

        ( client headerFor: #'MruHeader')
                value: ( MruHeader new
                                updateMru: false;
                                yourself).
       
        arg1 := Smalltalk.Query new queryString: 'select FirstName,
    LastName from Contact'; yourself.

        [
                value := client query: arg1.

Tamara Kogan
Smalltalk development,
Cincom Systems

> -----Original Message-----
> From: Thomas Gagné [mailto:[hidden email]]
> Sent: Friday, November 16, 2007 2:01 PM
> To: [hidden email]
> Cc: vwnc
> Subject: Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?
>
> Jan, setting "Allow marshaling derived types in relations" in the
> XMLObject Marshaling section of settings did the trick.  Of course, it
> caused another error:
>
>     Unhandled exception: No marshaler for: 'SoapHeaderStruct:
>     {#MruHeader->SoapHeaderEntry ( mustUnderstand: true;  value:
>     aSForce.MruHeader) #SessionHeader->SoapHeaderEntry ( mustUnderstand:
>     true;  value: a SForce.SessionHeader) #QueryOptions
>     ->SoapHeaderEntry ( mustUnderstand: true;  value: a
>     SForce.QueryOptions)}'
>
> WebServices.WsdlBinding(WebServices.XMLObjectBinding)>>notifyNoMarshalerFo
> r:text:
>
> WebServices.WsdlBinding(WebServices.XMLObjectBinding)>>notifyNoMarshalerFo
> r:
>
> WebServices.SoapMarshalingManager(WebServices.XMLObjectMarshalingManager)>
> >notifyNoMarshalerFor:
>     WebServices.MarshalingContext>>notifyNoMarshalerFor:
>     WebServices.RelationMarshaler>>marshalDerivedValueFrom:
>     WebServices.RelationMarshaler>>privateMarshalFrom:
>     optimized [] in [] in
>     WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
>     XML.XPathChildNode(XML.XPathStep)>>marshalFrom:do:
>     XML.XPathChildNode(XML.XPathStep)>>setNodeAndMarshalFrom:do:
>     WebServices.XMLMarshalerProxy>>setNodeAndMarshalFrom:do:
>     [] in WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
>     WebServices.OneRelation>>marshalFrom:do:
>     WebServices.RelationMarshaler>>setNodeAndMarshalFrom:
>     WebServices.MarshalingContext>>setNodeAndMarshal
>     WebServices.RelationMarshaler>>marshalAspectFrom:implementation:
>     optimized [] in WebServices.ObjectMarshaler>>marshalElement:from:
>
> But hitting "proceed" from the debugger pop-up continues fine.  The WSDL
> doesn't define a complex type for MruHeader, but interestingly this
> message isn't raised while trying to read a message from Salesforce,
> it's raised while /creating/ a message to SalesForce.
>
> --
> Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
>       <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
Hmm.  With that fix I'm back to where I started -- with an SObject
instead of a Contact.

Kogan, Tamara wrote:

> Use the fix:
>
> ObjectMarshaler>>acceptClass: theClass
>
> ^self aspectImplementation isStruct
> or: [self smalltalkClass notNil
> and: [ theClass == self smalltalkClass ]]
>
>
> With this fix I got UHE
> 'UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService'
>
> It should be more settings than that:
> ( client headerFor: #'QueryOptions')
> value: ( QueryOptions new
> batchSize: 100;
> yourself).
>
> ( client headerFor: #'SessionHeader')
> value: ( SessionHeader new
> sessionId:'exgAzYjzlrgCW';
> yourself).
>
> ( client headerFor: #'MruHeader')
> value: ( MruHeader new
> updateMru: false;
> yourself).
>  
Those are set in my workspace, but of course I have another patch as well:

SoapClient

    executeRequest
        "In case of persistent transport client set to nil old values"
        response := nil.
        responseValue := nil.
    "
    request needs the SoapClient's headers - tgg
    "
        request setHeaderFrom: self header.

        "Execute request and set new response"
        response := self request executeWith: self transportClient.

        ^(self request isOneWay and: [ response isNil] )
            ifTrue: [nil]
            ifFalse: [ responseValue := response value ]

--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

RE: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Kogan, Tamara
The fix should not affect the #object aspect implementation. Try to recreate objects in a clean image with fixes or you can send me the debug stack but I'll be able to look at it next week.

Tamara Kogan
Smalltalk development,
Cincom Systems

> -----Original Message-----
> From: Thomas Gagné [mailto:[hidden email]]
> Sent: Saturday, November 17, 2007 2:55 PM
> To: vwnc
> Subject: Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?
>
> Hmm.  With that fix I'm back to where I started -- with an SObject
> instead of a Contact.
>
> Kogan, Tamara wrote:
> > Use the fix:
> >
> > ObjectMarshaler>>acceptClass: theClass
> >
> > ^self aspectImplementation isStruct
> > or: [self smalltalkClass notNil
> > and: [ theClass == self smalltalkClass ]]
> >
> >
> > With this fix I got UHE
> > 'UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from
> login must be set in the SforceService'
> >
> > It should be more settings than that:
> > ( client headerFor: #'QueryOptions')
> > value: ( QueryOptions new
> > batchSize: 100;
> > yourself).
> >
> > ( client headerFor: #'SessionHeader')
> > value: ( SessionHeader new
> > sessionId:'exgAzYjzlrgCW';
> > yourself).
> >
> > ( client headerFor: #'MruHeader')
> > value: ( MruHeader new
> > updateMru: false;
> > yourself).
> >
> Those are set in my workspace, but of course I have another patch as well:
>
> SoapClient
>
>     executeRequest
>         "In case of persistent transport client set to nil old values"
>         response := nil.
>         responseValue := nil.
>     "
>     request needs the SoapClient's headers - tgg
>     "
>         request setHeaderFrom: self header.
>
>         "Execute request and set new response"
>         response := self request executeWith: self transportClient.
>
>         ^(self request isOneWay and: [ response isNil] )
>             ifTrue: [nil]
>             ifFalse: [ responseValue := response value ]
>
> --
> Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
>       <http://gagne.homedns.org/~tgagne/> for more great reading.

Reply | Threaded
Open this post in threaded view
|

Re: WebService's SoapMarshaler not recocnizing xsi:type= specs?

Thomas Gagné-2
In reply to this post by Kogan, Tamara
Kogan, Tamara wrote:

> Use the fix:
>
> ObjectMarshaler>>acceptClass: theClass
>
> ^self aspectImplementation isStruct
> or: [self smalltalkClass notNil
> and: [ theClass == self smalltalkClass ]]
>
>
> With this fix I got UHE
> 'UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService'
>  
With the fix, I get that my first time, too.  For whatever reason,
running it a second time fixes that problem but in the end, still
returns an SObject rather than a Contact.

I tested that starting with an image with only the SOAP parcels loaded,
applied the patch above, imported "enterprises.wsdl," then ran the
workspace.

--
Visit <http://tggagne.blogspot.com/>,<http://gagne.homedns.org/> or
      <http://gagne.homedns.org/~tgagne/> for more great reading.