sca-j message
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
| [List Home]
Subject: RE: [sca-j] Java Callback Simplification Proposal
- From: Simon Nash <NASH@uk.ibm.com>
- To: "OASIS Java" <sca-j@lists.oasis-open.org>
- Date: Wed, 13 Feb 2008 22:25:21 +0000
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"
<mrowley@bea.com>
13/02/2008 14:58
|
To
| Mike Edwards/UK/IBM@IBMGB, "OASIS
Java" <sca-j@lists.oasis-open.org>
|
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:mike_edwards@uk.ibm.com]
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: mike_edwards@uk.ibm.com
Jim Marino <jmarino@bea.com>
12/02/2008 18:23
|
To
| OASIS Java <sca-j@lists.oasis-open.org>
|
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
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
| [List Home]