Ignacio came up with a nice design and implementation (including a presentation posted on the wiki) for callback support. I've applied the patch as well as did a bit of refactoring that I will describe below. There's still a lot of refactoring to be done and some things that we will probably want to clean up a bit more. Also, callbacks currently work from component-to-component invocations and not through references (i.e. across remote boundaries).

The changes I made were:

1. Move the functionality of CallbackProcessor to ServiceProcessor and HeuristicProcessor to avoid ordering problems. Specifically, CallbackProcessor introspected the implementation class and added callback information to the service located on the component type. This assumes the service processor is invoked before the callback processor, which in most cases it is, but may not be depending on SCDL configuration ordering. To avoid this, and as callback information is part of service processing, I moved it to the service processor. The HeuristicProcessor may also need to analyze callback information so I factored common methods to ProcessorUtils - not ideal but given the complexities of introspecting implementation artifacts it may be the best solution.


2. I changed the outbound wire on the source side to contain the inbound callback wire *as well as* the outbound callback wire associated with the target. So given:

@Callback(FooCallback.class)
interface Foo{
    void call()
}

interface FooCallback{
        void callback();
}
class Client implements FooCallback{
        
        @Reference
        protected Foo foo;

        public void callback(){
                System.out.println("received callback");
        }

        public void invoke(){
                foo.call();             
        }
}

class FooImpl implements Foo{
        
        @Callback
        protected FooCallback callback;

        public void call(){
                callback.callback();
        }

}

The builder is currently responsible for creating inbound and outbound wires for a component (I intend to do a little refactoring here but that's a different topic). For example, when building Client, the builder will create the outbound wire for the "foo" reference. When building FooImpl, it will create the inbound wire for the "Foo" service. The Connector will bridge the two.

The builder is also responsible for creating inbound and outbound callback wires. The one difference is that the outbound callback wire is created by the builder when it evaluates the client component. For example, when building Client, the outbound wire associated with the "foo" reference will have both inbound and outbound callback wires on it. These will be bridged by the connector. This allows all wires within a composite to by "connected" and target wire resolution avoided during invocation (remote invocations will need some dynamicity). During an invocation, the AsyncTargetInvoker will set the work context with the outbound callback wire. When a callback is made by the target, the proxy invocation handler will pull the outbound callback wire from the work context and send the invocation down the correct chain. This will allow us to support the case where two different client components may invoke a target and the callback needs to resolve to the correct client.

I'm not sure this is the best approach to take so it would be worth discussing further.

Things to do
---------------------

I'm going to take another pass at cleaning up the extension API and some code refactorings.

We need to get callbacks working for References and this will involve handling longer-term conversational state. I was thinking we will need to have a durable persistent store tied to a conversational scope container and we may be able to implement this as a write- behind cache. The reference would flow the callback component id (a FQN in the composite hierarchy) as well as an id associated with the component implementation instance. The callback component id would be used to resolve the correct callback wire, while the conversation id would be used by the conversational scope container to resolve the correct implementation instance, possibly deserializing it with its state. As part of the serialization, we are going to need a way to handle reference proxies that may be on the callback instance. For example, Client may have other references pointing to other components that need to be reactivated during the callback.

Anyone interested in working on this let Ignacio and I know.

Jim








---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to