I don't know if we reached a conclusion on this discussion.

If we are agreed that the callback object is conceptually part of
the conversation state and should not be changed during a conversation
(because of unpredictable results in some async cases), then we could
go one step further and prevent it from being changed while it is
associated with an active converation.  This removes the concern of
unpredictability.  We can also ask the OASIS TC for a spec clarification
on how this is supposed to work.

  Simon

Simon Nash wrote:

See inline.

  Simon

Raymond Feng wrote:

Comments inline.

Thanks,
Raymond

----- Original Message ----- From: "Simon Nash" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Tuesday, September 11, 2007 7:47 AM
Subject: Re: WS-Addressing mapping (was Re: What is Message.set/getCallableReference used for?)


Thanks for pointing out this issue.  I think we're OK with just
using ConversationID as the correlator as long as we make the
following assumptions:

 1. The correlation from ConversationID to callback object is done
    on a per-reference basis.



Are you assuming for the lifecylce of a conversation, there is only one effective callback object for a given service reference?

 >
Yes.  This seems consistent with the following spec words: "...callback
messages go to the client and are then routed to the specific instance
that has been registered as the callback object".  See further comments
below on this.

Even so, we still need to do some correlations (using the callback endpoint URI as the key?) to relate a callback to the given service reference, right?

Logically yes, but I don't think any explicit correlation on endpoint
URI is needed.  I was expecting each callback endpoint to keep its own
correlation table that maps ConversationID to callback object.  (This
is probably just a particular implementation of what you are saying.)

 2. The callback goes to the callback object that is set into the
    reference at the time the callback is made, not at the time
    the forward call is made.

Consider the following code:

  myRef = componentContext.getServiceReference(convInterface, refName);
  myRef.setCallback(callback1);
  myRef.getService().startConversation();
  myRef.setCallback(callback2);
  myRef.getService().continueConversation();
  myRef.setCallback(callback3);


Are you saying if the myRef.setCallback() is called for multiple times, the effective callback object will override the previous one? If so and if startConversation() and contineConversation() are one-way async operations, the result is unpredictable.

Yes, I am saying that.  The situation won't arise unless someone changes
the callback object after making an async call.  If the callback object
were never set, then all callbacks would go to a single instance of the
client component.  It seems reasonable to think of the callback object
as a way of redirecting callbacks from this single instance to a different
single instance on the client side, rather than a way of redirecting
callbacks to multiple client-side instances on a per-call basis.

Another way to look at this is that the callback object instance becomes
part of the state of the conversation.  This seems consistent with the
requirement that a callback object that isn't a service reference can
only be used with a stateful callback.  If a different unique
correlation ID were used to locate the callback object, there would
be no need for the stateful callback limitation.

With the assumptions listed above, the callbacks from startConversation()
and continueConversation() would go to callback3 (the current value)
instead of callback1 and callback2 respectively (the values at the time
of the forward calls).  I don't see anything in the spec that says that
this is not correct.



Assuming both the forward call and callback are synchronous, if the callback happens in the startConversation() method of the target service, then it will go to callback1, right? In this case, the setCallback(callback2) hasn't even been called.

Yes, thanks for the clarification.  I realised just as I pushed Send that
I hadn't been clear that I was thinking of the async case where callbacks
arrived after all the code had been executed.

  Simon


Does this take care of the cases you had in mind?

  Simon

Raymond Feng wrote:

+1 on the proposal. There is one more thing to add.

For the case that the callback object is not a ServiceReference, we don't flow it in the Message, but we still need to correlate the callback to this object so that the callback can be routed to the right callback object. ConversationID alone is good enough, because we can use different callback objects in the same conversation. I suggest that we add a "CallbackObjectID" to reference parameter under the CallbackReference. The CallbackObjectID can be the system hash code of the callback object. The ConversationID + CallbackObjectID will be the key for the correlation.

Do you agree?

Thanks,
Raymond

----- Original Message ----- From: "Jean-Sebastien Delfino" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Monday, September 10, 2007 3:43 PM
Subject: Re: WS-Addressing mapping (was Re: What is Message.set/getCallableReference used for?)


Comments inline.

[snip]
Simon Nash wrote:

I agree that we need a conclusion. I believe the detailed proposal below supports all the SCA semantics and I'd like to propose that we go with it
for Tuscany 1.0.

Any comments, questions, agreement, or disagreement?

  Simon


I was initially thinking that the Callback EPR should be a separate header outside of the To EPR but the code snippet that you put together to simulate the SCA built-in callback (at the bottom of that email) convinced me that I was wrong about it :)

So I'm +1 with your proposal in [1]:

