Dispatch inside-out: actions can now be executed directly

This commit is contained in:
Papick Garcia Taboada committed 2015-04-08 15:50:37 +02:00
1 parent 60e373f579
commit ac0c8bfd22
14 files changed
+117 -251

No files matched your search

@@ -1,20 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch;
import java.lang.reflect.ParameterizedType;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
public abstract class AbstractHandler<R extends Result, A extends Action<R>> implements Handler<R, A> {
private Class<A> type;
@SuppressWarnings("unchecked")
protected AbstractHandler() {
type = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
@Override
public final Class<A> getType() {
return type;
}
}
@@ -1,19 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
import com.sap.sailing.server.RacingEventService;
public abstract class AbstractSailingHandler<R extends Result, A extends Action<R>> extends AbstractHandler<R, A> {
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
public AbstractSailingHandler(ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker) {
this.racingEventServiceTracker = racingEventServiceTracker;
}
public RacingEventService getService() {
return racingEventServiceTracker.getService();
}
}
@@ -1,11 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
public interface DispatchContext {
public <R extends Result, A extends Action<R>> R execute(A action) throws DispatchException;
}
@@ -1,95 +1,26 @@
package com.sap.sailing.gwt.ui.server.dispatch;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.gwt.ui.server.Activator;
import com.sap.sailing.gwt.ui.server.ProxiedRemoteServiceServlet;
import com.sap.sailing.gwt.ui.server.dispatch.handlers.BatchActionHandler;
import com.sap.sailing.gwt.ui.server.dispatch.handlers.GetLiveRacesActionHandler;
import com.sap.sailing.gwt.ui.server.dispatch.handlers.OtherActionHandler;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContextImpl;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
import com.sap.sailing.gwt.ui.shared.dispatch.rpc.DispatchRPC;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.util.ServiceTrackerFactory;
public class DispatchRPCImpl extends ProxiedRemoteServiceServlet implements DispatchRPC {
private static final long serialVersionUID = -245230476512348999L;
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
private final Map<Class<? extends Action<?>>, Handler<? extends Result, ? extends Action<?>>> handlers = new HashMap<>();
private final DispatchContext ctx;
public DispatchRPCImpl() {
BundleContext context = Activator.getDefault();
Activator activator = Activator.getInstance();
if (context != null) {
// TODO
// activator.setSailingService(this); // register so this service is informed when the bundle shuts down
}
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
addHandlers();
}
private void addHandlers() {
addHandler(new BatchActionHandler());
addHandler(new GetLiveRacesActionHandler(racingEventServiceTracker));
addHandler(new OtherActionHandler(racingEventServiceTracker));
}
private <R extends Result, A extends Action<R>> void addHandler(Handler<R, A> handler) {
Class<A> actionType = handler.getType();
if (handlers.containsKey(actionType)) {
String errorMessage = MessageFormat.format(
"A handler for Action {0} is already registered. Registered handler: {1}, new handler: {2}",
actionType.getName(), handlers.get(actionType).getClass().getName(), handler.getClass().getName());
throw new IllegalStateException(errorMessage);
}
handlers.put(actionType, handler);
ctx = new DispatchContextImpl();
}
@Override
public <R extends Result, A extends Action<R>> R execute(A action) throws DispatchException {
return execute(action, new DispatchContextImpl(getThreadLocalRequest(), getThreadLocalResponse()));
}
@SuppressWarnings({ "unchecked" })
public <R extends Result, A extends Action<R>> R execute(A action, DispatchContext context) throws DispatchException {
Class<A> actionType = (Class<A>) action.getClass();
Handler<R, A> handler = (Handler<R, A>) handlers.get(actionType);
if (handler != null) {
return handler.execute(action, context);
}
String errorMessage = MessageFormat.format("No handler found for Action {0}", actionType.getName());
throw new IllegalStateException(errorMessage);
}
private class DispatchContextImpl implements DispatchContext {
@SuppressWarnings("unused")
private final HttpServletRequest req;
@SuppressWarnings("unused")
private final HttpServletResponse resp;
public DispatchContextImpl(HttpServletRequest req, HttpServletResponse resp) {
this.req = req;
this.resp = resp;
}
public <R extends Result, A extends Action<R>> R execute(A action) throws DispatchException {
return DispatchRPCImpl.this.execute(action, this);
}
return action.execute(ctx);
}
}
@@ -1,10 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
public interface Handler<R extends Result, A extends Action<R>> {
Class<A> getType();
R execute(A action, DispatchContext context);
}
@@ -1,46 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch.handlers;
import java.util.ArrayList;
import com.sap.sailing.gwt.ui.server.dispatch.AbstractHandler;
import com.sap.sailing.gwt.ui.server.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.BatchAction;
import com.sap.sailing.gwt.ui.shared.dispatch.BatchResult;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException;
import com.sap.sailing.gwt.ui.shared.dispatch.Result;
public class BatchActionHandler extends AbstractHandler<BatchResult, BatchAction> {
@Override
public BatchResult execute(BatchAction action, DispatchContext context) throws DispatchException {
final int nrOfActions = action.getActions().length;
final ArrayList<Result> results = new ArrayList<Result>(nrOfActions);
final ArrayList<DispatchException> exceptions = new ArrayList<DispatchException>(nrOfActions);
for (Action<?> a : action.getActions()) {
final String actionName = a.getClass().getSimpleName();
// TODO LOG.trace("Found action {} in batch", actionName);
Result result = null;
try {
result = context.execute(a);
exceptions.add(null);
} catch (Throwable e) {
DispatchException e2 = this.handleException(e);
exceptions.add(e2);
}
results.add(result);
}
return new BatchResult(results, exceptions);
}
/**
* Throw exception to terminate Batch, return Exception to add to list
*
* @param e
* @return
*/
protected DispatchException handleException(Throwable e) {
return new DispatchException(e.getLocalizedMessage());
}
}
@@ -1,47 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch.handlers;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.gwt.ui.server.dispatch.AbstractSailingHandler;
import com.sap.sailing.gwt.ui.server.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRacesDTO;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class GetLiveRacesActionHandler extends AbstractSailingHandler<ResultWithTTL<LiveRacesDTO>, GetLiveRacesAction> {
public GetLiveRacesActionHandler(ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker) {
super(racingEventServiceTracker);
}
@Override
public ResultWithTTL<LiveRacesDTO> execute(GetLiveRacesAction action, DispatchContext context) {
MillisecondsTimePoint now = MillisecondsTimePoint.now();
LiveRacesDTO result = new LiveRacesDTO();
Event event = getService().getEvent(action.getEventId());
for (LeaderboardGroup lg : event.getLeaderboardGroups()) {
for (Leaderboard lb : lg.getLeaderboards()) {
// Regatta regatta = getService().getRegattaByName(lb.getName());
for (TrackedRace trackedRace : lb.getTrackedRaces()) {
// trackedRace.getMarks()
if(trackedRace.getStartOfRace().before(now) && trackedRace.getEndOfRace().after(now)) {
result.addRace(new LiveRaceDTO(trackedRace.getRace().getName()));
}
}
// for (RaceDefinition rd : regatta.getAllRaces()) {
// rd.
// }
}
}
return new ResultWithTTL<LiveRacesDTO>(5000, result);
}
}
@@ -1,23 +0,0 @@
package com.sap.sailing.gwt.ui.server.dispatch.handlers;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.gwt.ui.server.dispatch.AbstractSailingHandler;
import com.sap.sailing.gwt.ui.server.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL;
import com.sap.sailing.gwt.ui.shared.dispatch.event.OtherAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.OtherDTO;
import com.sap.sailing.server.RacingEventService;
public class OtherActionHandler extends AbstractSailingHandler<ResultWithTTL<OtherDTO>, OtherAction> {
public OtherActionHandler(ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker) {
super(racingEventServiceTracker);
}
@Override
public ResultWithTTL<OtherDTO> execute(OtherAction action, DispatchContext context) {
return new ResultWithTTL<>(3000, new OtherDTO());
}
}
@@ -1,7 +1,11 @@
package com.sap.sailing.gwt.ui.shared.dispatch;
import com.google.gwt.core.shared.GwtIncompatible;
import com.google.gwt.user.client.rpc.IsSerializable;
public interface Action<R extends Result> extends IsSerializable {
}
@GwtIncompatible
R execute(DispatchContext ctx) throws DispatchException;
}
@@ -1,5 +1,9 @@
package com.sap.sailing.gwt.ui.shared.dispatch;
import java.util.ArrayList;
import com.google.gwt.core.shared.GwtIncompatible;
public class BatchAction implements Action<BatchResult> {
private Action<?>[] actions;
@@ -14,4 +18,32 @@ public class BatchAction implements Action<BatchResult> {
public Action<?>[] getActions() {
return actions;
}
@Override
@GwtIncompatible
public BatchResult execute(DispatchContext ctx) throws DispatchException {
final int nrOfActions = getActions().length;
final ArrayList<Result> results = new ArrayList<Result>(nrOfActions);
final ArrayList<DispatchException> exceptions = new ArrayList<DispatchException>(nrOfActions);
for (Action<?> a : getActions()) {
final String actionName = a.getClass().getSimpleName();
// TODO LOG.trace("Found action {} in batch", actionName);
Result result = null;
try {
result = a.execute(ctx);
exceptions.add(null);
} catch (Throwable e) {
DispatchException e2 = handleException(e);
exceptions.add(e2);
}
results.add(result);
}
return new BatchResult(results, exceptions);
}
@GwtIncompatible
protected DispatchException handleException(Throwable e) {
return new DispatchException(e.getLocalizedMessage());
}
}
@@ -0,0 +1,10 @@
package com.sap.sailing.gwt.ui.shared.dispatch;
import com.google.gwt.thirdparty.guava.common.annotations.GwtCompatible;
import com.sap.sailing.server.RacingEventService;
@GwtCompatible
public interface DispatchContext {
RacingEventService getRacingEventService();
}
@@ -0,0 +1,26 @@
package com.sap.sailing.gwt.ui.shared.dispatch;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.gwt.ui.server.Activator;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.util.ServiceTrackerFactory;
public class DispatchContextImpl implements DispatchContext {
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
public DispatchContextImpl() {
final BundleContext context = Activator.getDefault();
final Activator activator = Activator.getInstance();
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
}
@Override
public RacingEventService getRacingEventService() {
return racingEventServiceTracker.getService();
}
}
@@ -2,8 +2,15 @@ package com.sap.sailing.gwt.ui.shared.dispatch.event;
import java.util.UUID;
import com.google.gwt.core.shared.GwtIncompatible;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class GetLiveRacesAction implements Action<ResultWithTTL<LiveRacesDTO>> {
@@ -19,4 +26,28 @@ public class GetLiveRacesAction implements Action<ResultWithTTL<LiveRacesDTO>> {
public UUID getEventId() {
return eventId;
}
@Override
@GwtIncompatible
public ResultWithTTL<LiveRacesDTO> execute(DispatchContext context) {
MillisecondsTimePoint now = MillisecondsTimePoint.now();
LiveRacesDTO result = new LiveRacesDTO();
Event event = context.getRacingEventService().getEvent(getEventId());
for (LeaderboardGroup lg : event.getLeaderboardGroups()) {
for (Leaderboard lb : lg.getLeaderboards()) {
// Regatta regatta = getService().getRegattaByName(lb.getName());
for (TrackedRace trackedRace : lb.getTrackedRaces()) {
// trackedRace.getMarks()
if (trackedRace.getStartOfRace().before(now) && trackedRace.getEndOfRace().after(now)) {
result.addRace(new LiveRaceDTO(trackedRace.getRace().getName()));
}
}
// for (RaceDefinition rd : regatta.getAllRaces()) {
// rd.
// }
}
}
return new ResultWithTTL<LiveRacesDTO>(5000, result);
}
}
@@ -1,8 +1,16 @@
package com.sap.sailing.gwt.ui.shared.dispatch.event;
import com.google.gwt.core.shared.GwtIncompatible;
import com.sap.sailing.gwt.ui.shared.dispatch.Action;
import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext;
import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL;
public class OtherAction implements Action<ResultWithTTL<OtherDTO>> {
@Override
@GwtIncompatible
public ResultWithTTL<OtherDTO> execute(DispatchContext context) {
return new ResultWithTTL<>(3000, new OtherDTO());
}
}