From: Bryan Aupperle
[mailto:aupperle@us.ibm.com]
Sent: Friday, February 20, 2009
11:42 AM
To: sca-c-cpp@lists.oasis-open.org
Subject: RE: [sca-c-cpp] ISSUE 54:
Long Running Operations and C++
Here is a pass at a merge of my proxy proposal and
David's async invocation proposal.
This
leaves proxy generation for local interfaces direct from C++ for now.
Bryan Aupperle, Ph.D.
STSM, WebSphere Enterprise Platform Software Solution Architect
Research Triangle Park, NC
+1 919-254-7508 (T/L 444-7508)
Internet Address: aupperle@us.ibm.com
"David Haney"
<haney@roguewave.com>
02/17/2009 04:21 PM
|
To
|
"Pete Robbins"
<ROBBINS@uk.ibm.com>, <sca-c-cpp@lists.oasis-open.org>
|
cc
|
|
Subject
|
RE: [sca-c-cpp] ISSUE 54: Long Running
Operations and C++
|
|
Attached is an updated version of the proposal
for Issue 54. The response object has been updated so that it can be used
for callbacks, polling, or synchronous access. The function pointer has
been replaced with a function object, and various interfaces have been updated
or moved around. All of the examples assume that a ServiceProxy is always
returned, so this update may need to be put on hold until a more complete
review of the spec has been done to switch to using ServiceProxies instead of
void*.
Thanks.
David.
From: Pete Robbins [mailto:ROBBINS@uk.ibm.com]
Sent: Monday, February 16, 2009 11:01 AM
To: sca-c-cpp@lists.oasis-open.org
Subject: RE: [sca-c-cpp] ISSUE 54: Long Running Operations and C++
I think we have to go with (1), always return a proxy. As is pointed out the
runtime should always be able to know when control is passed between
components.
Way back in the beginnings of time we did consider mandating that all services
would inherit from a base class... and rejected it. I don't think that is what
you are suggesting here. I think you are saying that the returned (generated)
proxy should always inherit from a standard proxy base class?
So the ComponentContext method would be:
virtual ServiceProxy * getService(const
std::string& referenceName) const = 0;
I like this better as I have a personal hatred of void* ;-)
Cheers,
Pete Robbins
Phone: UK
(01962) 818667
Notes: Pete Robbins/UK/IBM@IBMGB
email: robbins@uk.ibm.com
Bryan Aupperle
<aupperle@us.ibm.com>
13/02/2009 19:12
|
To
|
sca-c-cpp@lists.oasis-open.org
|
cc
|
|
Subject
|
RE: [sca-c-cpp] ISSUE 54: Long Running
Operations and C++
|
|
I have a slight preference for (1) over (2) (even though it is more spec work).
If the concrete implementation is returned by a getService call, then the
SCA runtime should not know when control is passed from one component to the
next and a getCurrent() is likely to return the wrong context. Further,
even if the client and service are in the same process, if the service's
interface is remotable, the appropriate marshalling/unmarshalling has to be
done.
Having said that, I would only generate the Async functions when necessary -
which does mean the SCDL file have to be considered when generating code.
The base proxy class could be where the API for WiredByImpl is supported. But
if there was not a base proxy class, and async functions are only included when
the asyncInvocation is present , would the proxy have to have its own header
file?
Bryan Aupperle, Ph.D.
STSM, WebSphere Enterprise Platform Software Solution Architect
Research Triangle Park, NC
+1 919-254-7508 (T/L 444-7508)
Internet Address: aupperle@us.ibm.com
"David Haney"
<haney@roguewave.com>
02/13/2009 01:38 PM
|
To
|
Bryan
Aupperle/Raleigh/IBM@IBMUS, <sca-c-cpp@lists.oasis-open.org>
|
cc
|
|
Subject
|
RE: [sca-c-cpp] ISSUE 54: Long Running
Operations and C++
|
|
At the moment we’ve been casting the return from service to a CustomerService*
(in this case), which is the base interface that the user used to define their
interface. I would normally expect that to be a proxy instance as well,
however in the current model I didn’t see any reason why an SCA runtime
couldn’t return the customers concrete implementation instead (for instance if
both the caller and callee are running in the same process). With the
introduction of the Async APIs, it doesn’t seem like that is the case any
longer, and we should always be returning a proxy instance, even in the case
where caller and callee are in the same process.
I think I see three routes we can go:
1) Assume (require) that it is always a proxy
In this case, it doesn’t seem like we should be using the original interface
class directly, and instead should be returning (and casting to) a proxy class
interface. The proxy class interface would provide the same API as the
original C++ interface (possibly by deriving from it), but would also include
additional APIs specific to the proxy (such as the *Async functions), and could
provide basic functionality that is common to all proxies (allowing the user to
customize the binding or endpoint or something else? I’m not sure what
would make sense here). In this case, I think it would make sense to
update all of our examples to indicate that a proxy is being returned from the
getService() calls, i.e instead of getting a CustomerService*, they’d get a
CustomerServiceProxy*, and includes and other factors would need to change).
We should also provide additional details on the code generation process
for that proxy interface. Offhand that seems to include the addition of
the Async methods beyond the normal synchronous methods from the original
interface. I’m not sure whether we should just always generate these
functions, or only generate them if the asyncInvocation intent is specified.
It seems like if we’re going to rely on the asyncInvocation, then an
implementation would need to include the SCDL files in the code generation
process (since they are the definitive source for these properties, right?).
2) Assume that it can be the user’s implementation class or a proxy
In this case, a customer would still need to initially get the service back as
their interface type (CustomerService*), and then would/should
dynamic_cast<> it to a CustomerServiceProxy* if they want to access some
of the extension methods, like *Async. If it’s a user implementation
class, the dynamic_cast will fail (return 0) and they’ll know that those APIs
aren’t available. If it succeeds, they’ll be able to use the asynchronous
APIs. I think in this case we would still need to discuss the code
generation process for the proxy interface (same as above), and we would need
to provide additional details in the async chapter to discuss casting to the
proxy when they want access to those functions.
3) Require the user’s interface to declare the Async methods.
When a user is defining their interface, if they want to support asynchronous
operations, they’ll need to provide the appropriate methods on their interface.
This would require no changes to the way that we currently handle
services, however we’ll then need to deal with the disconnect where a composite
indicates that asyncInvocation should be used (or at least is available) on a
service where the interface does not provide the async methods. We’ll
also need to look at our WSDL->C++ mapping and determine when our generated
interface should include the Async functions.
Off hand I would lean towards (1) or (2), as I don’t like the idea of pushing
the asynchronous APIs on to the service writer. It seems like those are
the kinds of things that should be managed by the runtime. In that case,
I don’t think we should dance around the proxy question, and the spec should be
clear that a proxy MUST or at least MAY be returned from the getService() call,
and what the API of the proxy will look like. Otherwise we’ll head down
the path of implementation-specific definitions for the proxies that may make
it difficult to write portable code.
Thanks.
David.
From: Bryan Aupperle [mailto:aupperle@us.ibm.com]
Sent: Friday, February 13, 2009 5:46 AM
To: sca-c-cpp@lists.oasis-open.org
Subject: RE: [sca-c-cpp] ISSUE 54: Long Running Operations and C++
I may be missing a bit of history here, but my understanding of the spec has
always been that ComponentContext::getService() returned a proxy. From
section 3.1:
The
getService() member function takes as its input
argument the name of the reference and returns a pointer to an object providing
access to the service. The returned object will implement the abstract base
class definition that is used to describe the reference.
The
following shows a sample of how the ComponentContext is used in
a C++ component implementation. The getService() member
function is called on the ComponentContext passing the
reference name as input. The return of the getService() member
function is cast to the abstract base class defined for the reference.
#include "ComponentContext.h"
#include "CustomerService.h"
using namespace oasis::sca;
void clientFunction()
{
unsigned long customerNumber = 1234;
ComponentContextPtr context = ComponentContext::getCurrent();
CustomerService* service =
(CustomerService*
)context->getService("customerService");
short rating = service->getCreditRating(customerNumber);
}
If the object returned by ComponentContext::getService() is not a generated
proxy, then what is it?
Bryan Aupperle, Ph.D.
STSM, WebSphere Enterprise Platform Software Solution Architect
Research Triangle Park, NC
+1 919-254-7508 (T/L 444-7508)
Internet Address: aupperle@us.ibm.com
"David Haney"
<haney@roguewave.com>
02/12/2009 07:51 PM
|
To
|
Bryan
Aupperle/Raleigh/IBM@IBMUS, <sca-c-cpp@lists.oasis-open.org>
|
cc
|
|
Subject
|
RE: [sca-c-cpp] ISSUE 54: Long Running
Operations and C++
|
|
An issue came up when revising this document to take an IOU/Future approach to
the asynchronous interface. With the introduction of the asynchronous
functions, we’ve also introduced the concept of a service proxy class, which I
don’t think has been mentioned before. This appears to be a code
generated class, based on either the WSDL or C++ interface for the service, and
it looks like it will be this class that is returned from the
ComponentContext::getService() and presumably the ExternalContext::getService().
This seems like a relatively significant change from what we’ve discussed
before, and may have wider reaching implications than just the asynchronous
API. For example, if we’re now requiring code generation of a proxy class
for all services, then we no longer have a requirement that the
ComponentContext::getService() method return a type without a base class.
We could require that all generated proxy classes derive from some sort
of base Proxy class. This would allow us to provide a type safe mechanism
for accessing the proxies, instead of the unsafe mechanism we have today:
oasis::sca::ComponentContextPtr context =
oasis::sca::ComponentContext::getCurrent();
MyServiceProxy* proxy =
dynamic_cast<MyServiceProxy*>(context->getService(“MyService”));
proxy will be null if the service we get back isn’t a MyServiceProxy.
This only works though if all proxies (and all services returned from
MyService) inherit from a common base class.
If we are introducing the generation of a proxy concept, we also probably need
to expand the current WSDL mapping rules and clarify how we map from a WSDL to
a generated proxy.
Thanks.
David.
From: Bryan Aupperle [mailto:aupperle@us.ibm.com]
Sent: Friday, February 06, 2009 12:36 PM
To: sca-c-cpp@lists.oasis-open.org
Subject: [sca-c-cpp] ISSUE 54: Long Running Operations and C++
This is a fairly complete proposal
The one topic that is open is how to deal with operations that have multiple
possible WSDL faults. Do we need to define a ServiceBusinessException
class that the classes generated from a WSDL document extend?
Bryan Aupperle, Ph.D.
STSM, WebSphere Enterprise Platform Software Solution Architect
Research Triangle Park, NC
+1 919-254-7508 (T/L 444-7508)
Internet Address: aupperle@us.ibm.com [attachment
"sca-cppcni-1.1-spec-cd02+Issue54a-rev2.doc" deleted by Bryan
Aupperle/Raleigh/IBM] ---------------------------------------------------------------------
To unsubscribe from this mail list, you must leave
the OASIS TC that
generates this mail. Follow this link to all
your TCs in OASIS at:
https://www.oasis-open.org/apps/org/workgroup/portal/my_workgroups.php