RE: [sca-j] Java Callback Simplification Proposal

From
Michael Rowley <>
Date
2008-02-13T14:58:35+00:00
ID
Thread
RE: [sca-j] Java Callback Simplification Proposal
Mike,

 

I’m glad you liked 3 of the 4
proposed simplifications.   Regarding the one you didn’t like:

 

The proposal:

3. Making ServiceReference.setCallbackID(Object id)
illegal and  

ServiceReference.getCallbackID() (assuming #2)
return null for  

conversational interactions.

 

Then part of the rationale, and your
response to it, were:

...conversations by nature correlate  

invocations between a client and provider
instance. If finer-grained  

correlation is needed such as between multiple
invocations in the  

same conversation, correlation data can be
included as part of the  

service operation data (e.g. “line item
number” can be passed as a  

parameter in the example above).

<mje>THIS is where I hear the baby screaming
as it flies out with the bathwater. 

 

<MR>I don’t know... Claiming we are baby-killers seems a
bit severe doesn’t it :-) </MR>

IF you really believe
that, then there is no need for a callback ID ever.  All you

do is use correlation data
in the messages themselves.  I suggested this to 

Michael
 Rowley not so long ago, with the model of BPEL
correlation in mind.  He 

was of the opinion that the
BPEL correlation approach was a failure and not 

to be used as a model for
SCA. 

There is a good argument to
be made for a system managed correlation 

mechanism in that it
simplifies the life of the programmer.  Forcing the use of

correlation data in the
message may well have the consequence of distorting 

the form of the messages,
since they now *HAVE* to contain data fields that 

are "uniquely
identifying" - and this must be done for all callback messages.

</mje>

 

<MR>Actually my point on BPEL
correlation is a little more subtle.  Having to use correlation to get to the
right process instance is indeed too much of a pain.  The system should be able
to do that.  However, when you have a complex process and you need to get to
the right place within that process, then correlation is OK, and in fact the
SCA BPEL spec makes it clear that BPEL correlations can and should continue to
be used for this.  Because this is a less-common complex case, it is OK to
require some complication in the solution.

 

The situation is analogous for Java.  The infrastructure
should be able to route to the right client instance, based on the conversation
that is taking place.  If you need finer-grained correlation, that is up to
you.

 

Also, it would be difficult or impossible
for the system to make any useful guarantees about which callback ID will be
received for a conversational interaction.  Imagine this case (pseudocode):

 

{

  setCallbackID(“1”)

  callService() 

  setCallbackID(“2”)

  callService()

}

 

receiveCallback() {

getCallbackID(); 
-- what does this return?

}

 

When multiple callback IDs are set within
a single conversation, there is nothing to guarantee that the service provider
will keep track of all of the outstanding callback IDs (“1” and “2”
in this case) and use the most appropriate one when it is invoking a callback. 
Creating such an ability to automatically maintain a set of outstanding
callback IDs would be too complex for the value it would provide.

 

Michael

 

From: Mike
Edwards [mailto:] 

Sent: Wednesday, February 13, 2008
5:24 AM

To: OASIS Java

Subject: Re: [sca-j] Java Callback
Simplification Proposal

 

Jim, 

Thanks
for this detailed proposal. 

I've
got a few concerns, that I can summarize simply as "the baby being thrown
out with the bathwater" 

-
ie some capabilities that are actually quite important seem to get chopped in
the name of simplicity. 

I'm
left feeling that callbacks in particular are no longer of any use once the
proposals are accepted. 

Let
me try to express what I see as the problems in inline comments as <mje>...</mje>

Yours,  Mike.

Strategist - Emerging Technologies, SCA & SDO.

Co Chair OASIS SCA Assembly TC.

IBM Hursley
Park, Mail Point 146, Winchester, SO21
  2JN, Great Britain.

Phone & FAX: +44-1962-818014    Mobile: +44-7802-467431  

Email:   

 

  
  
Jim Marino <> 

  
12/02/2008 18:23 

  
  
  
   

    
    
To

    
    
    
OASIS Java <>
    

    
   

   

    
    
cc

    
    
    
 

    
   

   

    
    
Subject

    
    
    
[sca-j] Java Callback Simplification Proposal

    
   

  
  
 

  
   

    
    
 

    
    
    
 

    
   

  
  

  
 

All,

Bellow is a proposal from BEA to simplify callback
mechanisms in the  

Java C&I specifications. I will work on the
appropriate steps of  

getting this into a JIRA so that it can be
tracked.

Thanks,

Jim

This proposal aims to simplify using asynchronous
communication in   

the SCA Java programming model by:

1. Eliminating callback objects.

   - Removing
ServiceReference.get/setCallback() 

<mje>So this implies
the client MUST implement the callback I/F</mje> 

2. Removing the ability for service providers to
get callback IDs.

   - Moving CallableReference
getCallbackID() to ServiceReference) 

<mje>.+1 </mje>

<mje>There is one
interesting argument to follow from this.  It is possible to 

take the view that
callbackID is only of interest to the client, while conversationID

