sca-c-cpp message
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
| [List Home]
Subject: RE: [sca-c-cpp] ISSUE 54: Long Running Operations and C++
- From: Bryan Aupperle <aupperle@us.ibm.com>
- To: sca-c-cpp@lists.oasis-open.org
- Date: Fri, 13 Feb 2009 14:12:44 -0500
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
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
| [List Home]