I have this code that allows to execute functions in a separate thread if “Asynch” annotation is present on them. Everything works fine, except for the day when I realized I also have to handle return value for some new functions that I’ve just added. I could use handlers and message-passing for this, but, due to already built project structure(which is huge and working fine), I can’t change the existing functions to work with message passing.
Here’s the code:
/**
* Defining the Asynch interface
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Asynch {}
/**
* Implementation of the Asynch interface. Every method in our controllers
* goes through this interceptor. If the Asynch annotation is present,
* this implementation invokes a new Thread to execute the method. Simple!
*/
public class AsynchInterceptor implements MethodInterceptor {
public Object invoke(final MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
if(declaredAnnotations != null && declaredAnnotations.length > 0) {
for (Annotation annotation : declaredAnnotations) {
if(annotation instanceof Asynch) {
//start the requested task in a new thread and immediately
//return back control to the caller
new Thread(invocation.getMethod().getName()) {
public void execute() {
invocation.proceed();
}
}.start();
return null;
}
}
}
return invocation.proceed();
}
}
Now, how can i convert it so that if its something as:
@Asynch
public MyClass getFeedback(int clientId){
}
MyClass mResult = getFeedback(12345);
“mResult” gets updated with the returned value?
Thanx in advance…
You can’t, fundamentally.
getFeedbackhas to return something in a synchronous way – and while in some cases you could update the returned object later on, in other cases you clearly couldn’t – immutable classes likeStringare obvious examples. You can’t change the value of the variablemResultlater… it’s quite possibly a local variable, after all. Indeed, by the time the result has been computed the method in which it was used may have completed… using a bogus value.You’re not going to be able to get clean asynchrony by just adding annotations on top of a synchronous language. Ideally, an asynchronous operation should return something like a
Future<T>to say “at some point later, there’ll be a result” – along with ways of finding out what that result is, whether it’s been computed or not, whether there was an exception etc. This sort of thing is precisely whyasync/awaitwas added in C# 5 – because you can’t just do it transparently at the library level, even with AOP. Writing asynchronous code should be a very deliberate decision – not just something which is bolted onto synchronous code via an annotation.