sca-j message
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
| [List Home]
Subject: RE: [sca-j] ISSUE 25 - Callback Simplification
- From: Simon Nash <NASH@uk.ibm.com>
- To: mnrowley@gmail.com
- Date: Thu, 29 May 2008 19:53:00 +0100
Michael,
I took a look at the WCF duplex contract
sample. In SCA terms, this is a stateful callback from a conversational
service to a conversational client, where both the "client" and
service maintain shared state over a series of bidirectional interactions.
I am putting the word "client" in quotes because the callbacks
are actually directed via an InstanceContext object to a different object
instance from the client sending the requests, though maybe it would be
possible to use the same instance for both. Also, there is no mention
of a "callback ID" that the "client" can use to correlate
a callback with a specific forward call that it has made. If this
is required, it would need to be passed as an application-level parameter.
It would be possible to write the WCF
duplex sample with my proposal, as long as the client is conversational
(which it needs to be for a WCF duplex contract). So my proposal
is compatible/interoperable with the WCF sample. I believe yours
is not compatible/interoperable, because the SCA callbackID magic doesn't
have a mapping into any corresponding WCF magic.
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
17/04/2008 05:10
|
To
| sca-j@lists.oasis-open.org
|
cc
|
|
Subject
| RE: [sca-j] ISSUE 25 - Callback Simplification |
|
Michael,
Sorry for the delay in responding. I have been on vacation in a primitive
and beautiful part of the USA (Southern Utah) where internet connectivity
is a very scarce resource, and not possessed by the current and previous
places where I have been staying.
I'll start by giving the code for this example using my proposal. There's
a slight inconsistency in your code, with orderData being passed on the
call to orderProcessor.placeOrder() where I think you meant to pass order.
I've made this change in the code below. This makes the Client
class rather trivial, as it seems to add no value at all but simply forwards
the order passed to its buy() method straight through to orderProcessor.
A more realistic scenario would be where different items in the order
were ordered from different suppliers.
@Callback(OrderCallback.class)
public interface OrderService {
void placeOrder(Order order);
}
public interface OrderCallback {
void confirm(Order order);
}
public class Client implements OrderCallback {
@Reference
OrderService orderService;
void buy(Order order) {
orderProcessor.placeOrder(order);
}
void confirm(Order order) {
order.setConfirmed(true);
}
}
This contains less code than even your conversational client case, and
it works for all client scopes. It handles the stateless scope case
with no need for a ServiceReference, the calls to getCallbackID(), or a
PersistenceHelper (although the more realistic scenario that I described
above would need a PersistenceHelper). It handles multiple outstanding
callbacks (for multiple orders in progress at any one time, which is certainly
plausible). Despite the extra parameter on the callback, I'd say
that this is simpler than your version.
Some more comments on your proposed approach:
1. Your assertion that service providers will design services only for
conversational clients and then get caught out when clients have other
scopes doesn't makes sense to me. One of the basic principles of
SOA is that service providers should design a service and its interface
without knowing what kind of client will invoke the service. We should
not be optimizing SCA around use cases that violate SOA principles.
2. There's a timing window in your stateless scoped example. It doesn't
work if the callback occurs before the client has called persistenceHelper.persist(),
To get around this, you'ld need to first create your own unique callbackID
(an orderID), then use this orderID to make the persistenceHelper.persist()
call, then call setCallbackID() on the ServiceReference, and finally call
orderProcessor.placeOrder(). The need to create this orderID in business
logic means that your code would become closer to my equivalent, in which
an orderID is created in business logic, passed to the service, and returned
on the callback.
3. Your reference to WCF duplex contracts is interesting, and I'll check
it out when I get back to civilization. I'll be interested to see
how it handles the issues I have raised above.
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>
10/04/2008 21:37
|
To
| "Michael Rowley"
<mrowley@bea.com>, Simon Nash/UK/IBM@IBMGB, <sca-j@lists.oasis-open.org>
|
cc
|
|
Subject
| RE: [sca-j] ISSUE 25 - Callback Simplification |
|
Note that BEA is not the only company with experience treating service
callbacks in this way. Take a look at an example “duplex
contract” in WCF.
Note the lack of any correlation data in the callback parameters.
Michael
From: Michael Rowley [mailto:mrowley@bea.com]
Sent: Thursday, April 10, 2008 4:26 PM
To: Simon Nash; sca-j@lists.oasis-open.org
Subject: RE: [sca-j] ISSUE 25 - Callback Simplification
Simon,
Looking at code is indeed an excellent way to handle this. Here is
a bidirectional interface pair that I think represents the most common
case:
@Callback(OrderCallback.class)
public interface OrderService {
void placeOrder(Order order);
}
public interface OrderCallback {
void confirm();
}
Here is a conversational client. I believe this client can be written
using either of our proposals:
@Scope(CONVERSATIONAL)
public class Client implements OrderCallback {
Order myOrder;
@Reference
OrderService orderService;
void buy(Order order) {
myOrder = order;
orderProcessor.placeOrder(orderData);
}
void confirm() {
myOrder.setConfirmed(true);
}
}
The above client is, I believe, the simplest and most common case. I
think it is much less common that there will be multiple outstanding callbacks,
but if there were, the client might need to maintain a Map of, for example,
items ordered and confirmations for each item (assuming there is a callback
for each). However, it would still be in the context of the original
purchase order that had been made.
Nonetheless, it should be possible (although not necessarily easy, given
its less frequent use) that someone be able to create a client for this
service that is stateless. This stateless client would be responsible
for the storage and correlation work that a conversational component would
have done for him. Thus the stateless client would look like this
(using the current API, so as not to confuse things too much):
@Scope(STATELESS)
public class Client implements OrderCallback {
@Reference
ServiceReference<OrderService> orderService;
@Context
RequestContext requestContext;
PersistenceHelper persistenceHelper; // a way of skipping
junk I don’t want to show.
void buy(Order order) {
orderService.getService().placeOrder(order);
Object orderID = orderProcessor.getCallbackID();
persistenceHelper.persist(orderID, order);
}
void confirm() {
Object orderID = requestContext.getCallbackID();
Order order = persistenceHelper.find(orderID);
order.setConfirmed(true);
persistenceHelper.store(orderID, order);
}
}
This is leaving out all the technical junk that would also need to be done
in order to set up the connection to the persistence context, dealing with
transactions (even if declaratively), etc. All of the stuff that
is done for you when you have a conversational client.
SUMMARY:
In both of our approaches people can, and therefore would, create the simple
code in the conversational-scoped client of the first example. However,
in your approach, it would then be impossible to use that service from
the stateless client, such as I show in the second example. Because
of this, people would unwittingly write services that could only be used
by conversational clients.
I do understand that you would advise them _not_ to create interfaces
such as the one I have here, and would tell them that they _should_
always pass around enough information so that they could create a stateless
client even without help from a system generated callbackID. However,
since in the conversational-scoped case that extra information would not
be needed, I don’t think people would do it.
Michael
From: Simon Nash [mailto:NASH@uk.ibm.com]
Sent: Thursday, April 10, 2008 10:42 AM
To: sca-j@lists.oasis-open.org
Subject: RE: [sca-j] ISSUE 25 - Callback Simplification
Michael,
I think we're talking about example 2 here (stateless client and stateful
callback).
The bidirectional interface provided by C should be usable by clients of
all different scopes. For a stateless scoped client, the business
data must be present or else the client cannot identify the order being
confirmed. I'm not sure how your proposal would address this requirement.
The automatic correlation works only in very limited cases (conversation
scoped client with a single outbound request in progress at any one time).
In all other cases, business data must be used for the correlation.
It's far simpler to pass explicit business data on the service call
in every case, with a consistent programming model, than to have an automated
"convenience" feature for a single relatively uncommon case and
a complex programming model that uses special APIs to handle all other
cases.
Can you illustrate the code needed on the client and provider sides to
implement example 2 with your proposal for a) a stateless client and b)
a conversational client? The interface and provider code should be
the same in both cases. I think this will make the complexity issues
clear.
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>
08/04/2008 21:38
|
To
| Simon Nash/UK/IBM@IBMGB
|
cc
| <sca-j@lists.oasis-open.org>
|
Subject
| RE: [sca-j] ISSUE 25 - Callback Simplification |
|
Simon,
I am certainly willing to give up any automatic correlation when there
may be multiple simultaneous outstanding callbacks. In that case,
use business data.
However, for the common case where there is only one outstanding callback
for a specific client, then your approach already allows the client to
know what the callback is talking about without passing any correlation
information in the business data. This is because your approach routes
the callback to the right client instance.
I think this is good. We should encourage it. However, in the
unfortunate event that someone can’t use a conversational-scoped client,
they should still be able to use the bi-directional service without having
to ask the service provider to change its interface. Admittedly,
the stateless client will have to implement many of the steps that you
list below, but that is the price for being non-conversational.
I also believe that if we followed your suggestion, then no matter what
we say, people just won’t send unneeded correlation information as business
data when they know that the callback is going to be sent to the right
place. They won’t think: “Oh, just in case I ever have a stateless
client, I better put this extra data into the business data.” Instead,
they will just leave out the data, with the unintended consequence being
that they’ve limited their clients to being only those that use a conversational
scope. That would be bad.
Michael
From: Simon Nash [mailto:NASH@uk.ibm.com]
Sent: Thursday, April 03, 2008 12:13 PM
To: Michael Rowley
Cc: sca-j@lists.oasis-open.org
Subject: RE: [sca-j] ISSUE 25 - Callback Simplification
There's a basic problem with this approach. Whether or not B has
conversational scope depends on its interactions with A. In a single
A to B conversation, the same conversational instance of B might place
5 orders with C. Using the A to B conversation ID to identify the
order that was placed is therefore never safe, even if B is conversational.
The only way this approach could work is if B were to generate a new "callback
conversation ID" for every request that it sends to C. This
would be different from any regular conversation ID that B may be sending
to C as part of a B to C conversation. Here are the steps that would
need to be followed.
1. B generates a new "callback conversation ID" and associates
it with its reference for C. This needs to happen before any calls
to C are made.
2. An API needs to be defined to allow B to get this "callback conversation
ID" before it makes the placeOrder() call to C. B stores the
"callback conversation ID" and associates it with the order it
is placing.
3. B makes a placeOrder() call to C.
4. The SCA infrastructure transmits the "callback conversation ID"
from B to C with the placeOrder() call.
5. C stores the "callback conversation ID" in the callback reference
so that it can be returned to B in any callbacks.
6. C makes a callback to B.
7. The SCA infrastructure transmits the "callback conversation ID"
from C to B with the callback.
8. An API needs to be defined to allow B to get this "callback conversation
ID" when the callback is executing. This ID is different from
the conversation ID that's active for the A to B conversation.
All of the above are not needed if the correlation information is passed
as business data, which is a much simpler approach.
I considered this approach when I was trying to come up with a good definition
of conversational callback interfaces between the 3/20 and 3/27 calls,
but I rejected it because I did not believe that the value justified the
complexity.
Simon
Simon C. Nash, IBM Distinguished Engineer
Member of the IBM Academy of Technology
Tel. +44-1962-815156 Fax +44-1962-818999
"Michael Rowley" <mnrowley@gmail.com>
03/04/2008 15:40
Please respond to
mrowley@bea.com |
|
To
| Simon Nash/UK/IBM@IBMGB, sca-j@lists.oasis-open.org
|
cc
|
|
Subject
| RE: [sca-j] ISSUE 25 - Callback Simplification |
|
I like the fact that, in Simon's
model, callbacks always go back to the instance that made the outbound
call. However, it looks like he does not take advantage of that fact
in the interfaces of the examples that he created. For example, he
has the following:
@Callback(OrderCallback.class)
public interface Order {
void placeOrder(String orderID, String orderData);
}
public interface OrderCallback {
void confirm(String orderID);
void update(String orderID, String status);
}
However, since you know that
the order callback goes back to the right instance, you should be able
to define the callback interface as follows:
public interface OrderCallback {
void confirm();
void update(String status);
}
In Simon's model this should
be possible, but there is a catch. If the callback interface is defined
this way, the client has to use a conversational scope. If the client
is stateless or composite scoped, then the routing of the callback to the
right instance doesn't say anything useful about what is being confirmed.
I would like to enable this
style of callback interface irrespective of the scope of the client. As
with Simon's approach, if the client is conversational scoped, then the
client is especially simple and does not have to do any correlation at
all. However, if the client needs to use some other scope, for whatever
reason, then the service with the callback can still be used. However,
it just needs to get the callback ID (or conversation ID) that is associated
with the callback in order to determine what the callback is talking about.
Michael
From: Simon Nash [mailto:NASH@uk.ibm.com]
Sent: Thursday, March 27, 2008 11:47 AM
To: sca-j@lists.oasis-open.org
Subject: Re: [sca-j] ISSUE 25 - Callback Simplification
There's an update to this proposal at
http://www.oasis-open.org/apps/org/workgroup/sca-j/download.php/27733/JAVA-25-Proposal-2.doc
This version removes conversational callbacks as all my attempts to define
these involve more complexity than is justified by the functional value
of this capability.
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
20/03/2008 11:01
|
|
Last week I took an action to produce a written up proposal for callback
simplification by today. I have uploaded this to the document repository
as
http://www.oasis-open.org/apps/org/workgroup/sca-j/download.php/27649/JAVA-25-Proposal.doc.
The content of this proposal corresponds to the "Callback Simplification"
section of the proposal sent out by Michael R, and does not address the
changes proposed in the "API Simplification" section. I
think it is best to have these discussions separately.
This proposal corresponds to what I was describing at the sca-j F2F with
two changes / additions:
1. Outstanding callbacks don't pin conversational objects after the conversation's
creator has ended the conversation.
2. In all cases, the caller of a bidirectional interface creates the callback
EPR that will be used (including any reference parameters needed).
I believe the issues that still need to be discussed and resolved are as
follows:
a) Should all 4 combinations of conversational and non-conversational forward
and callback interfaces be allowed, or only 2 of these?
b) Should the callback interface used to make callbacks to a conversation-scoped
component be marked as conversational?
c) Should each forward request within a conversation generate a unique
ID that is not part of business data and is returned with the callback?
Simon
Simon C. Nash, IBM Distinguished Engineer
Member of the IBM Academy of Technology
Tel. +44-1962-815156 Fax +44-1962-818999
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
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]