Writing an asynchronous execution interceptor: not possible?

200 views
Skip to first unread message

Mario Scalas

unread,
Nov 15, 2009, 5:52:15 PM11/15/09
to google-guice
I'm using Guice in my Eclipse application. In my architecture the
controller calls View's methods in order to update it: Eclipse (based
on the SWT Eclipse toolkit) requires calls to be performed in the
single GUI thread and provides specific API (similar to the Swing
EventQueue.invokeLater()), which may not be the case when I perform
long jobs in the background in another thread.

So my idea to avoid boiler plate code is to wrap View methods with
@SWTThread annotation and let the interceptor do the job. In the past
I've already an AspectJ aspect that does the job but making it benefit
of Guice injection is a bit hard and I thought I could use the same
approach with an AOP Alliance method interceptor which, instead, is
supported by Guice. So I've written something like :

public class SWTThreadInterceptor implements MethodInterceptor {

@Inject
private Provider<Display> displayProvider;

@Override
public Object invoke( final MethodInvocation invocation ) throws
Throwable {
// If we are in the SWT Thread then avoid wrapping (otherwise the
interceptor will go in infinite
// recursive call)
Display display = displayProvider.get();

executeAsynch( display, invocation );
return null;
}

private void executeAsynch( Display display, final MethodInvocation
invocation ) {
display.asyncExec( new Runnable() {
public void run() {
try {
invocation.proceed();
} catch (Throwable e) {
throw new SWTThreadException( e );
}
}
});
}
}

My problem is that the invocation.proceed() method is invoked
recursively from within the UI thread! Anybody with more experience
may provide more insights? I guess that the proxied method is being
invoked again and again (instead of the actual class method, which is
invoked if I call invocation.proceed() directly) but don't know how to
access it (tried getThis() but had no luck).

Please help me! :)
Regards
Mario

Alen Vrečko

unread,
Nov 26, 2009, 6:04:18 AM11/26/09
to google-guice
Maybe you have already solved this. If not...This is what happens:

After the return null happens the invocation chain goes one step back
since there is no proceed call. The index-- happens[1]. Then the
thread invokes proceed but the index is at -1. It just calls invoke on
method interceptor again. This repeats and repeats...

The most simple solution is to manually increment the chain position
to compensate for the return null. In the thread do

Field field = methodInvocation.getClass().getDeclaredField("index");
field.setAccessible(true);
field.setInt(methodInvocation,field.getInt(methodInvocation)+1);

before calling proceed

I can think of one more solution with invokespecial but that is
another story.

Cheers
Alen

[1] http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/inject/internal/InterceptorStackCallback.java

Mario Scalas

unread,
Nov 26, 2009, 5:57:45 PM11/26/09
to google-guice
Hi Alen,
it works like a charm!

Thanks!
Mario

Ps: by the way, I reverted to use AspectJ load-time-weaving instead of
interceptors (but, of course, injection is ... troublesome in this
case): I'm glad to know that interceptors have become a viable
solution once again :)

On 26 Nov, 12:04, Alen Vrečko <alen_vre...@yahoo.com> wrote:
> Maybe you have already solved this. If not...This is what happens:
>
> After the return null happens the invocation chain goes one step back
> since there is no proceed call. The index-- happens[1]. Then the
> thread invokes proceed but the index is at -1. It just calls invoke on
> method interceptor again. This repeats and repeats...
>
> The most simple solution is to manually increment the chain position
> to compensate for the return null. In the thread do
>
> Field field = methodInvocation.getClass().getDeclaredField("index");
> field.setAccessible(true);
> field.setInt(methodInvocation,field.getInt(methodInvocation)+1);
>
> before calling proceed
>
> I can think of one more solution with invokespecial but that is
> another story.
>
> Cheers
> Alen
>
> [1]http://code.google.com/p/google-guice/source/browse/trunk/src/com/goo...
Reply all
Reply to author
Forward
0 new messages