Skip to content

Commit

Permalink
feat: Add access delegate method in Component
Browse files Browse the repository at this point in the history
fixes #20104
  • Loading branch information
TatuLund authored Oct 2, 2024
1 parent abc0122 commit c00a900
Showing 1 changed file with 66 additions and 2 deletions.
68 changes: 66 additions & 2 deletions flow-server/src/main/java/com/vaadin/flow/component/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
package com.vaadin.flow.component;

import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.Future;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;

Expand All @@ -35,6 +37,9 @@
import com.vaadin.flow.internal.LocaleUtil;
import com.vaadin.flow.internal.nodefeature.ElementData;
import com.vaadin.flow.server.Attributes;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.shared.Registration;

/**
Expand Down Expand Up @@ -92,6 +97,8 @@ public MapToExistingElement(Element element,

private final boolean templateMapped;

private WeakReference<UI> uiRef;

/**
* Creates a component instance with an element created based on the
* {@link Tag} annotation of the sub class.
Expand Down Expand Up @@ -467,7 +474,7 @@ public Optional<String> getId() {
* the attach event
*/
protected void onAttach(AttachEvent attachEvent) {
// NOOP by default
uiRef = new WeakReference<>(attachEvent.getUI());
}

/**
Expand All @@ -483,7 +490,64 @@ protected void onAttach(AttachEvent attachEvent) {
* the detach event
*/
protected void onDetach(DetachEvent detachEvent) {
// NOOP by default
if (uiRef != null) {
uiRef.clear();
uiRef = null;
}
}

/**
* Provides exclusive access to UI where this component is attached from
* outside a request handling thread.
* <p>
* The given command is executed while holding the session lock to ensure
* exclusive access to the UI. If the session is not locked, the lock will
* be acquired and the command is run right away. If the session is
* currently locked, the command will be run before that lock is released.
* </p>
* <p>
* RPC handlers for components inside the UI do not need to use this method
* as the session is automatically locked by the framework during RPC
* handling.
* </p>
* <p>
* Please note that the command 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 command is executed.
* {@link UI#getCurrent()}, {@link VaadinSession#getCurrent()} and
* {@link VaadinService#getCurrent()} are set according to this UI before
* executing the command. Other standard CurrentInstance values such as
* {@link VaadinService#getCurrentRequest()} and
* {@link VaadinService#getCurrentResponse()} will not be defined.
* </p>
* <p>
* The returned future can be used to check for task completion and to
* cancel the task.
* </p>
*
* @see UI#access(Command)
* @see UI#accessSynchronously(Command)
* @see VaadinSession#access(Command)
* @see VaadinSession#lock()
*
*
* @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 Component is not attached to the UI.
*
* @return a future that can be used to check for task completion and to
* cancel the task
*/
protected void access(Command command) {
if (uiRef == null || uiRef.get() == null) {
throw new IllegalStateException(
"Cannot perform access in detached component");
}
uiRef.get().access(command);
}

/**
Expand Down

0 comments on commit c00a900

Please sign in to comment.