What's the concept of offshoots, and when should I use it?
Conceptually, offshoots are remotely visible objects whose life is limited to that of the component or client that created them. Offshoots logically belong to their "mother" component (or client) out of which they "grow" (that's where the funny term comes from). Yet offshoots can have their own functional interfaces. Technically, under the hood of ZLegacy/ACS.ContainerServices, offshoots are activated as CORBA objects using a POA that is dependent on the "mother" POA. Offshoots are mainly used internally by ACS, for example to implement the callback mechanism that allows one component to offer a callback object to another component, or for the DAO objects obtained from the CDB. But also the archive uses offshoots for DB cursors and other things. Here we list some features and compare offshoots to plain programming language level objects and to ACS components. There it may become clearer whether offshoots are attractive for your application:
A likely scenario in which offshoots would be useful is the following:
Warning: in some cases (e.g. operational archive), offshoots have been used as a replacement for dynamic components when the latter concept was not yet available in ACS. These should not serve as role models, but should be changed at some point. How to implement your own offshootThe offshoot class must be defined as an IDL interface that inherits from ACS OffShoot: interface Cursor : ACS::OffShoot { ... }; Notice that the offshoot base interface does not declare any operations. It serves only as a "marker interface" that helps avoid some wild activation of CORBA objects that could quickly mess with the way that ACS harnesses CORBA. The IDL compiler will create the same kind of proxy and skeleton classes as it does for components, for example in Java
Most of these classes you can ignore; what you need is described below in the example. In your component implementation, you can instantiate the offshoot skeleton class and pass it to the method Here are some example code fragments from a component that creates the above Cursor offshoot. First we declare our offshoot class as a subclass of public class CursorImpl extends CursorPOA { public CursorImpl(DBCursor cursor, ContainerServices cs) { if (cursor == null || cs == null) { throw new IllegalArgumentException("DBCursor and ContainerServices must not be null."); } this.cursor = cursor; this.containerServices = cs; this.logger = containerServices.getLogger(); } public void close() { // ... closing of db cursor and exception handling omitted here in the example ... // This is an example where the offshoot object deactivates itself // when its client no longer needs it. // In a different design the client would tell the mother component that the offshoot is no longer needed // (or the component figures this out itself), and then the component calls deactivateOffShoot. containerServices.deactivateOffShoot(this); } Note that we could also have extended our offshoot class from Then we instantiate our offshoot class, activate the object, cast it to its correct type, and return it. CursorImpl externalCursor = new CursorImpl(internalCursor, containerServices); return CursorHelper.narrow(containerServices.activateOffShoot(externalCursor)); |
Related articles appear here based on the labels you select. Click to edit the macro and add or change labels.
|