From: Leif Åstrand
- * The given runnable is executed while holding the session lock to ensure - * exclusive access to this session. The session and related thread locals - * are set properly before executing the runnable. + * It is generally recommended to use {@link #access(Runnable)} instead of + * this method for accessing a session from a different thread as + * {@link #access(Runnable)} can be used while holding the lock of another + * session. To avoid causing deadlocks, this methods throws an exception if + * it is detected than another session is also locked by the current thread. *
*- * RPC handlers for components inside this session do not need this method - * as the session is automatically locked by the framework during request - * handling. - *
- *- * Note that calling this method while another session is locked by the - * current thread will cause an exception. This is to prevent deadlock - * situations when two threads have locked one session each and are both - * waiting for the lock for the other session. + * This method behaves differently than {@link #access(Runnable)} in some + * situations: + *
+ * The given runnable is executed while holding the session lock to ensure + * exclusive access to this session. If this session is not locked, the lock + * will be acquired and the runnable is run right away. If this session is + * currently locked, the runnable will be run before that lock is released. + *
+ *+ * RPC handlers for components inside this session do not need to use this + * method as the session is automatically locked by the framework during RPC + * handling. + *
+ *+ * Please note that the runnable might be invoked on a different thread or + * later on the current thread, which means that custom thread locals might + * not have the expected values when the runnable is executed. The session + * and other thread locals provided by Vaadin are set properly before + * executing the runnable. + *
+ *+ * The returned future can be used to check for task completion and to + * cancel the task. To help avoiding deadlocks, {@link Future#get()} throws + * an exception if it is detected that the current thread holds the lock for + * some other session. + *
+ * + * @see #lock() + * @see #getCurrent() + * @see #accessSynchronously(Runnable) + * @see UI#access(Runnable) + * + * @since 7.1 + * + * @param runnable + * the runnable which accesses the session + * @return a future that can be used to check for task completion and to + * cancel the task + */ + public Future
+ * This method is automatically run by the framework at appropriate
+ * situations and is not intended to be used by application developers.
+ *
+ * @since 7.1
+ */
+ public void runPendingAccessTasks() {
+ assert hasLock();
+
+ FutureTask
- * The given runnable is executed while holding the session lock to ensure
- * exclusive access to this UI and its session. The UI and related thread
- * locals are set properly before executing the runnable.
+ * It is generally recommended to use {@link #access(Runnable)} instead of
+ * this method for accessing a session from a different thread as
+ * {@link #access(Runnable)} can be used while holding the lock of another
+ * session. To avoid causing deadlocks, this methods throws an exception if
+ * it is detected than another session is also locked by the current thread.
*
- * RPC handlers for components inside this UI do not need this method as the
- * session is automatically locked by the framework during request handling.
- *
- * Note that calling this method while another session is locked by the
- * current thread will cause an exception. This is to prevent deadlock
- * situations when two threads have locked one session each and are both
- * waiting for the lock for the other session.
+ * This method behaves differently than {@link #access(Runnable)} in some
+ * situations:
+ *
+ *
*
+ * The given runnable is executed while holding the session lock to ensure + * exclusive access to this UI. If the session is not locked, the lock will + * be acquired and the runnable is run right away. If the session is + * currently locked, the runnable will be run before that lock is released. + *
+ *+ * RPC handlers for components inside this UI do not need to use this method + * as the session is automatically locked by the framework during RPC + * handling. + *
+ *+ * Please note that the runnable might be invoked on a different thread or + * later on the current thread, which means that custom thread locals might + * not have the expected values when the runnable is executed. The UI and + * other thread locals provided by Vaadin are set properly before executing + * the runnable. + *
+ *+ * The returned future can be used to check for task completion and to + * cancel the task. + *
+ * + * @see #getCurrent() + * @see #accessSynchronously(Runnable) + * @see VaadinSession#access(Runnable) + * @see VaadinSession#lock() + * + * @since 7.1 + * + * @param runnable + * the runnable which accesses the UI + * @throws UIDetachedException + * if the UI is not attached to a session (and locking can + * therefore not be done) + * @return a future that can be used to check for task completion and to + * cancel the task + */ + public FutureNew Test | ||
open | +/run/com.vaadin.tests.components.ui.UiAccess?restartApplication | ++ |
click | +vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0] | ++ |
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2 | +exact:0. Access from UI thread future is done? false | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1 | +1. Access from UI thread is run | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +exact:2. beforeClientResponse future is done? true | +
click | +vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0] | ++ |
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1 | +0. Initial background message | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +exact:1. Thread has current response? false | +
waitForText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_4 | +0. Initial background message | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2 | +exact:2. Thread got lock, inital future done? true | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1 | +exact:3. Access has current response? true | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +exact:4. Thread is still alive? false | +
click | +vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0] | ++ |
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2 | +0. Throwing exception in access | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1 | +exact:1. firstFuture is done? true | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +2. Got exception from firstFuture: java.lang.RuntimeException: Catch me if you can | +
click | +vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0] | ++ |
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +0. future was cancled, should not start | +
click | +vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[4]/VButton[0]/domChild[0]/domChild[0] | ++ |
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2 | +0. Waiting for thread to start | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1 | +1. Thread started, waiting for interruption | +
assertText | +vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0 | +2. I was interrupted | +