Search in sources :

Example 6 with ClientRunContext

use of org.eclipse.scout.rt.client.context.ClientRunContext in project scout.rt by eclipse.

the class ClientJobCancelTest method doPingRequestAsync.

/**
 * Runs a 'ping-request' which gets blocked in the service implementation.
 */
protected RequestData doPingRequestAsync(final String pingRequest) throws Exception {
    final BlockingCountDownLatch serviceCallSetupLatch = new BlockingCountDownLatch(1);
    final BlockingCountDownLatch serviceCallCompletedLatch = new BlockingCountDownLatch(1);
    final AtomicBoolean serviceCallInterrupted = new AtomicBoolean(false);
    // Mock the PingService.
    class PingService implements IPingService {

        @Override
        public String ping(String s) {
            try {
                assertTrue(serviceCallSetupLatch.countDownAndBlock());
            } catch (java.lang.InterruptedException e) {
                serviceCallInterrupted.set(true);
            } finally {
                serviceCallCompletedLatch.countDown();
            }
            return s.toUpperCase();
        }
    }
    // Create a separate RunContext with a separate RunMonitor, so we can wait for the service result in case of cancellation.
    final ClientRunContext runContext = ClientRunContexts.copyCurrent();
    final RunMonitor runMonitor = BEANS.get(RunMonitor.class);
    runContext.withRunMonitor(runMonitor);
    IFuture<String> pingFuture = Jobs.schedule(new Callable<String>() {

        @Override
        public String call() throws Exception {
            return runContext.call(new Callable<String>() {

                @Override
                public String call() throws Exception {
                    IBean<?> bean = TestingUtility.registerBean(new BeanMetaData(PingService.class).withInitialInstance(new PingService()).withApplicationScoped(true));
                    try {
                        return ServiceTunnelUtility.createProxy(IPingService.class).ping(pingRequest);
                    } finally {
                        TestingUtility.unregisterBeans(Arrays.asList(bean));
                    }
                }
            });
        }
    }, Jobs.newInput().withExceptionHandling(null, false));
    // Wait for the ping request to enter service implementation.
    assertTrue(serviceCallSetupLatch.await());
    return new RequestData(pingFuture, runMonitor, serviceCallSetupLatch, serviceCallCompletedLatch, serviceCallInterrupted);
}
Also used : BlockingCountDownLatch(org.eclipse.scout.rt.testing.platform.util.BlockingCountDownLatch) BeanMetaData(org.eclipse.scout.rt.platform.BeanMetaData) IPingService(org.eclipse.scout.rt.shared.services.common.ping.IPingService) Callable(java.util.concurrent.Callable) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) IPingService(org.eclipse.scout.rt.shared.services.common.ping.IPingService) RunMonitor(org.eclipse.scout.rt.platform.context.RunMonitor)

Example 7 with ClientRunContext

use of org.eclipse.scout.rt.client.context.ClientRunContext 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;
}
Also used : ILookupRow(org.eclipse.scout.rt.shared.services.lookup.ILookupRow) ArrayList(java.util.ArrayList) ThreadInterruptedError(org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) FutureCancelledError(org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledError) ILookupRowFetchedCallback(org.eclipse.scout.rt.shared.services.lookup.ILookupRowFetchedCallback) List(java.util.List) ArrayList(java.util.ArrayList)

Example 8 with ClientRunContext

use of org.eclipse.scout.rt.client.context.ClientRunContext in project scout.rt by eclipse.

the class AbstractSmartField2 method newByRecLookupRowProvider.

/**
 * @see LookupCall#getDataByRec()
 */
protected ILookupRowProvider<VALUE> newByRecLookupRowProvider(final VALUE parentKey, final TriState activeState) {
    return new ILookupRowProvider<VALUE>() {

        @SuppressWarnings("unchecked")
        @Override
        public List<ILookupRow<VALUE>> provide(ILookupCall<VALUE> lookupCall) {
            return (List<ILookupRow<VALUE>>) lookupCall.getDataByRec();
        }

        @Override
        public void beforeProvide(ILookupCall<VALUE> lookupCall) {
            prepareRecLookup(lookupCall, parentKey, activeState);
        }

        @Override
        public void afterProvide(ILookupCall<VALUE> lookupCall, List<ILookupRow<VALUE>> result) {
            interceptFilterLookupResult(lookupCall, result);
            interceptFilterRecLookupResult(lookupCall, result);
            cleanupResultList(result);
        }

        @Override
        public void provideSync(ILookupCall<VALUE> lookupCall, ILookupRowFetchedCallback<VALUE> callback) {
            throw new UnsupportedOperationException("Legacy calls not supported");
        }

        @Override
        public IFuture<Void> provideAsync(ILookupCall<VALUE> lookupCall, ILookupRowFetchedCallback<VALUE> callback, ClientRunContext clientRunContext) {
            throw new UnsupportedOperationException("Legacy calls not supported");
        }

        @Override
        public String toString() {
            ToStringBuilder sb = new ToStringBuilder(this).attr("Rec Lookup").attr("parentKey", parentKey).attr("activeState", activeState);
            return sb.toString();
        }
    };
}
Also used : ILookupRow(org.eclipse.scout.rt.shared.services.lookup.ILookupRow) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) ILookupRowProvider(org.eclipse.scout.rt.client.ui.form.fields.smartfield.ILookupRowProvider) ILookupRowFetchedCallback(org.eclipse.scout.rt.shared.services.lookup.ILookupRowFetchedCallback) ToStringBuilder(org.eclipse.scout.rt.platform.util.ToStringBuilder) List(java.util.List) ArrayList(java.util.ArrayList) ILookupCall(org.eclipse.scout.rt.shared.services.lookup.ILookupCall)

