use of org.eclipse.scout.rt.platform.util.concurrent.IRunnable in project scout.rt by eclipse.
the class AbstractSmartField2 method fetchLookupRows.
/**
* Loads lookup rows according to the specified {@link ILookupRowProvider}, and notifies the specified callback upon
* fetching completed.
*
* @return {@link IFuture} if data is fetched asynchronously, or <code>null</code> for synchronous fetching, or if
* using {@link LocalLookupCall}.
*/
private IFuture<Void> fetchLookupRows(final ILookupRowProvider<VALUE> dataProvider, final ILookupRowFetchedCallback<VALUE> callback, final boolean asynchronousFetching, final int maxRowCount) {
cancelPotentialLookup();
if (getLookupCall() == null) {
callback.onSuccess(Collections.<ILookupRow<VALUE>>emptyList());
return null;
}
// Prepare the lookup call.
final ILookupCall<VALUE> lookupCall = cloneLookupCall();
lookupCall.setMaxRowCount(maxRowCount > 0 ? maxRowCount : getBrowseMaxRowCount());
// Prepare processing of the fetched rows.
final ILookupRowFetchedCallback<VALUE> internalCallback = new ILookupRowFetchedCallback<VALUE>() {
@Override
public void onSuccess(final List<? extends ILookupRow<VALUE>> rows) {
joinModelThreadAndUpdateField(rows, null);
}
@Override
public void onFailure(final RuntimeException e) {
joinModelThreadAndUpdateField(null, e);
}
private void joinModelThreadAndUpdateField(final List<? extends ILookupRow<VALUE>> rows, final RuntimeException exception) {
if (ModelJobs.isModelThread()) {
updateField(rows, exception);
} else {
// Note: The model job will not commence execution if the current ClientRunContext is or gets cancelled.
try {
ClientRunContext callerRunContext = ClientRunContexts.copyCurrent();
if (callerRunContext.getRunMonitor().isCancelled()) {
return;
}
ModelJobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
updateField(rows, exception);
}
}, ModelJobs.newInput(callerRunContext).withName("Updating {}", AbstractSmartField2.this.getClass().getName())).awaitDone();
} catch (ThreadInterruptedError e) {
/*
This state can be reached by a race condition when the job's RunMonitor is in canceled state and later the ModelJob is run.
This yields to a Thread.interrupt in the RunContext.ThreadInterrupter...
at RunContext$ThreadInterrupter.cancel(boolean) line: 563
at RunMonitor.cancel(ICancellable, boolean) line: 160
at RunMonitor.registerCancellable(ICancellable) line: 104 <---------------------
at RunContext$ThreadInterrupter.<init>(Thread, RunMonitor) line: 545
at ClientRunContext(RunContext).call(Callable<RESULT>, Class<IExceptionTranslator<EXCEPTION>>) line: 154
at RunContextRunner<RESULT>.intercept(Chain<RESULT>) line: 38
which itself causes the running job to be interrupted with a InterruptedException
at org.eclipse.scout.rt.platform.job.internal.JobExceptionTranslator.translateInterruptedException(JobExceptionTranslator.java:49)
at org.eclipse.scout.rt.platform.job.internal.JobFutureTask.awaitDone(JobFutureTask.java:339)
at org.eclipse.scout.rt.client.ui.form.fields.smartfield2.AbstractSmartField2$7.joinModelThreadAndUpdateField(AbstractSmartField2.java:1598)
at org.eclipse.scout.rt.client.ui.form.fields.smartfield2.AbstractSmartField2$7.onSuccess(AbstractSmartField2.java:1575)
at org.eclipse.scout.rt.shared.services.lookup.LookupCall.loadData(LookupCall.java:437)
at org.eclipse.scout.rt.shared.services.lookup.LookupCall$5.run(LookupCall.java:417)
*/
return;
}
}
}
private void updateField(final List<? extends ILookupRow<VALUE>> rows, final RuntimeException exception) {
try {
if (exception != null) {
// throw to handle exception at the end.
throw exception;
}
final List<ILookupRow<VALUE>> result = new ArrayList<>(rows);
dataProvider.afterProvide(lookupCall, result);
callback.onSuccess(result);
} catch (FutureCancelledError | ThreadInterruptedError e) {
// NOSONAR
callback.onSuccess(Collections.<ILookupRow<VALUE>>emptyList());
} catch (final RuntimeException e) {
callback.onFailure(e);
}
}
};
// Start fetching lookup rows.
IFuture<Void> asyncLookupFuture = null;
try {
dataProvider.beforeProvide(lookupCall);
if (asynchronousFetching) {
asyncLookupFuture = dataProvider.provideAsync(lookupCall, internalCallback, ClientRunContexts.copyCurrent());
} else {
dataProvider.provideSync(lookupCall, internalCallback);
asyncLookupFuture = null;
}
} catch (final RuntimeException e) {
internalCallback.onFailure(e);
asyncLookupFuture = null;
}
m_lookupFuture = asyncLookupFuture;
return asyncLookupFuture;
}
use of org.eclipse.scout.rt.platform.util.concurrent.IRunnable in project scout.rt by eclipse.
the class HealthCheckerTest method testTimeToLive.
@Test
public void testTimeToLive() throws Exception {
IRunnable test = mock(IRunnable.class);
AbstractHealthChecker checker = createDummyHealthChecker(true, TimeUnit.SECONDS.toMillis(1), 0, test);
// start & validate first run
checker.checkHealth(RunContexts.empty());
awaitDone(checker.getFuture());
verify(test, times(1)).run();
assertEquals("result", true, checker.checkHealth(RunContexts.empty()));
// spam checking
for (int i = 0; i < 10; i++) {
assertEquals("resultX" + i, true, checker.checkHealth(RunContexts.empty()));
}
// validate executions again
verify(test, times(1)).run();
// wait for TTL to expire
TimeUnit.SECONDS.sleep(1);
// start and validate again
checker.checkHealth(RunContexts.empty());
awaitDone(checker.getFuture());
verify(test, times(2)).run();
assertEquals("resultZ", true, checker.checkHealth(RunContexts.empty()));
}
use of org.eclipse.scout.rt.platform.util.concurrent.IRunnable in project scout.rt by eclipse.
the class HealthCheckerTest method testTimeout.
@Test
public void testTimeout() throws Exception {
final AtomicBoolean sleep = new AtomicBoolean(false);
AbstractHealthChecker checker = createDummyHealthChecker(true, 0, TimeUnit.SECONDS.toMillis(1), new IRunnable() {
@Override
public void run() throws Exception {
if (sleep.get()) {
TimeUnit.SECONDS.sleep(10);
}
}
});
// run without sleep
assertEquals("resultInitial", false, checker.checkHealth(RunContexts.empty()));
awaitDone(checker.getFuture());
// run with sleep
sleep.set(true);
assertEquals("resultT", true, checker.checkHealth(RunContexts.empty()));
// wait for timeout
TimeUnit.SECONDS.sleep(2);
// fails due to timeout
assertEquals("resultF", false, checker.checkHealth(RunContexts.empty()));
}
use of org.eclipse.scout.rt.platform.util.concurrent.IRunnable in project scout.rt by eclipse.
the class HealthCheckerTest method testAsync.
@Test
public void testAsync() throws Exception {
final AtomicBoolean flag = new AtomicBoolean(false);
final Object sync = new Object();
IHealthChecker checker = createDummyHealthChecker(true, TimeUnit.DAYS.toMillis(1), 1, new IRunnable() {
@Override
public void run() throws Exception {
synchronized (sync) {
flag.set(true);
sync.notify();
sync.wait();
flag.set(false);
sync.notify();
}
}
});
// ping-pong synchronization: main(checkHealth) -> checker(flag=true) -> main(assertEquals) -> checker(flag=false) -> main(assertEquals)
synchronized (sync) {
checker.checkHealth(RunContexts.empty());
sync.wait();
assertEquals("flag check 1", true, flag.get());
sync.notify();
sync.wait();
assertEquals("flag check 2", false, flag.get());
}
}
use of org.eclipse.scout.rt.platform.util.concurrent.IRunnable in project scout.rt by eclipse.
the class UploadRequestHandler method handlePost.
@Override
public boolean handlePost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
// serve only /upload
String pathInfo = req.getPathInfo();
Matcher matcher = PATTERN_UPLOAD_ADAPTER_RESOURCE_PATH.matcher(pathInfo);
if (!matcher.matches()) {
return false;
}
final String uiSessionId = matcher.group(1);
final String targetAdapterId = matcher.group(2);
// Check if is really a file upload
if (!ServletFileUpload.isMultipartContent(req)) {
return false;
}
final long startNanos = System.nanoTime();
if (LOG.isDebugEnabled()) {
LOG.debug("File upload started");
}
// disable caching
m_httpCacheControl.checkAndSetCacheHeaders(req, resp, null);
try {
// Get and validate existing UI session
final IUiSession uiSession = UiSession.get(req, uiSessionId);
if (uiSession == null) {
throw new IllegalStateException("Could not resolve UI session with ID " + uiSessionId);
}
// Touch the session
uiSession.touch();
// Associate subsequent processing with the uiSession.
RunContexts.copyCurrent().withThreadLocal(IUiSession.CURRENT, uiSession).withDiagnostics(BEANS.all(IUiRunContextDiagnostics.class)).run(new IRunnable() {
@Override
public void run() throws Exception {
handleUploadFileRequest(IUiSession.CURRENT.get(), req, resp, targetAdapterId);
}
}, DefaultExceptionTranslator.class);
} catch (Exception e) {
LOG.error("Unexpected error while handling multipart upload request", e);
writeJsonResponse(resp, m_jsonRequestHelper.createUnrecoverableFailureResponse());
} finally {
if (LOG.isDebugEnabled()) {
LOG.debug("File upload completed in {} ms", StringUtility.formatNanos(System.nanoTime() - startNanos));
}
}
return true;
}
Aggregations