is only really of use to the
provider.  Each is being used to pick out state of 

some kind, but at opposite
ends of the communication. So perhaps we can 

eliminate the client having
access to the conversation ID? 

It would be nice to coalesce
the 2 IDs,  The problem is that they have completely 

different lifecycles.  The
conversationID has some fixed span dictated by the 

form of the forward call
interface, with specific starting and ending operations. 

The callback ID has an indeterminate
span, always starting with one forward 

call, but with an
undetermined number and type of callback operations 

being included in its span.
Logically it needs to change for each subsequent 

forward call.

I'm now really heading off
into the weeds, but it occurs to me that there is a 

relationship of the callback
ID to the concept of "Future" that is used in the Java

concurrency packages.  There,
the Future represents the asychronous operation 

that is taking place, and
can be used to feed back results. The Future is handed 

back to the
"client" application on the invocation of the forward
"service" invocation. 

Today, Futures only handle
one-shot pieces of asychronous work, with a single 

"response"
message.  However, you could conceive of stretching this, to permit

something you might call a
"CallbackFuture" - which would represent an asynchronous

process with a continuing
life and an arbitrary number of "response" messages.

The nasty thing about this
is that with our current callback design there is no 

obvious end to the life of a
CallbackFuture - in other words, the callback interface 

does not define the
equivalent of an "endsConversation" which indicates completion

of the work of the
asynchronous service.  Today, the "end" of the callbacks must

be defined in metadata
outside the interface.  Perhaps we need to fix that, 

but it will not be
easy.</mje> 

3. Saying callback IDs are irrelevant in
conversations.

   - Making
ServiceReference.setCallbackID(Object id) illegal and

     ServiceReference.getCallbackID()