Example 9 with ClientRunContext

use of org.eclipse.scout.rt.client.context.ClientRunContext in project scout.rt by eclipse.

the class DisplayParentResolver method findClosestDisplayParent.

/**
 * Resolves to the closest {@link IDisplayParent} from the current calling context.
 */
protected IDisplayParent findClosestDisplayParent() {
    final ClientRunContext currentRunContext = ClientRunContexts.copyCurrent();
    // Check whether a Form is currently the 'displayParent'. If being a wrapped Form, return its outer Form.
    IForm currentForm = currentRunContext.getForm();
    if (currentForm != null) {
        while (currentForm.getOuterForm() != null) {
            currentForm = currentForm.getOuterForm();
        }
        // added to the desktop (e.g. forms managed by form tool buttons).
        if (currentForm.isFormStarted()) {
            return currentForm;
        }
    }
    // Check whether an Outline is currently the 'displayParent'.
    final IOutline currentOutline = currentRunContext.getOutline();
    if (currentOutline != null) {
        return currentOutline;
    }
    // Use the desktop as 'displayParent'.
    return currentRunContext.getDesktop();
}
Also used : ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) IOutline(org.eclipse.scout.rt.client.ui.desktop.outline.IOutline)

Example 10 with ClientRunContext

use of org.eclipse.scout.rt.client.context.ClientRunContext in project scout.rt by eclipse.

the class BlockingTestUtility method runBlockingAction.

/**
 * Helper method to test code which will enter a blocking condition.
 * <p>
 * If <code>runnableOnceBlocked</code> throws an exception, it is given to {@link JUnitExceptionHandler} to make the
 * JUnit test fail.
 *
 * @param runnableGettingBlocked
 *          {@code IRunnable} that will enter a blocking condition.
 * @param runnableOnceBlocked
 *          {@code IRunnable} to be executed once the 'runnableGettingBlocked' enters a blocking condition.
 * @param awaitBackgroundJobs
 *          true waits for background jobs running in the same session to complete before runnableOnceBlocked is
 *          called
 */
