use of com.vaadin.flow.internal.CurrentInstance in project flow by vaadin.
the class UI method accessSynchronously.
/**
* Locks the session of this UI and runs the provided command right away.
* <p>
* It is generally recommended to use {@link #access(Command)} instead of
* this method for accessing a session from a different thread as
* {@link #access(Command)} 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.
* <p>
* This method behaves differently than {@link #access(Command)} in some
* situations:
* <ul>
* <li>If the current thread is currently holding the lock of the session,
* {@link #accessSynchronously(Command)} runs the task right away whereas
* {@link #access(Command)} defers the task to a later point in time.</li>
* <li>If some other thread is currently holding the lock for the session,
* {@link #accessSynchronously(Command)} blocks while waiting for the lock
* to be available whereas {@link #access(Command)} defers the task to a
* later point in time.</li>
* </ul>
*
* @since 7.1
*
* @param command
* the command which accesses the UI
* @throws UIDetachedException
* if the UI is not attached to a session (and locking can
* therefore not be done)
* @throws IllegalStateException
* if the current thread holds the lock for another session
*
* @see #access(Command)
* @see VaadinSession#accessSynchronously(Command)
*/
public void accessSynchronously(Command command) throws UIDetachedException {
Map<Class<?>, CurrentInstance> old = null;
VaadinSession session = getSession();
if (session == null) {
throw new UIDetachedException();
}
VaadinService.verifyNoOtherSessionLocked(session);
session.lock();
try {
if (getSession() == null) {
// acquired the lock.
throw new UIDetachedException();
}
old = CurrentInstance.setCurrent(this);
command.execute();
} finally {
session.unlock();
if (old != null) {
CurrentInstance.restoreInstances(old);
}
}
}
use of com.vaadin.flow.internal.CurrentInstance in project flow by vaadin.
the class ApplicationRunnerServlet method findDeploymentConfiguration.
private DeploymentConfiguration findDeploymentConfiguration(DeploymentConfiguration originalConfiguration) throws Exception {
// First level of cache
DeploymentConfiguration configuration = CurrentInstance.get(DeploymentConfiguration.class);
if (configuration == null) {
// Not in cache, try to find a VaadinSession to get it from
VaadinSession session = VaadinSession.getCurrent();
if (session == null) {
/*
* There's no current session, request or response when serving
* static resources, but there's still the current request
* maintained by ApplicationRunnerServlet, and there's most
* likely also a HttpSession containing a VaadinSession for that
* request.
*/
HttpServletRequest currentRequest = VaadinServletService.getCurrentServletRequest();
if (currentRequest != null) {
HttpSession httpSession = currentRequest.getSession(false);
if (httpSession != null) {
Map<Class<?>, CurrentInstance> oldCurrent = CurrentInstance.setCurrent((VaadinSession) null);
try {
VaadinServletService service = (VaadinServletService) VaadinService.getCurrent();
session = service.findVaadinSession(new VaadinServletRequest(currentRequest, service));
} finally {
/*
* Clear some state set by findVaadinSession to
* avoid accidentally depending on it when coding on
* e.g. static request handling.
*/
CurrentInstance.restoreInstances(oldCurrent);
currentRequest.removeAttribute(VaadinSession.class.getName());
}
}
}
}
if (session != null) {
String name = ApplicationRunnerServlet.class.getName() + ".deploymentConfiguration";
try {
session.lock();
configuration = (DeploymentConfiguration) session.getAttribute(name);
if (configuration == null) {
ApplicationRunnerServlet servlet = (ApplicationRunnerServlet) VaadinServlet.getCurrent();
Class<?> classToRun;
try {
classToRun = servlet.getClassToRun();
} catch (ClassNotFoundException e) {
/*
* This happens e.g. if the UI class defined in the
* URL is not found or if this servlet just serves
* static resources while there's some other servlet
* that serves the UI (e.g. when using /run-push/).
*/
return originalConfiguration;
}
CustomDeploymentConfiguration customDeploymentConfiguration = classToRun.getAnnotation(CustomDeploymentConfiguration.class);
if (customDeploymentConfiguration != null) {
Properties initParameters = new Properties(originalConfiguration.getInitParameters());
for (Conf entry : customDeploymentConfiguration.value()) {
initParameters.put(entry.name(), entry.value());
}
initParameters.put(VaadinSession.UI_PARAMETER, getApplicationRunnerApplicationClassName(request.get()));
configuration = new DefaultDeploymentConfiguration(servlet.getClass(), initParameters, this::scanForResources);
} else {
configuration = originalConfiguration;
}
session.setAttribute(name, configuration);
}
} finally {
session.unlock();
}
CurrentInstance.set(DeploymentConfiguration.class, configuration);
} else {
configuration = originalConfiguration;
}
}
return configuration;
}
use of com.vaadin.flow.internal.CurrentInstance in project flow by vaadin.
the class VaadinSession method unlock.
/**
* Unlocks this session. This method should always be used in a finally
* block after {@link #lock()} to ensure that the lock is always released.
* <p>
* For UIs in this session that have its push mode set to
* {@link PushMode#AUTOMATIC automatic}, pending changes will be pushed to
* their respective clients.
*
* @see #lock()
* @see UI#push()
*/
public void unlock() {
assert hasLock();
boolean ultimateRelease = false;
try {
/*
* Run pending tasks and push if the reentrant lock will actually be
* released by this unlock() invocation.
*/
if (((ReentrantLock) getLockInstance()).getHoldCount() == 1) {
ultimateRelease = true;
getService().runPendingAccessTasks(this);
for (UI ui : getUIs()) {
if (ui.getPushConfiguration().getPushMode() == PushMode.AUTOMATIC) {
Map<Class<?>, CurrentInstance> oldCurrent = CurrentInstance.setCurrent(ui);
try {
ui.push();
} finally {
CurrentInstance.restoreInstances(oldCurrent);
}
}
}
}
} finally {
getLockInstance().unlock();
}
/*
* If the session is locked when a new access task is added, it is
* assumed that the queue will be purged when the lock is released. This
* might however not happen if a task is enqueued between the moment
* when unlock() purges the queue and the moment when the lock is
* actually released. This means that the queue should be purged again
* if it is not empty after unlocking.
*/
if (ultimateRelease && !getPendingAccessQueue().isEmpty()) {
getService().ensureAccessQueuePurged(this);
}
}
Aggregations