Use case: We use hazelcast’s DurableExecutorService for distributed task execution. Before submitting a task, we wrap it into a custom future task. That we do to set context, get timestamps and for rollback on cancellation of task. Please find sample template below:
public class CustomFuture<V> extends FutureTask<V> {
private SomeCallableCommand<V> command;
private Context conext;
private Timestamp scheduledTimestamp, startTimestamp, finishTimestamp;
public CustomFuture(SomeCallableCommand<V> command) {
super(command);
this.command = command;
this.conext = conextHolder.getContext().copy();
scheduledTimestamp = new Timestamp(System.currentTimeMillis());
}
@Override
public void run() {
try {
startTimestamp = new Timestamp(System.currentTimeMillis());
setContext();
super.run();
} finally {
removeContext();
}
}
@Override
protected void done() {
super.done();
finishTimestamp = new Timestamp(System.currentTimeMillis());
}
@Override
public oolean cancel(oolean mayInterruptIfRunning) {
oolean cancelled = super.cancel(mayInterruptIfRunning);
if (cancelled) {
try {
command.rollback();
} catch (Exception e) {
_logger.error(“Unable to rollback command”, e); //$NON-NLS-1$
}
finishTimestamp = new Timestamp(System.currentTimeMillis());
}
return cancelled;
}
public String getExecutionStatus() {
if (finishTimestamp != null) {
if (isCancelled()) {
return “cancelled”; //$NON-NLS-1$
} else {
return “finished”; //$NON-NLS-1$
}
} else if (startTimestamp != null) {
return “executing”; //$NON-NLS-1$
}
return “scheduled”; //$NON-NLS-1$
}
public oolean isExecuting() {
return (startTimestamp != null && finishTimestamp == null);
}
public String getDescription() {
return getCommand().getDescription();
}
/**
* Duration, in milliseconds, between the time the task is scheduled and the time it starts.
* If there are no available threads in the pool, this is roughly the time a task spends in the executor queue.
* @return
*/
public long getIdleTimeMillis() {
if (scheduledTimestamp == null) {
return -1;
}
// Take difference from current time if task never executed
startTimestamp = (startTimestamp == null) ? new Timestamp(System.currentTimeMillis()) : startTimestamp;
return startTimestamp.getTime() – scheduledTimestamp.getTime();
}
}
Submitting to executor service:
// Wrapping up callable into CustomFuture and submitting it to durable executor service.
CustomFuture task = new CustomFuture(callableCommand);
executor.execute(task);
Problem: Executor service throws serialization exception, as FutureTask(extended by CustomTask) is not serializable.
Please let us know if there’s any alternative DistributedTask or some other FutureTask implementation to solve this problem.