public static void runBlockingAction(final IRunnable runnableGettingBlocked, final IRunnable runnableOnceBlocked, final boolean awaitBackgroundJobs) {
    final ClientRunContext runContext = ClientRunContexts.copyCurrent();
    final IBlockingCondition onceBlockedDoneCondition = Jobs.newBlockingCondition(true);
    // remember the list of client jobs before blocking
    final Set<IFuture<?>> jobsBefore = new HashSet<>();
    jobsBefore.addAll(BEANS.get(IJobManager.class).getFutures(new IFilter<IFuture<?>>() {

        @Override
        public boolean accept(IFuture<?> cand) {
            final RunContext candContext = cand.getJobInput().getRunContext();
            return candContext instanceof ClientRunContext && ((ClientRunContext) candContext).getSession() == runContext.getSession();
        }
    }));
    final IRegistrationHandle listenerRegistration = IFuture.CURRENT.get().addListener(Jobs.newEventFilterBuilder().andMatchEventType(JobEventType.JOB_STATE_CHANGED).andMatchState(JobState.WAITING_FOR_BLOCKING_CONDITION).andMatchExecutionHint(ModelJobs.EXECUTION_HINT_UI_INTERACTION_REQUIRED).toFilter(), new IJobListener() {

        @Override
        public void changed(final JobEvent event) {
            // waitFor was entered
            final IRunnable callRunnableOnceBlocked = new IRunnable() {

                @Override
                public void run() throws Exception {
                    try {
                        runnableOnceBlocked.run();
                    } finally {
                        event.getData().getBlockingCondition().setBlocking(false);
                        onceBlockedDoneCondition.setBlocking(false);
                    }
                }
            };
            final JobInput jobInputForRunnableOnceBlocked = ModelJobs.newInput(runContext).withExceptionHandling(BEANS.get(JUnitExceptionHandler.class), true).withName("JUnit: Handling blocked thread because waiting for a blocking condition");
            if (awaitBackgroundJobs) {
                // wait until all background jobs finished
                Jobs.schedule(new IRunnable() {

                    @Override
                    public void run() throws Exception {
                        jobsBefore.add(IFuture.CURRENT.get());
                        BEANS.get(IJobManager.class).awaitFinished(new IFilter<IFuture<?>>() {

                            @Override
                            public boolean accept(IFuture<?> f) {
                                RunContext candContext = f.getJobInput().getRunContext();
                                return candContext instanceof ClientRunContext && ((ClientRunContext) candContext).getSession() == runContext.getSession() && !jobsBefore.contains(f);
                            }
                        }, 5, TimeUnit.MINUTES);
                        // call runnableOnceBlocked
                        ModelJobs.schedule(callRunnableOnceBlocked, jobInputForRunnableOnceBlocked);
                    }
                }, Jobs.newInput().withName("wait until background jobs finished"));
            } else {
                // call runnableOnceBlocked directly
                ModelJobs.schedule(callRunnableOnceBlocked, jobInputForRunnableOnceBlocked);
            }
        }
    });
    try {
        // this action will enter a blocking condition which causes the 'runnableOnceBlocked' to be executed.
        runnableGettingBlocked.run();
    } catch (final Exception e) {
        throw BEANS.get(DefaultRuntimeExceptionTranslator.class).translate(e);
    } finally {
        listenerRegistration.dispose();
    }
    // we need to wait until the runnableOnceBlocked is completed.
    // runnableOnceBlocked may, during its execution,  set the original blocking condition to non-blocking but still execute
    // important code afterwards. Therefore, the original blocking condition that starts runnableOnceBlocked is only used
    // to indicate the start of the runnableOnceBlocked, but this method returns only AFTER runnableOnceBlocked completes execution.
    onceBlockedDoneCondition.waitForUninterruptibly(120, TimeUnit.SECONDS);
}
Also used : IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) JUnitExceptionHandler(org.eclipse.scout.rt.testing.platform.runner.JUnitExceptionHandler) IJobManager(org.eclipse.scout.rt.platform.job.IJobManager) IFuture(org.eclipse.scout.rt.platform.job.IFuture) IJobListener(org.eclipse.scout.rt.platform.job.listener.IJobListener) PlatformException(org.eclipse.scout.rt.platform.exception.PlatformException) JobInput(org.eclipse.scout.rt.platform.job.JobInput) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) JobEvent(org.eclipse.scout.rt.platform.job.listener.JobEvent) IFilter(org.eclipse.scout.rt.platform.filter.IFilter) RunContext(org.eclipse.scout.rt.platform.context.RunContext) ClientRunContext(org.eclipse.scout.rt.client.context.ClientRunContext) IRegistrationHandle(org.eclipse.scout.rt.platform.util.IRegistrationHandle) IBlockingCondition(org.eclipse.scout.rt.platform.job.IBlockingCondition) HashSet(java.util.HashSet)

Aggregations

ClientRunContext (org.eclipse.scout.rt.client.context.ClientRunContext)19 ArrayList (java.util.ArrayList)10 List (java.util.List)9 ILookupRow (org.eclipse.scout.rt.shared.services.lookup.ILookupRow)9 ILookupRowFetchedCallback (org.eclipse.scout.rt.shared.services.lookup.ILookupRowFetchedCallback)9 ToStringBuilder (org.eclipse.scout.rt.platform.util.ToStringBuilder)8 ILookupCall (org.eclipse.scout.rt.shared.services.lookup.ILookupCall)8 IRunnable (org.eclipse.scout.rt.platform.util.concurrent.IRunnable)7 ILookupRowProvider (org.eclipse.scout.rt.client.ui.form.fields.smartfield.ILookupRowProvider)4 EventListenerList (org.eclipse.scout.rt.platform.util.EventListenerList)4 FutureCancelledError (org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledError)3 ThreadInterruptedError (org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError)3 Test (org.junit.Test)3 IOutline (org.eclipse.scout.rt.client.ui.desktop.outline.IOutline)2 RunMonitor (org.eclipse.scout.rt.platform.context.RunMonitor)2 BlockingCountDownLatch (org.eclipse.scout.rt.testing.platform.util.BlockingCountDownLatch)2 JSONObject (org.json.JSONObject)2 HashSet (java.util.HashSet)1 Callable (java.util.concurrent.Callable)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1