(assuming #2) return null for

     conversational interactions.

<mje>Why does having a
conversation enable this to be done? 

The callback ID I thought
allowed a client to mark a service invocation in 

a way that callbacks made to
the client carried the same ID and that 

this enables the client to
establish which original request caused a 

given response.  

Conversation ID does not do
this at all, unless I am mistaken, since 

while callback ID can change
from one invocation to the next, conversation ID 

stays the same for the whole
of a conversation.  Thus conversation ID is 

useless for distinguishing
one callback from another.</mje> 

4. Removing the distinction between stateless and
conversational

   callback interfaces.

    - Removing the ability to specify
conversational on callback

      Interfaces.

<mje>+1</mje>

By simplification, we mean as a primarily reducing
the number of   

concepts and APIs a developer must understand to
program  

asynchronous  services. This will entail some
reduction in  

capability. However,  this reduction, we
argue, affects edge-cases  

that can be accommodated through alternative
techniques. A secondary  

aspect of simplification concerns implementation.
By removing the  

requirement for runtimes to provide infrastructure
for  handling edge  

cases that can be accommodated through relatively
simple application  

programming techniques,implementing callback
capabilities becomes  

fairly straightforward. 

<mje>Unfortunately, unless
I'm mistaken, some rather central use cases have been 

trashed too.</mje>

[RATIONAL]

The rational for proposed items is dealt with
individually in this  

section.

1. ServiceReference.setCallback(Object object) and
 

ServiceReference.getCallback()

------------------------------------------------------------------------

---------------------------------------------

<mje>+1</mje>

This API exists as a mechanism to route callbacks
to instances other  

than an instance of the client component making a
forward invocation.  

This provides two capabilities.  Clients do
not have to implement a  

callback interface. The API also allows clients to
instruct the  

runtime to perform callback dispatching for
stateless interactions  

that execute concurrently. A common example of
this is inventory  

check. A client component needs to perform an
inventory check for  

multiple line items. As an efficiency, it written
to invoke the same

inventory service using a non-blocking call
multiple times. For each  

invocation, it wishes to dispatch the associated
callback to a  

different handler instance it creates.  For
example:

ServiceReference<InventoryService>
serviceReference = ..

for (LineItem item: purchaseOrder.getLineItems())
{

    CallbackService handler = new
CallbackServiceImpl();

   
serviceReference.setCallback(handler)

   
serviceReference.getService().checkInventory(item);

}

This can be done using the
CallableReference.getCallbackID():

// code that conducts the forward invoke:

ServiceReference<InventoryService>
serviceReference = ..

for (LineItem item: purchaseOrder.getLineItems())
{

    String id = // generate or assign
the callback ID

    // store the callback id and
whatever information the callback  

needs

    cache.put(id, handler);

    serviceReference.getService().checkInventory(item);

}

Callback processing can either be done directly by
a component  

implementation instance or delegated to
CallbackServiceImpl as shown  

below:

// code in the same class that handles the
callback:

public void onCallback(InventoryStatus status) {

    String id =
requestContext.getServiceReference().getCallbackID();

    CallbackInfo info = .. // retrieve
the stored callback

information by using the callback id

    CallbackService handler = new
CallbackServiceImpl(info);

    handler.onCallback(status);

}

Some advantages to eliminating get/set/Callback()
are:

a. Reduces the number of concepts and APIs a
developer will be  

presented with without affecting common
functionality. In other  

words, this API is primarily used for edge-cases
and removing it  

simplifies the common case.

b. Application migrations and versioning are
easier using the   

alternative approach. By using an object instance,
runtime  

implementations would be responsible for handling
class versioning

for in-process interactions. By avoiding
serialization and the use of  

a specific classes, and instead storing callback
data,  

CallbackServiceImpl can be versioned and
substituted for callbacks  

that have not yet occurred.

c. Runtime performance characteristics are likely
to improve. For  

cases where the client is stateless, routing to
the specific instance  

set through setCallback() requires that the
callback be routed to the  

specific JVM where the instance is hosted.
Eliminating routing to a  

particular instance allows the callback to
potentially be sent to any  

JVM where the client component is hosted.

d. Eliminates the need for runtime implementations
to manage garbage  

collection of callback objects. For example, if a
callback is never  

made, the runtime at some point will need to
remove the object from  

storage or memory.

2. Moving CallableReference.getCallbackID() to
ServiceReference

------------------------------------------------------------------------

--------------------

<mje>+1</mje>

We propose removing getCallbackID() from access by
service providers  

as it is cannot be used for correlation in
third-party components  

except when the third-party is configured with a
callback to the same  

client component. For example in the stateless
case:

A---------B--------C

The only way C can callback to A is either by
calling back B or  

having B pass a CallableReference to C.  The
callback ID is not  

sufficient, in itself, to be used by arbitrary
code to send a message  

that qualifies as a callback in this bidirectional
exchange.  For  

example, if B has clients other than A, the
callback ID doesn’t have  

the information to tell which client it is for.

Moving CallableReference.getCallbackID() to
ServiceReference   

simplifies the Java programming model by:

a. Eliminating an API that can only be used in
very particular  

circumstances.

b. Removing the need for a runtime implementation
to create and  

maintain a distributed domain-wide mapping of
callback ids to  

callback endpoints. Note that routing information
cannot be encoded  

in the callback id as it can be set by the
application.

3. Making ServiceReference.setCallbackID(Object
id) illegal and  

ServiceReference.getCallbackID() (assuming #2)
return null for  

conversational interactions.

------------------------------------------------------------------------

------------------------------------------------------------------------

----------------------------------------------------------------------

Having both callback ids and conversation ids for
bi-directional  

conversational wires is confusing and not needed
as the conversation  

id will be used for correlation. 

<mje>This is what I
challenge - it isn't true if you need to correlate callback responses

to individual requests.  Conversation
ID is necessarily the same for all the forward 

invocations in a
conversation.  This then is useless for distinguishing between 

callback messages resulting
from different forward invocations. 

In fact, I argue that
conversationID is almost useless for the client - it's really a 

provider-defined thing
useful for the provider to access its state data.</mje>

Sometimes a
client may wish to  

correlate callback invocations using the callback
id. For  

conversational callbacks, correlation using the
callback id is  

limited. Since conversations are serial between a
particular client  

instance and a provider instance, the additional
correlation that may  

be needed is between different invocations to the
provider within the  

same conversation. In other words, conversations
by nature correlate  

invocations between a client and provider
instance. If finer-grained  

correlation is needed such as between multiple
invocations in the  

same conversation, correlation data can be
included as part of the  

service operation data (e.g. “line item
number” can be passed as a  

parameter in the example above).

<mje>THIS is where I
hear the baby screaming as it flies out with the bathwater. 

IF you really believe that,
then there is no need for a callback ID ever.  All you 

do is use correlation data
in the messages themselves.  I suggested this to 

Michael
 Rowley not so long ago, with the model of BPEL
correlation in mind.  He 

was of the opinion that the
BPEL correlation approach was a failure and not 

to be used as a model for
SCA. 

There is a good argument to
be made for a system managed correlation 

mechanism in that it
simplifies the life of the programmer.  Forcing the use of

correlation data in the message
may well have the consequence of distorting 

the form of the messages,
since they now *HAVE* to contain data fields that 

are "uniquely
identifying" - and this must be done for all callback messages.

</mje>

This simplifies the Java programming model by
clarifying the  

relationship between callback and conversation
ids.

4. Removing the ability to specify stateless or
conversational  

callback service contracts

------------------------------------------------------------------------

-----------------------------------------------------

<mje>+1</mje>

We propose wires be either conversational or
stateless in both  

directions and that it be specified as part of the
forward service  

contract. In other words, @Conversational cannot
be specified on the  

callback interface definition.  We don't
believe having a stateless  

callback for a stateful forward invocation and
vice versa makes much  

sense.

---------------------------------------------------------------------

To unsubscribe from this mail list, you must leave
the OASIS TC that

generates this mail.  You may a link to this
group and all your TCs in OASIS

at:

https://www.oasis-open.org/apps/org/workgroup/portal/my_workgroups.php

 

Unless stated
otherwise above:

IBM United Kingdom Limited - Registered in England
and Wales
with number 741598. 

Registered office: PO Box 41,
  North Harbour, Portsmouth, Hampshire PO6 3AU