Next in thread → Next in month →

RE: [sca-j] Java Callback Simplification Proposal

From
Simon Nash <>
Date
2008-02-14T17:13:33+00:00
ID
Thread
RE: [sca-j] Java Callback Simplification Proposal
Michael,

Thanks for your positive reaction.  I'd
like to point out that this isn't quite the same as your proposal 4.  With
my proposal it would be valid to have

   - non-conversational forward
interface and conversational calllback interface

   - conversational forward
interface and conversational calllback interface

whereas the BEA proposal 4 would allow

   - non-conversational forward
interface and non-conversational calllback interface

   - conversational forward
interface and conversational calllback interface

I think it's clearer to explicitly mark
the callback interface as conversational rather than imply it.  One
benefit of this (apart from clarity) is that the same interface can be
used as a conversational forward interface as well.  I can think of
situations where this would be useful.

I'll need to think a bit more about
which instance the callback should go to.  In particular, we need
to consider what happens for conversational-scoped clients when the forward
interface is either non-conversational or conversational.  The client
could force the same instance to be used for callbacks by propagating the
active conversation ID on the forward call.  If the client doesn't
do this, then I don't think we should guarantee that the callback returns
to the same instance.

    Simon

Simon C. Nash, IBM Distinguished Engineer

Member of the IBM Academy of Technology

Tel. +44-1962-815156  Fax +44-1962-818999

"Michael Rowley"
<> 

14/02/2008 15:21

To

Simon Nash/UK/IBM@IBMGB, "OASIS
Java" <>

cc

Subject

RE: [sca-j] Java Callback Simplification
Proposal

Simon,

 

I like the idea of combining
the callbackID and the conversation ID, since in our proposal only one
of them ever made sense at a time.  I also like the way you described
it: “thinking of callbacks as a type of conversation that starts with
a forward call and ends when the last callback has been made by the service
provider”.

 

You objected to our proposal
4, which we titled: “Removing the distinction between stateless and conversational
callback interfaces.”  However, you then proposed exactly the semantics
I was thinking of (although I hadn’t thought of merging the two kinds
of IDs).

 

Your proposal (1) says: “A
bidirectional interface MUST have a conversational callback interface.”
 This is exactly what I wanted.  There is no choice to be made.
 However, since there is no choice, I was not going to require that
the callback interface be marked as “conversational”.  Its semantics
are the semantics of a callback.  The “conversational” marking doesn’t
help.

 

One question that hasn’t been
answered in either of our proposals is what instance is a callback delivered
to?  I’m thinking that for stateless-scoped clients, it goes to a
new (or pooled) instance.  For every other scope, it goes to the instance
that made the outgoing call, if it still exists.  If it doesn’t exist,
it means that the client no longer cares about the callback and so it is
dropped (and probably logged).

 

Michael

 

From: Simon Nash [mailto:]

Sent: Thursday, February 14, 2008 5:02 AM

To: OASIS Java

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

 

I need to make a small change to my proposal so that it covers another
important case. 

If the forward interface is always conversational, it is difficult to handle
the case of multiple forward calls each with its own separate series of
callbacks, because the same conversation ID would be used for all the callbacks
and it would be hard to tie the callbacks to their corresponding forward
call. 

The solution is to allow the forward interface to be non-conversational
even though the callback interface is conversational (as is possible at
present).  Each forward call would start a new callback conversation
(and allocate a new conversation ID) but there is no conversational relationship
between calls in the forward direction.

Here's an example of how this works (extending the previous example):

a) Stateless client A makes a forward call F to stateless service B over
bidirectional non-conversational interface X (with callback conversational
interface Y). 

b) Call F causes the infrastructure to start a callback conversation and
allocate a conversationID C for this, which is passed on call F. 

c) Stateless client A makes a second forward call F to stateless service
B over the same interface X 

d) The second call F causes the infrastructure to start a callback conversation
and allocate a conversationID D for this, which is passed on the second
call F. 

e) The first invocation of F on B makes callbacks G and H.  These
are routed to new stateless instances of A.  These callbacks carry
conversationID C, which can be used by A to perform correlation with the
first call F (in place of callbackID). 

f) Call H ends the conversation that was started by the first call F.  (If
this isn't done, the conversation will eventually time out.) 

g) The second invocation of F on B also makes callbacks G and H.  These
are routed to new stateless instances of A.  These callbacks carry
conversationID D, which can be used by A to perform correlation with the
second call F (in place of callbackID). 

h) Call H ends the conversation that was started by the second call F.
 (If this isn't done, the conversation will eventually time out.)

Steps e) and g) can be interleaved without any confusion, because the callbacks
are distinguished by the different conversation IDs C and D.

Here is a summary of the revised proposal (with RFC2119 keywords this time):

