diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml
new file mode 100644
index 0000000..dc89ac2
--- /dev/null
+++ b/.github/workflows/build-and-publish.yml
@@ -0,0 +1,38 @@
+# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
+# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path
+
+name: Build and publish
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 8
+ uses: actions/setup-java@v2
+ with:
+ java-version: '8'
+ distribution: 'zulu'
+ server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
+ # settings-path: ${{ github.workspace }} # location for the settings.xml file
+
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
+
+ - name: Publish to GitHub Packages Apache Maven
+ # run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
+ run: mvn --batch-mode deploy
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
diff --git a/README.md b/README.md
index d51090f..4c4ac4a 100755
--- a/README.md
+++ b/README.md
@@ -5,6 +5,11 @@
# Async Manager for Vaadin Flow
+# Hinweis "c-si" Version
+Bei der Ausführung der Async-Tasks werden die Session und der SecurityContext der jeweiligen UI an den "Background-Thread" gesetzt.
+
+# About
+
In complex application quite often you end up having a view that takes ages to load
because some parts of view require heavy computation. If you are pursuing the goal
of making your application responsive, you would probably want to defer updates for
@@ -85,6 +90,11 @@ AsyncManager.getInstance().setExceptionHandler((task, exception) -> ...);
Note: By default all worker threads are started by `ThreadPoolExecutor` which defaults
to pool size of 25 threads. You can change that with `AsyncManager.getInstance().setExecutorService()`.
+As of version 1.2 it is possible to set a task state handler if you need more information about each task, e.g. for ui loading indicator handling.
+```java
+AsyncManager.getInstance().setTaskStateHandler((task, state) -> ...);
+```
+
## Installing with Maven
```xml
diff --git a/pom.xml b/pom.xml
index 6120fbf..2b34c15 100755
--- a/pom.xml
+++ b/pom.xml
@@ -3,11 +3,11 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- org.vaadin.helper
+ de.csi.vaadin.helper
async-manager
- 1.1.0
+ 1.2.1
Async Manager
- Async Manager for Vaadin Flow
+ Async Manager for Vaadin Flow (CSI fork)
10.0.5
@@ -38,6 +38,13 @@
+
+
+ github
+ GitHub Packages
+ https://maven.pkg.github.com/c-si/async-manager
+
+
@@ -55,6 +62,18 @@
com.vaadin
vaadin-core
+
+ javax.servlet
+ servlet-api
+ 2.5
+ provided
+
+
+ org.springframework.security
+ spring-security-web
+ 5.5.3
+ provided
+
org.slf4j
slf4j-simple
diff --git a/src/main/java/org/vaadin/flow/helper/AsyncManager.java b/src/main/java/org/vaadin/flow/helper/AsyncManager.java
index e8e7d29..d7f8522 100644
--- a/src/main/java/org/vaadin/flow/helper/AsyncManager.java
+++ b/src/main/java/org/vaadin/flow/helper/AsyncManager.java
@@ -5,7 +5,10 @@
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.UI;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -60,6 +63,11 @@ public final class AsyncManager {
* Exception handler
*/
private ExceptionHandler exceptionHandler = AsyncManager::logException;
+ /**
+ * Task state handler
+ */
+ private TaskStateHandler taskStateHandler;
+
/**
* Instance of {@link ExecutorService} used for asynchronous tasks
*/
@@ -132,6 +140,15 @@ public void setExceptionHandler(ExceptionHandler handler) {
exceptionHandler = handler;
}
+ /**
+ * Set custom task state handler to monitor
+ * @param handler State handler to set
+ */
+ public void setTaskStateHandler(TaskStateHandler handler) {
+ taskStateHandler = handler;
+ }
+
+
/**
* Get a {@link ExecutorService} used for asynchronous task execution.
*
@@ -294,6 +311,12 @@ void handleException(Task task, Exception e) {
exceptionHandler.handle(task, e);
}
+ void handleTaskStateChanged(Task task, TaskStateHandler.State state) {
+ if (taskStateHandler != null) {
+ taskStateHandler.taskChanged(task, state);
+ }
+ }
+
/**
* Functional interface for exception handling
*/
@@ -307,4 +330,32 @@ public interface ExceptionHandler {
*/
void handle(Task task, Exception e);
}
+
+ /**
+ * Functional interface for task state handling
+ */
+ @FunctionalInterface
+ public interface TaskStateHandler {
+ enum State {
+ /**
+ * Task started
+ */
+ RUNNING,
+ /**
+ * Task done
+ */
+ DONE,
+ /**
+ * Task was canceled
+ */
+ CANCELED
+ }
+
+ /**
+ * Handle state change during task execution.
+ * @param task Task where state change happened
+ * @param state State of the given task
+ */
+ void taskChanged(Task task, State state);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/vaadin/flow/helper/AsyncTask.java b/src/main/java/org/vaadin/flow/helper/AsyncTask.java
index 58965f1..fc5bf73 100644
--- a/src/main/java/org/vaadin/flow/helper/AsyncTask.java
+++ b/src/main/java/org/vaadin/flow/helper/AsyncTask.java
@@ -3,8 +3,12 @@
import com.vaadin.flow.component.*;
import com.vaadin.flow.router.BeforeLeaveEvent;
import com.vaadin.flow.server.Command;
+import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.shared.Registration;
import com.vaadin.flow.shared.communication.PushMode;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -50,7 +54,7 @@ public class AsyncTask extends Task {
* Number of poll events happened while action is executing, or {@link #PUSH_ACTIVE} if
* push is used for current task
*/
- private AtomicInteger missedPolls = new AtomicInteger();
+ private final AtomicInteger missedPolls = new AtomicInteger();
/**
* {@code true}, if thread may be interrupted if UI/Component detaches
*/
@@ -100,6 +104,7 @@ public void cancel() {
if (!task.isCancelled() && !task.isDone()) {
task.cancel(mayInterrupt);
}
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.CANCELED);
remove();
}
@@ -191,6 +196,12 @@ private void registerPoll(Component component, Action action) {
private FutureTask createFutureTask(Action action) {
return new FutureTask<>(() -> {
try {
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.RUNNING);
+
+ // Session + Security für den Async-Task setzen
+ VaadinSession.setCurrent(getUI().getSession());
+ SecurityContextHolder.setContext((SecurityContext) VaadinSession.getCurrent().getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
+
action.run(this);
} catch (UIDetachedException ignore) {
// Do not report
@@ -201,6 +212,7 @@ private FutureTask createFutureTask(Action action) {
// Dump
getAsyncManager().handleException(this, e);
} finally {
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.DONE);
remove();
}
}, this);
diff --git a/src/main/java/org/vaadin/flow/helper/SyncTask.java b/src/main/java/org/vaadin/flow/helper/SyncTask.java
index af0dfb6..cba0f49 100644
--- a/src/main/java/org/vaadin/flow/helper/SyncTask.java
+++ b/src/main/java/org/vaadin/flow/helper/SyncTask.java
@@ -69,10 +69,13 @@ public void preventThreadInterrupt() {
void register(UI ui, Component component, Action action) {
setUI(ui);
try {
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.RUNNING);
action.run(this);
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.DONE);
} catch (Exception e) {
// Dump
getAsyncManager().handleException(this, e);
+ getAsyncManager().handleTaskStateChanged(this, AsyncManager.TaskStateHandler.State.DONE);
}
}
}