Request message
<wsa:To>
 <wsa:EndpointReference xmlns:wsa="..." xmlns:tuscany="...">
   <wsa:Address>...URI of the service being invoked...</wsa:Address>
   <wsa:ReferenceParameters>
     <tuscany:CallbackID>callback-A01</tuscany:CallbackID>
     <tuscany:ConversationID>conversation-006</tuscany:ConversationID>
     <tuscany:CallbackReference>
       <wsa:EndpointReference>
<wsa:Address>...URI of the service for the callback...</wsa:Address>
         <wsa:EndpointReference>
     </tuscany:CallbackReference>
     </wsa:ReferenceParameters>
  </wsa:EndpointReference>
</wsa:To>

Callback message:
<wsa:To>
 <wsa:EndpointReference xmlns:wsa="..." xmlns:tuscany="...">
<wsa:Address>...URI of the service for the callback...</wsa:Address>
   <wsa:ReferenceParameters>
     <tuscany:CallbackID>callback-A01</tuscany:CallbackID>
     <tuscany:ConversationID>conversation-006</tuscany:ConversationID>
   </wsa:ReferenceParameters>
 </wsa:EndpointReference>
</wsa:To>

In plain text:
- CallbackID flows as a reference parameter of the "To" EPR
- ConversationID flows as a reference parameter of the "To" EPR
- CallbackReference is a well formed EPR and flows as a reference parameter of the "To" EPR

I think that we should propose this mapping to the OASIS SCA Bindings workgroup. Different implementations of SCA should follow the same mapping if we want them to interoperate over Web Services for example.

[1] http://www.mail-archive.com/[email protected]/msg22923.html


[snip]


Yes, I'm proposing what I said in [1] with a <tuscany:CallbackReference> reference parameter under the wsa:To stateful EPR. Looking at this again, it could be slightly improved to eliminate the <wsa:EndpointReference>
and <wsa:Address> within <tuscany:CallbackReference>, giving:

<wsa:To>
   <wsa:EndpointReference xmlns:wsa="..." xmlns:tuscany="...">
<wsa:Address>...URI of the service being invoked...</wsa:Address>
      <wsa:ReferenceParameters>
          <tuscany:CallbackID>callback-A01</tuscany:CallbackID>

<tuscany:ConversationID>conversation-006</tuscany:ConversationID>
          <tuscany:CallbackReference>
             ...URI of the service for the callback...
          </tuscany:CallbackReference>
      </wsa:ReferenceParameters>
   </wsa:EndpointReference>
</wsa:To>

This requires the <tuscany:CallbackReference> to be "fluffed up" into a <wsa:To><wsa:EndpointReference> when the callback is sent, with the
<tuscany:CallbackID> and <tuscany:ConversationID> as its reference
parameters:

<wsa:To>
   <wsa:EndpointReference xmlns:wsa="..." xmlns:tuscany="...">
<wsa:Address>...URI of the service for the callback...</wsa:Address>
      <wsa:ReferenceParameters>
          <tuscany:CallbackID>callback-A01</tuscany:CallbackID>

<tuscany:ConversationID>conversation-006</tuscany:ConversationID>
      </wsa:ReferenceParameters>
   </wsa:EndpointReference>
</wsa:To>

  Simon




I'm not keen on doing that. I'd prefer to stick to your initial proposal which seems cleaner to me, using the same standard form to represent the CallbackReference EPR in the request message and the To EPR in the callback message.



 @Service(Client.class)
 class Client {
    ComponentContext componentContext;
    Writer writer;

    write(inputData) {
target = componentContext.getServiceReference(Writer.class, "writer");
       self = componentContext.createSelfReference();
       id = new UUID();
       target.setCallbackID(id);
       self.setCallbackID(id);
       target.setCallback(self);
       target.getService().asyncWrite(target, inputData);
    }

    written(myReference) {
       // data <myReference.getCallbackID()> has been written
    }
 }

 @Service(Writer.class)
 class Writer {

    @OneWay
    asyncWrite(myReference, inputData) {
       // actually write the data

       clientReference = myReference.getCallback();
       clientReference.getService().written(clientReference);
    }
 }




I'd suggest a small variation of this pseudo-code, to be more in line with the protocol that you proposed (the callbackID doesn't flow in the CallbackReference in the request message):

@Service(Client.class)
class Client {
   ComponentContext componentContext;
   Writer writer;

   write(inputData) {
target = componentContext.getServiceReference(Writer.class, "writer");
      self = componentContext.createSelfReference();
      id = new UUID();
      target.setCallbackID(id);
      target.setCallback(self);
      target.getService().asyncWrite(target, inputData);
   }

   written(myReference) {
      // data <myReference.getCallbackID()> has been written
   }
}

@Service(Writer.class)
class Writer {

   @OneWay
   asyncWrite(myReference, inputData) {
      // actually write the data

      clientReference = myReference.getCallback();
      clientReference.setCallbackID(myReference.getCallbackID());
      clientReference.getService().written(clientReference);
   }
}

--

Jean-Sebastien


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to