1. A bidirectional interface MUST have a conversational callback interface.
 The forward interface MAY be non-conversational or conversational.
 The client and service implementations MAY have any scope.

2. A forward call over a bidirectional conversational forward interface
MUST start a forward conversation and a callback conversation unless a
forward conversation is already active.  The same conversation ID
MUST be used for both the forward and callback conversations.

3. A forward call over a bidirectional non-conversational interface MUST
start a callback conversation and MUST NOT start a forward conversation..

4. All callbacks made through a callback reference created by a forward
call MUST be treated as part of the callback conversation that was started
or continued by the forward call.

5. Normal rules for ending the callback conversation apply.  The final
callback MAY end the conversation, or the conversation MAY expire through
timing out.. 

6. If the service implementation is conversation-scoped, the infrastructure
MUST perform instance routing based on the conversation ID passed on the
forward call.  Otherwise, the conversation ID is available to the
service implementation to perform its own correlation.

7. If the client implementation is conversation-scoped, the infrastructure
MUST perform instance routing based on the conversation ID passed on the
callback.  Otherwise, the conversation ID is available to the client
implementation to perform its own correlation.

8. Any correlation that is more complex than the above mechanisms MAY be
performed by means of business data passed over forward and callback messages.

    Simon 

Simon C. Nash, IBM Distinguished Engineer

Member of the IBM Academy of Technology

Tel. +44-1962-815156  Fax +44-1962-818999

Simon Nash/UK/IBM@IBMGB

13/02/2008 22:25

To

"OASIS Java" <>

cc

 

Subject

RE: [sca-j] Java Callback Simplification
Proposal

 

 
 

I'll  resist the temptation to interleave more deeply.

I'm OK with proposals 1, 2 and 3.  For proposal 2, I didn't fully
understand the use case involving third parties and mapping callbacks IDs
to callback endpoints, but I'm OK with this on simplification grounds.

I'd like to propose a small change to proposal 4.  For the conversational-both-ways
case, I think it's better to still mark the callback interface as conversational
rather than having this implied from the conversational marking on the
forward interface.  I think this is clearer and would allow the callback
interface to be used as a regular forward conversational interface, which
could somettimes be useful.

I would like to go a step further and eliminate callback IDs in all cases.
 I believe this can be done by bringing callbacks and conversations
more closely together and using the conversation ID for client-side correlation
in cases that are currently treated as non-conversational and where the
callback ID is being used. 

This approach involves thinking of callbacks as a type of conversation
that starts with a forward call and ends when the last callback has been
made by the service provider.  This means that all callback interactions
would in effect be conversational in both directions (from an interface
perspective).  If the client's implementation isn't conversation-scoped,
the conversation ID from the callback would be available to the client
to use to perform its own correlation, replacing the current use of callbackID
for this purpose. 

WIth this view of the world, a callback would observe the following pattern:

1. Bidirectional interfaces must be marked as conversational for both the
forward and callback interfaces.  The client and service implementations
can have any scope. 

2. A forward call over a bidirectional interface starts a conversation
if it's not already started (this is just the current conversational semantics).

3. All callbacks are part of the same conversation that was started or
continued by the forward call.

4. Normal rules for ending this conversation apply.  Typically, the
final callback would end the conversation.

5. If the service implementation is conversation-scoped, the infrastructure
will automatically perform routing based on the conversation ID passed
on the forward call.  Otherwise, the conversation ID is available
to the service implementation to perform its own correlation.

6. If the client implementation is conversation-scoped, the infrastructure
will automatically perform routing based on the conversation ID passed
on the callback.  Otherwise, the conversation ID is available to the
client implementation to perform its own correlation.

7. Any correlation that is more complex than the above mechanisms provide
must be performed by means of business data passed over forward and callback
messages. 

Here's an example of how this would work for the simplest "stateless
callback" case: 

a. Stateless client A makes a forward call F to stateless service B over
bidirectional conversational interface X (with callback conversational
interface Y). 

b. Call F causes the infrastructure to start a conversation and allocate
a conversationID C, which is passed on call F.

c. B makes callbacks G and H.  These are routed to new stateless instances
of A.  These callbacks carry conversationID C, which can be used by
A to perform correlation (in place of callbackID).

d. Call H ends the conversation that was started by call F.  (If this
isn't done, the conversation will eventually time out.)

   Simon 

Simon C. Nash, IBM Distinguished Engineer

Member of the IBM Academy of Technology

Tel. +44-1962-815156  Fax +44-1962-818999

"Michael Rowley"
<> 

13/02/2008 14:58

 

To

Mike Edwards/UK/IBM@IBMGB,
"OASIS Java" <>

cc

 

Subject

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 

 

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 

 

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 

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
Next in thread → Next in month →