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