/**
*
*/
package de.tutorials;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author Thomas.Darimont
*
*/
public class TimeConstrainedMethodExecutionExample {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
IService service = (IService)Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), new Class[] { IService.class },
new TimeConstraintAwareInvocationHandler(new Service()));
System.out.println(service.operation("aaa"));
}
static interface IService {
@TimeConstrained(amount = 5, timeUnit = TimeUnit.SECONDS)
String operation(String arg);
}
static class Service implements IService {
public String operation(String arg) {
try {
TimeUnit.SECONDS.sleep((long)(10 * Math.random()));
} catch (InterruptedException e) {
e.printStackTrace();
}
return arg.toUpperCase();
}
}
static class TimeConstraintAwareInvocationHandler implements
InvocationHandler {
static ExecutorService executorService = Executors
.newCachedThreadPool();
Object invocationTarget;
public TimeConstraintAwareInvocationHandler(Object invocationTarget) {
this.invocationTarget = invocationTarget;
}
public Object invoke(final Object proxy, final Method method,
final Object[] args) throws Throwable {
if (method.isAnnotationPresent(TimeConstrained.class)) {
TimeConstrained timeConstraind = method
.getAnnotation(TimeConstrained.class);
try {
return executorService.submit(new Callable<Object>() {
public Object call() throws Exception {
return method.invoke(getInvocationTarget(), args);
}
}).get(timeConstraind.amount(), timeConstraind.timeUnit());
} catch (TimeoutException e) {
// Timeout occured
// e.printStackTrace();
return null;
}
}
return method.invoke(getInvocationTarget(), args);
}
/**
* @return the invocationTarget
*/
public Object getInvocationTarget() {
return invocationTarget;
}
/**
* @param invocationTarget
* the invocationTarget to set
*/
public void setInvocationTarget(Object invocationTarget) {
this.invocationTarget = invocationTarget;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
static @interface TimeConstrained {
TimeUnit timeUnit();
long amount();
}
}