package org.tessell.dispatch.server.servlet;
import javax.servlet.GenericServlet;
import org.tessell.dispatch.server.ActionDispatch;
import org.tessell.dispatch.server.ExecutionContext;
import org.tessell.dispatch.server.SessionIdValidator;
import org.tessell.dispatch.shared.Action;
import org.tessell.dispatch.shared.ActionException;
import org.tessell.dispatch.shared.DispatchService;
import org.tessell.dispatch.shared.Result;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* Provides a basic {@link DispatchService} implementation that defers to subclasses
* for the {@link SessionIdValidator} and {@link ActionDispatch} instances.
*/
public abstract class AbstractDispatchServiceServlet extends RemoteServiceServlet implements DispatchService {
private static final long serialVersionUID = 1L;
@Override
public Result execute(final String sessionId, final Action<?> action) throws ActionException {
ActionDispatch d = getActionDispatch();
if (d == null) {
throw new IllegalStateException("Null ActionDispatch, ensure the server started correctly");
}
try {
beginAction(action);
return d.execute(action, new ExecutionContext(getThreadLocalRequest(), getThreadLocalResponse(), sessionId));
} catch (final ActionException ae) {
// assume the user has already logged the ActionException appropriately
throw ae;
} catch (final Exception e) {
logActionFailure(e);
throw wrapInActionException(e);
} finally {
endAction(action);
}
}
/** Allows subclasses to override exception logging. By default uses {@link GenericServlet#log}. */
protected void logActionFailure(Exception e) {
log(e.getMessage(), e);
}
/** Allows subclasses to log/MDC at the start of action handling. */
protected void beginAction(Action<?> action) {
}
/** Allows subclasses to log/MDC at the end of action handling. */
protected void endAction(Action<?> action) {
}
/** Allows subclasses to create their own "runtime exception" subclass of {@link ActionException}. */
protected ActionException wrapInActionException(Exception e) {
return new ActionException("A server error occured."); // don't leak the raw exception message
}
/** Method for subclasses to return their {@link ActionDispatch} class. */
protected abstract ActionDispatch getActionDispatch();
}