mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-28 14:57:12 +00:00
Minor refactorings
This commit is contained in:
1 parent
56dd5a9e81
commit
6aff2799c4
28 files changed
+282
-125
No files matched your search
+4
-5
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.dashboards.gwt.server;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -18,11 +17,11 @@ import com.sap.sailing.gwt.ui.server.ProxiedRemoteServiceServlet;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.ResultWrapper;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.ServerDispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.DispatchRPC;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.RequestWrapper;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.ResultWrapper;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class DashboardDispatchRPCServletImpl extends ProxiedRemoteServiceServlet implements DispatchRPC<DashboardDispatchContext> {
|
||||
@@ -56,9 +55,9 @@ public class DashboardDispatchRPCServletImpl extends ProxiedRemoteServiceServlet
|
||||
logger.log(Level.WARNING, "Server exception", d);
|
||||
throw d;
|
||||
} catch (Throwable t) {
|
||||
String serverExceptionUUID = UUID.randomUUID().toString();
|
||||
logger.log(Level.SEVERE, "Uncaught server exception id: " + serverExceptionUUID, t);
|
||||
throw new ServerDispatchException(serverExceptionUUID, t);
|
||||
ServerDispatchException dispatchException = new ServerDispatchException(t);
|
||||
logger.log(Level.SEVERE, "Uncaught server exception id: " + dispatchException.getExceptionId(), t);
|
||||
throw dispatchException;
|
||||
} finally {
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
final Level logLevel;
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import org.junit.Test;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.caching.CachingDispatch;
|
||||
@@ -263,7 +263,7 @@ public class CacheDispatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
private class DispatchMock implements DispatchAsync<DispatchContextMock> {
|
||||
private class DispatchMock implements DispatchSystemAsync<DispatchContextMock> {
|
||||
@Override
|
||||
public <R extends Result, A extends Action<R, DispatchContextMock>> void execute(A action,
|
||||
AsyncCallback<R> callback) throws DispatchException {
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.home.server.servlets;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -15,11 +14,11 @@ import com.sap.sailing.news.EventNewsService;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.ResultWrapper;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.ServerDispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.DispatchRPC;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.RequestWrapper;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.ResultWrapper;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class DispatchRPCServletImpl extends ProxiedRemoteServiceServlet implements DispatchRPC<SailingDispatchContext> {
|
||||
@@ -52,9 +51,9 @@ public class DispatchRPCServletImpl extends ProxiedRemoteServiceServlet implemen
|
||||
logger.log(Level.WARNING, "Server exception", d);
|
||||
throw d;
|
||||
} catch (Throwable t) {
|
||||
String serverExceptionUUID = UUID.randomUUID().toString();
|
||||
logger.log(Level.SEVERE, "Uncaught server exception id: " + serverExceptionUUID, t);
|
||||
throw new ServerDispatchException(serverExceptionUUID, t);
|
||||
ServerDispatchException dispatchException = new ServerDispatchException(t);
|
||||
logger.log(Level.SEVERE, "Uncaught server exception id: " + dispatchException.getExceptionId(), t);
|
||||
throw dispatchException;
|
||||
} finally {
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
final Level logLevel;
|
||||
|
||||
+7
-1
@@ -11,6 +11,8 @@ import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -51,6 +53,8 @@ import com.sap.sse.shared.media.MediaDescriptor;
|
||||
import com.sap.sse.shared.media.VideoDescriptor;
|
||||
|
||||
public final class HomeServiceUtil {
|
||||
private static final Logger logger = Logger.getLogger(HomeServiceUtil.class.getName());
|
||||
|
||||
public interface EventVisitor {
|
||||
void visit(EventBase event, boolean onRemoteServer, URL baseURL);
|
||||
}
|
||||
@@ -533,7 +537,9 @@ public final class HomeServiceUtil {
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), url.getPort(), /* file */"");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ServerDispatchException(e);
|
||||
ServerDispatchException dispatchException = new ServerDispatchException(e);
|
||||
logger.log(Level.SEVERE, "Uncaught server exception id: " + dispatchException.getExceptionId(), e);
|
||||
throw dispatchException;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,29 @@ package com.sap.sse.gwt.dispatch.client;
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.impl.DispatchSystem;
|
||||
|
||||
/**
|
||||
* Action interface that defines actions that can be sent to server using a {@link DispatchSystem}.
|
||||
*
|
||||
* The execute method will be executed on the server side and is therefore {@link GwtIncompatible}.
|
||||
*
|
||||
* The state defined in the action is the state that will be sent over the wire. Any method (other than execute, which
|
||||
* is GwtIncompatible) can be called both on the client and on the server side.
|
||||
*
|
||||
* @param <R>
|
||||
* @param <CTX>
|
||||
*/
|
||||
public interface Action<R extends Result, CTX extends DispatchContext> extends IsSerializable {
|
||||
|
||||
/**
|
||||
* Server side execution of the action. The execute method is GwtIncompatible and will be available only on the
|
||||
* server side.
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
* @throws DispatchException
|
||||
*/
|
||||
@GwtIncompatible
|
||||
R execute(CTX ctx) throws DispatchException;
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@ package com.sap.sse.gwt.dispatch.client;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Collection result that can be reused to send a collection of {@link DTO} instances
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface CollectionResult<T extends DTO> extends DTO, Result {
|
||||
Collection<T> getValues();
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.sap.sse.gwt.dispatch.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
|
||||
public interface DispatchAsync<CTX extends DispatchContext> {
|
||||
|
||||
<R extends Result, A extends Action<R, CTX>> void execute(A action, AsyncCallback<R> callback);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.sap.sse.gwt.dispatch.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
|
||||
/**
|
||||
* Async interface that defines the dispatch system contract.
|
||||
*
|
||||
* @param <CTX>
|
||||
*/
|
||||
public interface DispatchSystemAsync<CTX extends DispatchContext> {
|
||||
|
||||
/**
|
||||
* Send an action to be executed on the server.
|
||||
*
|
||||
* @param action
|
||||
* the action to be executed on the server
|
||||
*
|
||||
* @param callback
|
||||
* the callback that will called upon success or failure.
|
||||
*/
|
||||
<R extends Result, A extends Action<R, CTX>> void execute(A action, AsyncCallback<R> callback);
|
||||
|
||||
}
|
||||
@@ -2,6 +2,11 @@ package com.sap.sse.gwt.dispatch.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
/**
|
||||
* Result marker interface for the dispatch communication pattern.
|
||||
*
|
||||
* Results may be reused across different actions.
|
||||
*/
|
||||
public interface Result extends IsSerializable {
|
||||
|
||||
}
|
||||
@@ -4,6 +4,11 @@ import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.gwt.dispatch.client.caching.HasClientCacheTotalTimeToLive;
|
||||
|
||||
/**
|
||||
* Result implementation that holds a {@link DTO} with a defined time to live expiration.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class ResultWithTTL<T extends DTO> implements Result, HasClientCacheTotalTimeToLive {
|
||||
|
||||
/** max millis the result might be loaded earlier so we do batches **/
|
||||
|
||||
+7
-6
@@ -6,15 +6,15 @@ import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
|
||||
public class AutomaticBatchingDispatch<CTX extends DispatchContext> implements DispatchAsync<CTX> {
|
||||
public class AutomaticBatchingDispatch<CTX extends DispatchContext> implements DispatchSystemAsync<CTX> {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(AutomaticBatchingDispatch.class.getName());
|
||||
|
||||
private final DispatchAsync<CTX> executionContext;
|
||||
private final DispatchSystemAsync<CTX> executionContext;
|
||||
|
||||
private DispatchCallStack<CTX> currentCallstack;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class AutomaticBatchingDispatch<CTX extends DispatchContext> implements D
|
||||
* the underlying service implementation to use
|
||||
*
|
||||
*/
|
||||
public AutomaticBatchingDispatch(DispatchAsync<CTX> service) {
|
||||
public AutomaticBatchingDispatch(DispatchSystemAsync<CTX> service) {
|
||||
this(service, false);
|
||||
}
|
||||
|
||||
@@ -40,9 +40,10 @@ public class AutomaticBatchingDispatch<CTX extends DispatchContext> implements D
|
||||
*
|
||||
* @param service
|
||||
* the underlying service implementation to use
|
||||
*
|
||||
* @param processResultsScheduled
|
||||
* use a {@link Scheduler} to process the results
|
||||
*/
|
||||
public AutomaticBatchingDispatch(DispatchAsync<CTX> service, boolean processResultsScheduled) {
|
||||
public AutomaticBatchingDispatch(DispatchSystemAsync<CTX> service, boolean processResultsScheduled) {
|
||||
this.executionContext = service;
|
||||
this.processResultsScheduled = processResultsScheduled;
|
||||
}
|
||||
|
||||
@@ -10,20 +10,20 @@ import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
|
||||
public class BatchAction<CTX extends DispatchContext> implements Action<BatchResult, CTX> {
|
||||
public final class BatchAction<CTX extends DispatchContext> implements Action<BatchResult, CTX> {
|
||||
private static final Logger logger = Logger.getLogger(BatchAction.class.getName());
|
||||
private Action<?, CTX>[] actions;
|
||||
private ArrayList<Action<?, CTX>> actions = new ArrayList<Action<?, CTX>>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private BatchAction() {
|
||||
protected BatchAction() {
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public BatchAction(Action<?, CTX>... actions) {
|
||||
this.actions = actions;
|
||||
public BatchAction(ArrayList<Action<?, CTX>> actions) {
|
||||
if (actions != null) {
|
||||
this.actions.addAll(actions);
|
||||
}
|
||||
}
|
||||
|
||||
public Action<?, CTX>[] getActions() {
|
||||
public ArrayList<Action<?, CTX>> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class BatchAction<CTX extends DispatchContext> implements Action<BatchRes
|
||||
@GwtIncompatible
|
||||
public BatchResult execute(CTX ctx) throws DispatchException {
|
||||
|
||||
final int nrOfActions = getActions().length;
|
||||
final int nrOfActions = getActions().size();
|
||||
final ArrayList<Result> results = new ArrayList<Result>(nrOfActions);
|
||||
final ArrayList<DispatchException> exceptions = new ArrayList<DispatchException>(nrOfActions);
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package com.sap.sse.gwt.dispatch.client.batching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
|
||||
public class BatchResult implements Result {
|
||||
private LinkedList<Result> results = new LinkedList<Result>();
|
||||
public final class BatchResult implements Result {
|
||||
private ArrayList<Result> results = new ArrayList<>();
|
||||
private ArrayList<DispatchException> exceptions = new ArrayList<>();
|
||||
|
||||
private LinkedList<DispatchException> exceptions = new LinkedList<DispatchException>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private BatchResult() {
|
||||
protected BatchResult() {
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
public BatchResult(List<Result> results, List<DispatchException> exceptions) {
|
||||
this.results.addAll(results);
|
||||
this.exceptions.addAll(exceptions);
|
||||
@@ -37,9 +37,20 @@ public class BatchResult implements Result {
|
||||
return results.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the result at a given position only if it has the right type. Type safety is ensured by comparing class
|
||||
* name. We cannot use isAssignableFrom because this is GWT/ client code.
|
||||
*
|
||||
* @param i
|
||||
* result position
|
||||
* @param type
|
||||
* required result type
|
||||
* @return result at given position
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Result> T getResult(int i, Class<T> type) {
|
||||
Object result = results.get(i);
|
||||
|
||||
if (result != null && type.getName().equals(result.getClass().getName()))
|
||||
return (T) result;
|
||||
return null;
|
||||
|
||||
+21
-14
@@ -1,6 +1,6 @@
|
||||
package com.sap.sse.gwt.dispatch.client.batching;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
@@ -9,7 +9,7 @@ import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
|
||||
/**
|
||||
* Convenience class used to aggregate {@link Call} instances.
|
||||
* Convenience class used to aggregate {@link DispatchCall} instances.
|
||||
*
|
||||
* The class and all methods are private, its use is internal only.
|
||||
*
|
||||
@@ -19,7 +19,7 @@ public final class DispatchCallStack<CTX extends DispatchContext> {
|
||||
/**
|
||||
* The list containg all queued actions.
|
||||
*/
|
||||
private final LinkedList<DispatchCall<?, ?, CTX>> actionQueue = new LinkedList<DispatchCall<?, ?, CTX>>();
|
||||
private final ArrayList<DispatchCall<?, ?, CTX>> actionQueue = new ArrayList<DispatchCall<?, ?, CTX>>();
|
||||
|
||||
/**
|
||||
* The batch action holding the all the actions build in the queue. This instance variable is used to lazy
|
||||
@@ -30,7 +30,8 @@ public final class DispatchCallStack<CTX extends DispatchContext> {
|
||||
/**
|
||||
* Add a call to the queue. Can only be called as long as the batch action has not been accessed/ initialized.
|
||||
*
|
||||
* @param call
|
||||
* @param action
|
||||
* @param callback
|
||||
*/
|
||||
public <A extends Action<R, CTX>, R extends Result> void addCall(A action, AsyncCallback<R> callback) {
|
||||
assert (this.batchAction == null);
|
||||
@@ -38,16 +39,15 @@ public final class DispatchCallStack<CTX extends DispatchContext> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aggregated calls as {@link BatchAction} instance. The instance is lazy initialized.
|
||||
* Return the aggregated calls as {@link BatchAction} instance. The instance is initialized lazily.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BatchAction<CTX> getBatchAction() {
|
||||
if (this.batchAction == null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Action<?, CTX>[] actions = new Action[this.actionQueue.size()];
|
||||
for (int loop = 0; loop < actions.length; loop++) {
|
||||
actions[loop] = this.actionQueue.get(loop).getAction();
|
||||
ArrayList<Action<?, CTX>> actions = new ArrayList<Action<?, CTX>>();
|
||||
for (DispatchCall<?, ?, CTX> dispatchCall : this.actionQueue) {
|
||||
actions.add(dispatchCall.getAction());
|
||||
}
|
||||
this.batchAction = new BatchAction<CTX>(actions);
|
||||
}
|
||||
@@ -67,16 +67,16 @@ public final class DispatchCallStack<CTX extends DispatchContext> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process results for the callstack. TODO: check generics usage, get rid of supress warnings
|
||||
* Process results for the callstack.
|
||||
*
|
||||
* @param batchResult
|
||||
* @param processResultsScheduled
|
||||
* use a scheduler to execute the calls
|
||||
*/
|
||||
public void processResult(BatchResult batchResult, boolean processResultsScheduled) {
|
||||
assert (batchResult != null);
|
||||
|
||||
int loop = 0;
|
||||
for (@SuppressWarnings("rawtypes")
|
||||
DispatchCall call : this.actionQueue) {
|
||||
for (DispatchCall<?, ?, CTX> call : this.actionQueue) {
|
||||
Result result = batchResult.getResult(loop);
|
||||
Throwable exception = batchResult.getException(loop);
|
||||
|
||||
@@ -90,17 +90,24 @@ public final class DispatchCallStack<CTX extends DispatchContext> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
|
||||
/**
|
||||
* Scheduled command wrapping the callback method call.
|
||||
*/
|
||||
private class CallbackCommand implements ScheduledCommand {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final DispatchCall call;
|
||||
private final Result result;
|
||||
private final Throwable exception;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public CallbackCommand(DispatchCall call, Result result, Throwable exception) {
|
||||
this.call = call;
|
||||
this.result = result;
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void execute() {
|
||||
if (hasFailed()) {
|
||||
|
||||
+3
@@ -1,5 +1,8 @@
|
||||
package com.sap.sse.gwt.dispatch.client.batching;
|
||||
|
||||
/**
|
||||
* Marker interface to identify actions that must not be batched
|
||||
*/
|
||||
public interface NonBatchableAction {
|
||||
|
||||
}
|
||||
+14
-3
@@ -8,6 +8,9 @@ import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
|
||||
/**
|
||||
* Convenience to enqueue and execute ScheduledCommands using the GWT scheduler.
|
||||
*/
|
||||
public class SplitScheduler {
|
||||
|
||||
private static final SplitScheduler INSTANCE = new SplitScheduler();
|
||||
@@ -16,6 +19,12 @@ public class SplitScheduler {
|
||||
|
||||
private boolean scheduled = false;
|
||||
|
||||
private SplitScheduler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeating command instance that picks up the next element in the queue of pending commands and executes it.
|
||||
*/
|
||||
private final RepeatingCommand repeatingCommand = new RepeatingCommand() {
|
||||
@Override
|
||||
public boolean execute() {
|
||||
@@ -33,13 +42,15 @@ public class SplitScheduler {
|
||||
}
|
||||
};
|
||||
|
||||
private SplitScheduler() {
|
||||
}
|
||||
|
||||
public static SplitScheduler get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a command to the queue and executes it using the gwt scheduler.
|
||||
*
|
||||
* @param command
|
||||
*/
|
||||
public void schedule(ScheduledCommand command) {
|
||||
pendingCommands.add(command);
|
||||
|
||||
|
||||
+46
-26
@@ -8,29 +8,42 @@ import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
|
||||
/**
|
||||
* Delegating dispatch implementation that caches results if actions implement IsClientCache interface.
|
||||
*
|
||||
* @author pgtaboada
|
||||
*/
|
||||
public final class CachingDispatch<CTX extends DispatchContext> implements DispatchAsync<CTX> {
|
||||
|
||||
public final class CachingDispatch<CTX extends DispatchContext> implements DispatchSystemAsync<CTX> {
|
||||
private static final Logger LOG = Logger.getLogger(CachingDispatch.class.getName());
|
||||
|
||||
private final CacheCleanupTask invalidationTask;
|
||||
private final HashMap<String, ResultHolder> resultsCache = new HashMap<>();
|
||||
private final DispatchAsync<CTX> dispatch;
|
||||
private final DispatchSystemAsync<CTX> dispatch;
|
||||
private final int defaultTimeToLive;
|
||||
|
||||
public CachingDispatch(DispatchAsync<CTX> service) {
|
||||
/**
|
||||
* Create new caching dispatch instance with default values.
|
||||
*
|
||||
* @param service
|
||||
* the underlying service used to make dispatch calls
|
||||
*/
|
||||
public CachingDispatch(DispatchSystemAsync<CTX> service) {
|
||||
this(service, true, (int) Duration.ONE_MINUTE.times(3).asMillis());
|
||||
}
|
||||
|
||||
public CachingDispatch(DispatchAsync<CTX> service, boolean enableCleanup, int defaultTimeToLive) {
|
||||
/**
|
||||
* Create new caching dispatch instance with given parameters
|
||||
*
|
||||
* @param service
|
||||
* the underlying service used to make dispatch calls
|
||||
* @param enableCleanup
|
||||
* enable cleanup cached elements
|
||||
* @param defaultTimeToLive
|
||||
* default cached element time to live
|
||||
*/
|
||||
public CachingDispatch(DispatchSystemAsync<CTX> service, boolean enableCleanup, int defaultTimeToLive) {
|
||||
this.dispatch = service;
|
||||
this.defaultTimeToLive = defaultTimeToLive;
|
||||
if (enableCleanup) {
|
||||
@@ -60,21 +73,23 @@ public final class CachingDispatch<CTX extends DispatchContext> implements Dispa
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform dispatch call with intercepting callback.
|
||||
* Perform dispatch call with using an intercepting callback for client cacheable commands.
|
||||
*
|
||||
* @param action
|
||||
* @param callback
|
||||
*/
|
||||
private <R extends Result, A extends Action<R, CTX>> void executeAndCache(final A action,
|
||||
final AsyncCallback<R> callback) {
|
||||
if (action instanceof IsClientCacheable) {
|
||||
dispatch.execute(action, new InterceptingCallback<>(action, callback));
|
||||
} else {
|
||||
dispatch.execute(action, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepting callback that stores the result into cache.
|
||||
*
|
||||
* @author pgtaboada
|
||||
*
|
||||
* @param <R>
|
||||
* @param <A>
|
||||
*/
|
||||
@@ -89,26 +104,35 @@ public final class CachingDispatch<CTX extends DispatchContext> implements Dispa
|
||||
|
||||
@Override
|
||||
public void onSuccess(R result) {
|
||||
if (action instanceof IsClientCacheable) {
|
||||
final IsClientCacheable clientCacheableAction = (IsClientCacheable) action;
|
||||
final String instanceKey = key(clientCacheableAction);
|
||||
int cacheTotalTimeToLiveMillis = timeToLive(action, result);
|
||||
resultsCache.put(instanceKey, new ResultHolder(System.currentTimeMillis() + cacheTotalTimeToLiveMillis,
|
||||
result));
|
||||
LOG.finest("Added " + instanceKey + " to cache, ttl: " + cacheTotalTimeToLiveMillis + "ms");
|
||||
if (invalidationTask != null && !invalidationTask.isRunning()) {
|
||||
LOG.finest("Schedule cache cleanup");
|
||||
invalidationTask.schedule((int) Duration.ONE_MINUTE.times(5).asMillis());
|
||||
}
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate time to live fore result
|
||||
*
|
||||
* @param action
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
private int timeToLive(A action, R result) {
|
||||
int cacheTotalTimeToLiveMillis = defaultTimeToLive;
|
||||
if (result instanceof HasClientCacheTotalTimeToLive) {
|
||||
cacheTotalTimeToLiveMillis = ((HasClientCacheTotalTimeToLive) result).cacheTotalTimeToLiveMillis();
|
||||
} else if (action instanceof HasClientCacheTotalTimeToLive) {
|
||||
cacheTotalTimeToLiveMillis = ((HasClientCacheTotalTimeToLive) action).cacheTotalTimeToLiveMillis();
|
||||
}
|
||||
resultsCache.put(instanceKey, new ResultHolder(System.currentTimeMillis()
|
||||
+ cacheTotalTimeToLiveMillis, result));
|
||||
LOG.finest("Added " + instanceKey + " to cache, ttl: " + cacheTotalTimeToLiveMillis + "ms");
|
||||
if (invalidationTask != null && !invalidationTask.isRunning()) {
|
||||
LOG.finest("Schedule cache cleanup");
|
||||
invalidationTask.schedule((int) Duration.ONE_MINUTE.times(5).asMillis());
|
||||
return cacheTotalTimeToLiveMillis;
|
||||
}
|
||||
}
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
callback.onFailure(caught);
|
||||
@@ -130,8 +154,6 @@ public final class CachingDispatch<CTX extends DispatchContext> implements Dispa
|
||||
/**
|
||||
* Holder class used to store results in cache.
|
||||
*
|
||||
* @author pgtaboada
|
||||
*
|
||||
*/
|
||||
private static class ResultHolder {
|
||||
final Result payload;
|
||||
@@ -168,8 +190,6 @@ public final class CachingDispatch<CTX extends DispatchContext> implements Dispa
|
||||
/**
|
||||
* Removes due elements from resultscache.
|
||||
*
|
||||
* @author pgtaboada
|
||||
*
|
||||
*/
|
||||
private class CacheCleanupTask extends Timer {
|
||||
@Override
|
||||
|
||||
+1
-3
@@ -1,9 +1,7 @@
|
||||
package com.sap.sse.gwt.dispatch.client.caching;
|
||||
|
||||
/**
|
||||
* Interface used by actions and results to override default cache time to live.
|
||||
*
|
||||
* @author pgtaboada
|
||||
* Interface used by actions and results to provide cache time to live.
|
||||
*
|
||||
*/
|
||||
public interface HasClientCacheTotalTimeToLive {
|
||||
|
||||
+3
-2
@@ -3,13 +3,14 @@ package com.sap.sse.gwt.dispatch.client.caching;
|
||||
/**
|
||||
* Cache interface used by the caching dispatch to identify which command can be cached on client side.
|
||||
*
|
||||
* @author pgtaboada
|
||||
* Each command must provide an instance key used to store the results in the cache.
|
||||
*
|
||||
* The instance key is appended to an class identifying key.
|
||||
*/
|
||||
public interface IsClientCacheable {
|
||||
|
||||
/**
|
||||
* The instance specific key used to identify instance specific results in the cache.
|
||||
* The builder used to identify instance specific results in the cache.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
+10
-1
@@ -1,16 +1,25 @@
|
||||
package com.sap.sse.gwt.dispatch.client.exceptions;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class DispatchException extends RuntimeException implements IsSerializable {
|
||||
|
||||
private static final long serialVersionUID = 8192187255698006941L;
|
||||
private String exceptionId;
|
||||
|
||||
protected DispatchException() {
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
public DispatchException(String message) {
|
||||
super(message);
|
||||
exceptionId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public String getExceptionId() {
|
||||
return exceptionId;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-13
@@ -1,28 +1,17 @@
|
||||
package com.sap.sse.gwt.dispatch.client.exceptions;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
|
||||
public class ServerDispatchException extends DispatchException {
|
||||
|
||||
private static final long serialVersionUID = 8192187255698006941L;
|
||||
private String uuid;
|
||||
|
||||
protected ServerDispatchException() {
|
||||
}
|
||||
|
||||
public ServerDispatchException(String uuid, Throwable cause) {
|
||||
super(cause.getMessage());
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@GwtIncompatible
|
||||
public ServerDispatchException(Throwable cause) {
|
||||
super(cause.getMessage());
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,15 @@ package com.sap.sse.gwt.dispatch.client.impl;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
|
||||
public interface DispatchSystem<CTX extends DispatchContext> extends DispatchAsync<CTX> {
|
||||
/**
|
||||
* The dispatch system is the client side implementation of the dispatch communication pattern.
|
||||
*
|
||||
* @param <CTX>
|
||||
* the context that will be provided to the actions during execution
|
||||
*/
|
||||
public interface DispatchSystem<CTX extends DispatchContext> extends DispatchSystemAsync<CTX> {
|
||||
Date getCurrentServerTime();
|
||||
}
|
||||
+29
-10
@@ -1,43 +1,62 @@
|
||||
package com.sap.sse.gwt.dispatch.client.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.gwt.core.shared.GWT;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.batching.AutomaticBatchingDispatch;
|
||||
import com.sap.sse.gwt.dispatch.client.caching.CachingDispatch;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.ServerDispatchException;
|
||||
import com.sap.sse.gwt.dispatch.client.rpcimpl.SimpleDispatch;
|
||||
|
||||
public class DispatchSystemImpl<CTX extends DispatchContext> implements DispatchSystem<CTX> {
|
||||
|
||||
/**
|
||||
* Base implementation of a client side dispatch executor.
|
||||
*
|
||||
* The dispatch system implements caching {@link CachingDispatch} and automatic batching
|
||||
* {@link AutomaticBatchingDispatch}.
|
||||
*
|
||||
* @param <CTX>
|
||||
*/
|
||||
public abstract class DispatchSystemImpl<CTX extends DispatchContext> implements DispatchSystem<CTX> {
|
||||
private final Logger LOG = Logger.getLogger(DispatchSystemImpl.class.getName());
|
||||
private final SimpleDispatch<CTX> simpleDispatch;
|
||||
private final DispatchAsync<CTX> dispatch;
|
||||
private final DispatchSystemAsync<CTX> dispatch;
|
||||
|
||||
public DispatchSystemImpl(String dispatchRPCPath) {
|
||||
this(dispatchRPCPath, false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Create a dispatch system
|
||||
*
|
||||
* @param dispatchRPCPath
|
||||
* rpc-servlet path
|
||||
* @param processResultsScheduled
|
||||
* use a {@link Scheduler} to process the results
|
||||
*/
|
||||
public DispatchSystemImpl(String dispatchRPCPath, boolean processResultsScheduled) {
|
||||
simpleDispatch = new SimpleDispatch<CTX>(dispatchRPCPath);
|
||||
dispatch = new CachingDispatch<CTX>(new AutomaticBatchingDispatch<CTX>(
|
||||
simpleDispatch, processResultsScheduled));
|
||||
LOG.finest("Started dispatch system for " + dispatchRPCPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends Result, A extends Action<R, CTX>> void execute(final A action, final AsyncCallback<R> callback) {
|
||||
// TODO: client side execution time logging
|
||||
AsyncCallback<R> wrappedCallback = new AsyncCallback<R>() {
|
||||
final AsyncCallback<R> wrappedCallback = new AsyncCallback<R>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
if (caught instanceof ServerDispatchException) {
|
||||
if (caught instanceof DispatchException) {
|
||||
ServerDispatchException sde = (ServerDispatchException) caught;
|
||||
// TODO: browser console log
|
||||
GWT.log("Server exception with id: " + sde.getUuid());
|
||||
LOG.log(Level.SEVERE, "Server exception with id: " + sde.getExceptionId());
|
||||
}
|
||||
callback.onFailure(caught);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,13 @@ import com.google.gwt.user.client.rpc.RemoteService;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.ResultWrapper;
|
||||
import com.sap.sse.gwt.dispatch.client.exceptions.DispatchException;
|
||||
|
||||
/**
|
||||
* GWT RPC interfaces for dispatch communication
|
||||
*
|
||||
* @param <CTX>
|
||||
*/
|
||||
public interface DispatchRPC<CTX extends DispatchContext> extends RemoteService {
|
||||
|
||||
<R extends Result, A extends Action<R, CTX>> ResultWrapper<R> execute(
|
||||
|
||||
+5
-1
@@ -4,8 +4,12 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.ResultWrapper;
|
||||
|
||||
/**
|
||||
* Async interface
|
||||
*
|
||||
* @param <CTX>
|
||||
*/
|
||||
public interface DispatchRPCAsync<CTX extends DispatchContext> {
|
||||
|
||||
<R extends Result, A extends Action<R, CTX>> void execute(
|
||||
|
||||
@@ -7,6 +7,16 @@ import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
|
||||
/**
|
||||
* Wrapper that encapsulates an action to be sent to the server.
|
||||
*
|
||||
* @param <A>
|
||||
* Action
|
||||
* @param <R>
|
||||
* Result
|
||||
* @param <CTX>
|
||||
* Execution context
|
||||
*/
|
||||
public class RequestWrapper<R extends Result, A extends Action<R, CTX>, CTX extends DispatchContext> implements
|
||||
IsSerializable {
|
||||
|
||||
|
||||
+7
-1
@@ -1,9 +1,15 @@
|
||||
package com.sap.sse.gwt.dispatch.client;
|
||||
package com.sap.sse.gwt.dispatch.client.rpcimpl;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
|
||||
/**
|
||||
* Result wrapper that encapsulates the curent server time.
|
||||
*
|
||||
* @param <R>
|
||||
*/
|
||||
public class ResultWrapper<R extends Result> implements IsSerializable {
|
||||
|
||||
private Date currentServerTime = new Date();
|
||||
+9
-4
@@ -5,12 +5,16 @@ import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||
import com.sap.sse.gwt.dispatch.client.Action;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchSystemAsync;
|
||||
import com.sap.sse.gwt.dispatch.client.DispatchContext;
|
||||
import com.sap.sse.gwt.dispatch.client.Result;
|
||||
import com.sap.sse.gwt.dispatch.client.ResultWrapper;
|
||||
|
||||
public class SimpleDispatch<CTX extends DispatchContext> implements DispatchAsync<CTX> {
|
||||
/**
|
||||
* Simple dispatch implementation that uses GWT RPC internally to communicate with the server
|
||||
*
|
||||
* @param <CTX>
|
||||
*/
|
||||
public class SimpleDispatch<CTX extends DispatchContext> implements DispatchSystemAsync<CTX> {
|
||||
|
||||
private final DispatchRPCAsync<CTX> dispatchRPC = GWT.create(DispatchRPC.class);
|
||||
|
||||
@@ -22,7 +26,8 @@ public class SimpleDispatch<CTX extends DispatchContext> implements DispatchAsyn
|
||||
|
||||
@Override
|
||||
public <R extends Result, A extends Action<R, CTX>> void execute(A action, final AsyncCallback<R> callback) {
|
||||
RequestWrapper<R, A, CTX> requestWrapper = new RequestWrapper<R, A, CTX>(action, LocaleInfo.getCurrentLocale()
|
||||
final RequestWrapper<R, A, CTX> requestWrapper = new RequestWrapper<R, A, CTX>(action, LocaleInfo
|
||||
.getCurrentLocale()
|
||||
.getLocaleName());
|
||||
final long clientTimeOnRequestStart = System.currentTimeMillis();
|
||||
dispatchRPC.execute(requestWrapper, new AsyncCallback<ResultWrapper<R>>() {
|
||||
|
||||
Reference in new issue
Block a user