Hey,

One of the ideas with side-effects is that it should be possible to 
invoke them asynchronously. For this reason, in an design-up-front kind 
of thing, we added the @Asynchronous annotation to be added to 
side-effects that should be invoked asynchronously.

Now I'm not too sure that's a good idea. The reason is that there are so 
many ways to invoke side-effects asynchronously (separate thread, put in 
JMS queue, send to JavaSpace, etc.), and they all have different 
semantics, that I don't think it's going to be so easy as to just mark a 
side-effect as @Asynchronous and that's it.

I'm not sure how to do it instead, but one way is to push the 
responsibility to the implementor. Basically in the side-effect 
implementation it can use whatever method it wants, and
delegate to it. If the implementation being delegated to takes a 
reasonably generic interface as input (such as InvocationHandler) this 
will not tie the actual application code to it.

I have as a test implemented a generic side-effect that delegates to a 
Java 5 Executor (implemented by a threadpool), which in turn is 
implemented as a ServiceComposite so that it is activated/passivated 
when the application starts/stops. Here's the application code that uses it:
@SideEffects(ExecutorSideEffect.class)
@Mixins(TestMixin.class)
public interface TestComposite
     extends Composite
{
     @ExecuteSideEffect( LogCall.class)
     String doStuff();
}
---
Here I declare the ExecutorSideEffect to be used, and then the 
annotation declares what it should instantiate and delegate to when 
invoked. The ExecutorSideEffect has @AppliesTo(ExecuteSideEffect.class) 
of course.

The LogCall could be implemented like this:
public static class LogCall
     implements InvocationHandler
{
     public Object invoke( Object o, Method method, Object[] objects ) 
throws Throwable
     {
         System.out.println("Called "+method.getName());
         return null;
     }
}
---
The ExecutorSideEffect hence simply puts a Runnable onto the Executor 
service which when executed instantiates and injects the LogCall, and 
then invokes it. Voila, asynchronous side-effects.

With this pattern any extra configuration for the asynchronous part can 
be put into the annotation. For example, if the job should be posted to 
a JMS queue it could specify the name of it, or specify the name of a 
configuration where it is configured. If the job should be executed in a 
delayed manner it could specify the delay, etc. There's a lot of 
flexibility here since the annotation is essentially application code.

Whaddyathink? Does it make sense?

/Rickard


_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to