Refs #722 BackgroundTasks: Web implementation

This commit is contained in:
Yuriy Artamonov 2011-08-11 13:02:22 +00:00
parent 5994e97315
commit 6efab0773e
15 changed files with 300 additions and 256 deletions

View File

@ -7,6 +7,7 @@
package com.haulmont.cuba.desktop.gui.utils;
import com.haulmont.cuba.core.global.TimeProvider;
import com.haulmont.cuba.gui.components.Window;
import com.haulmont.cuba.gui.executors.BackgroundTask;
import com.haulmont.cuba.gui.executors.BackgroundTaskHandler;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
@ -17,7 +18,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static com.google.common.base.Preconditions.checkNotNull;
@ -27,13 +27,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
*
* @author artamonov
*/
@SuppressWarnings("unused")
public class DesktopBackgroundWorker implements BackgroundWorker {
private WatchDog watchDogThread;
private WatchDog watchDog;
public DesktopBackgroundWorker() {
watchDogThread = new DesktopWatchDog();
watchDog = new DesktopWatchDog();
}
@Override
@ -42,48 +41,58 @@ public class DesktopBackgroundWorker implements BackgroundWorker {
// create task handler
TaskExecutor<T> taskExecutor = new DesktopTaskExecutor<T>(task);
return new TaskHandler<T>(taskExecutor, watchDogThread);
final TaskHandler<T> taskHandler = new TaskHandler<T>(taskExecutor, watchDog);
task.getOwnerWindow().addListener(new Window.CloseListener() {
@Override
public void windowClosed(String actionId) {
taskHandler.cancel(true);
}
});
return taskHandler;
}
/**
* WatchDog
*/
private class DesktopWatchDog extends SwingWorker<Void, TaskHandler> implements BackgroundWorker.WatchDog{
private class DesktopWatchDog extends SwingWorker<Void, TaskHandler> implements BackgroundWorker.WatchDog {
private static final int WATCHDOG_INTERVAL = 100;
private static final int WATCHDOG_INTERVAL = 2000;
private boolean watching = false;
private ReentrantLock watchLock;
private Set<TaskHandler> watches;
private final Set<TaskHandler> watches;
private DesktopWatchDog() {
watchLock = new ReentrantLock();
watches = new LinkedHashSet<TaskHandler>();
}
@Override
protected Void doInBackground() throws Exception {
while (watching) {
cleanupTasks();
}
return null;
}
private void cleanupTasks() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(WATCHDOG_INTERVAL);
watchLock.lock();
synchronized (watches) {
long actualTime = TimeProvider.currentTimestamp().getTime();
long actualTime = TimeProvider.currentTimestamp().getTime();
List<TaskHandler> forRemove = new LinkedList<TaskHandler>();
for (TaskHandler task : watches) {
if (task.isCancelled() || task.isDone()) {
forRemove.add(task);
} else if (task.checkHangup(actualTime)) {
cancelTask(task);
forRemove.add(task);
List<TaskHandler> forRemove = new LinkedList<TaskHandler>();
for (TaskHandler task : watches) {
if (task.isCancelled() || task.isDone()) {
forRemove.add(task);
} else if (task.checkHangup(actualTime)) {
cancelTask(task);
forRemove.add(task);
}
}
watches.removeAll(forRemove);
}
watches.removeAll(forRemove);
watchLock.unlock();
return null;
}
private void cancelTask(TaskHandler task) {
@ -94,7 +103,7 @@ public class DesktopBackgroundWorker implements BackgroundWorker {
protected void process(List<TaskHandler> chunks) {
for (TaskHandler task : chunks) {
if (task.isHangup())
task.cancel(true);
task.close();
}
}
@ -104,15 +113,12 @@ public class DesktopBackgroundWorker implements BackgroundWorker {
}
public void manageTask(TaskHandler backroundTask) {
watchLock.lock();
watches.add(backroundTask);
if (!watching) {
startWatching();
synchronized (watches) {
watches.add(backroundTask);
}
watchLock.unlock();
if (!watching)
startWatching();
}
}
@ -125,6 +131,7 @@ public class DesktopBackgroundWorker implements BackgroundWorker {
private DesktopTaskExecutor(BackgroundTask<T> runnableTask) {
this.runnableTask = runnableTask;
runnableTask.setProgressHandler(this);
}
@Override
@ -140,11 +147,19 @@ public class DesktopBackgroundWorker implements BackgroundWorker {
@Override
protected void done() {
runnableTask.done();
if (!runnableTask.isInterrupted())
runnableTask.done();
}
public void execute(long timeout, TimeUnit unit) {
execute();
@Override
public boolean cancelExecution(boolean mayInterruptIfRunning) {
runnableTask.setInterrupted(true);
if (!isDone()) {
cancel(mayInterruptIfRunning);
}
return true;
}
@Override

View File

@ -6,9 +6,9 @@
package com.haulmont.cuba.desktop.sys;
import com.haulmont.cuba.core.sys.AppContext;
import com.haulmont.cuba.desktop.gui.DesktopComponentsFactory;
import com.haulmont.cuba.desktop.gui.components.DesktopExportDisplay;
import com.haulmont.cuba.desktop.gui.utils.DesktopBackgroundWorker;
import com.haulmont.cuba.gui.AppConfig;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
import com.haulmont.cuba.gui.export.ExportDisplay;
@ -22,7 +22,6 @@ import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
public class DesktopAppConfig extends AppConfig {
private volatile ComponentsFactory componentsFactory;
private volatile BackgroundWorker backgroundWorker;
@Override
protected ExportDisplay __createExportDisplay() {
@ -31,12 +30,7 @@ public class DesktopAppConfig extends AppConfig {
@Override
protected BackgroundWorker __getBackgroundWorker() {
if (backgroundWorker == null) {
synchronized (this) {
backgroundWorker = new DesktopBackgroundWorker();
}
}
return backgroundWorker;
return AppContext.getBean(BackgroundWorker.NAME);
}
@Override

View File

@ -30,6 +30,8 @@
<bean id="cuba_FileUploading" class="com.haulmont.cuba.gui.upload.FileUploading"/>
<bean id="cuba_BackgroundWorker" class="com.haulmont.cuba.desktop.gui.utils.DesktopBackgroundWorker"/>
<!-- Remote stubs -->
<bean id="cuba_clusterInvocationSupport" class="com.haulmont.cuba.core.sys.remoting.ClusterInvocationSupport"

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.gui.backgroundtasks;
import com.haulmont.cuba.gui.AppConfig;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.executors.BackgroundTask;
import com.haulmont.cuba.gui.executors.BackgroundTaskHandler;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* BackgroundWorker Test
* <p>$Id$</p>
*
* @author artamonov
*/
public class BackgroundTasksWindow extends AbstractWindow {
protected BackgroundWorker backgroundWorker;
protected BackgroundTaskHandler taskHandler;
protected Button startBtn;
protected Button stopBtn;
protected Label statusLabel;
public BackgroundTasksWindow(IFrame frame) {
super(frame);
}
@Override
protected void init(Map<String, Object> params) {
super.init(params);
backgroundWorker = AppConfig.getBackgroundWorker();
final BackgroundTask<Integer> progressIndicator = new BackgroundTask<Integer>(this) {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ignored) {
}
publish((Integer) i);
}
}
@Override
public void canceled() {
statusLabel.setValue("Canceled");
startBtn.setEnabled(true);
stopBtn.setEnabled(false);
taskHandler = null;
}
@Override
public void done() {
statusLabel.setValue("Done");
startBtn.setEnabled(true);
stopBtn.setEnabled(false);
taskHandler = null;
}
@Override
public void progress(List<Integer> changes) {
int size = changes.size();
if (size >= 0)
statusLabel.setValue(String.valueOf(changes.get(size - 1)));
}
};
startBtn = getComponent("startTaskBtn");
stopBtn = getComponent("stopTaskBtn");
statusLabel = getComponent("statusLbl");
startBtn.setAction(new AbstractAction("Start") {
@Override
public void actionPerform(Component component) {
if (taskHandler == null) {
statusLabel.setValue("Started");
taskHandler = backgroundWorker.handle(progressIndicator);
startBtn.setEnabled(false);
stopBtn.setEnabled(true);
taskHandler.execute(5, TimeUnit.SECONDS);
}
}
});
stopBtn.setAction(new AbstractAction("Stop") {
@Override
public void actionPerform(Component component) {
if (taskHandler != null) {
taskHandler.cancel(true);
}
}
});
}
}

View File

@ -1,25 +0,0 @@
<window
xmlns="http://www.haulmont.com/schema/cuba/gui/window.xsd"
class="com.haulmont.cuba.gui.backgroundtasks.BackgroundTasksWindow"
caption="BackgroundTasks">
<dsContext>
</dsContext>
<layout spacing="true">
<groupBox expandable="false">
<caption label="Test background tasks"/>
<hbox spacing="true" margin="true">
<label value="Status:"/>
<label id="statusLbl" value="Stopped"/>
</hbox>
<hbox spacing="true">
<button id="startTaskBtn" caption="Start"/>
<button id="stopTaskBtn" caption="Stop"/>
</hbox>
</groupBox>
</layout>
</window>

View File

@ -12,6 +12,10 @@ import java.util.List;
/**
* Backround task for execute in {@link BackgroundWorker}
* <p>
* <b>It is strongly recommended to be able to interrupt working thread, <br/>
* don't ignore {@link InterruptedException} or its ancestors</b>
* </p>
* <p>$Id$</p>
*
* @param <T> measure unit which shows progress of task
@ -22,6 +26,8 @@ public abstract class BackgroundTask<T> {
private ProgressHandler<T> progressHandler;
private Window ownerWindow;
private volatile boolean isInterrupted = false;
protected BackgroundTask(Window ownerWindow) {
this.ownerWindow = ownerWindow;
}
@ -69,4 +75,12 @@ public abstract class BackgroundTask<T> {
public Window getOwnerWindow() {
return ownerWindow;
}
public boolean isInterrupted() {
return isInterrupted;
}
public void setInterrupted(boolean interrupted) {
isInterrupted = interrupted;
}
}

View File

@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkState;
* @author artamonov
*/
public interface BackgroundWorker {
String NAME = "cuba_BackgroundWorker";
/**
* Create handler for background task
@ -39,7 +40,7 @@ public interface BackgroundWorker {
void execute();
boolean cancel(boolean mayInterruptIfRunning);
boolean cancelExecution(boolean mayInterruptIfRunning);
BackgroundTask<T> getTask();
@ -97,13 +98,20 @@ public interface BackgroundWorker {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean canceled = taskExecutor.cancel(mayInterruptIfRunning);
boolean canceled = taskExecutor.cancelExecution(mayInterruptIfRunning);
if (canceled) {
taskExecutor.getTask().canceled();
}
return canceled;
}
/**
* Cancel without events for tasks
*/
public void close() {
taskExecutor.cancelExecution(true);
}
@Override
public boolean isDone() {
return taskExecutor.isDone();

View File

@ -84,7 +84,4 @@
<screen id="core$EntitySnapshot.view"
template="/com/haulmont/cuba/gui/app/core/entitydiff/diff-view.xml"/>
<screen id="test$BackroundTasks.window"
template="/com/haulmont/cuba/gui/backgroundtasks/background-task-window.xml"/>
</screen-config>

View File

@ -101,6 +101,8 @@ public abstract class App extends Application
private AppCookies cookies;
private BackgroundTaskManager backgroundTaskManager;
protected boolean testModeRequest = false;
protected String clientAddress;
@ -124,6 +126,7 @@ public abstract class App extends Application
};
cookies.setCookiesEnabled(true);
timers = new AppTimers(this);
backgroundTaskManager = new BackgroundTaskManager();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@ -457,6 +460,22 @@ public abstract class App extends Application
}
}
public BackgroundTaskManager getTaskManager() {
return backgroundTaskManager;
}
public void addBackgroundTask(Thread task) {
backgroundTaskManager.addTask(task);
}
public void removeBackgroundTask(Thread task) {
backgroundTaskManager.removeTask(task);
}
public void cleanupBackgroundTasks() {
backgroundTaskManager.cleanupTasks();
}
Window getCurrentWindow() {
String name = currentWindowName.get();
return (name == null ? getMainWindow() : getWindow(name));

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.web;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* <p>$Id$</p>
*
* @author artamonov
*/
public class BackgroundTaskManager {
private transient Set<Thread> taskSet;
public BackgroundTaskManager() {
taskSet = Collections.synchronizedSet(new LinkedHashSet<Thread>());
}
/**
* Add task to task set
* @param task Task
*/
public void addTask(Thread task) {
taskSet.add(task);
}
/**
* Stop manage of stopped task
* @param task Task
*/
public void removeTask(Thread task) {
taskSet.remove(task);
}
/**
* Interrupt all tasks
*/
public void cleanupTasks() {
// Stop threads
for (Thread taskThread : taskSet) {
if (taskThread.isAlive())
taskThread.interrupt();
}
// Clean task set
taskSet.clear();
}
}

View File

@ -6,13 +6,13 @@
package com.haulmont.cuba.web;
import com.haulmont.cuba.core.sys.AppContext;
import com.haulmont.cuba.gui.AppConfig;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
import com.haulmont.cuba.gui.export.ExportDisplay;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import com.haulmont.cuba.web.filestorage.WebExportDisplay;
import com.haulmont.cuba.web.gui.WebComponentsFactory;
import com.haulmont.cuba.web.gui.utils.WebBackgroundWorker;
/**
* <p>$Id$</p>
@ -22,7 +22,6 @@ import com.haulmont.cuba.web.gui.utils.WebBackgroundWorker;
public class WebAppConfig extends AppConfig {
private volatile ComponentsFactory componentsFactory;
private volatile BackgroundWorker backgroundWorker;
@Override
protected ExportDisplay __createExportDisplay() {
@ -31,12 +30,7 @@ public class WebAppConfig extends AppConfig {
@Override
protected BackgroundWorker __getBackgroundWorker() {
if (backgroundWorker == null) {
synchronized (this) {
backgroundWorker = new WebBackgroundWorker();
}
}
return backgroundWorker;
return AppContext.getBean(BackgroundWorker.NAME);
}
@Override

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.web.gui.utils;
import com.haulmont.cuba.web.App;
import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Collection;
/**
* <p>$Id$</p>
*
* @author artamonov
*/
public class BackgroundWorkerListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
// Do nothing
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
WebApplicationContext applicationContext = WebApplicationContext.getApplicationContext(session);
final Collection<Application> applications = applicationContext.getApplications();
// Cleanup tasks in applications
for (Application app : applications) {
// Purge threads
((App)app).cleanupBackgroundTasks();
}
}
}

View File

@ -7,21 +7,16 @@
package com.haulmont.cuba.web.gui.utils;
import com.haulmont.cuba.core.global.TimeProvider;
import com.haulmont.cuba.gui.components.IFrame;
import com.haulmont.cuba.gui.components.Timer;
import com.haulmont.cuba.gui.components.Window;
import com.haulmont.cuba.gui.executors.BackgroundTask;
import com.haulmont.cuba.gui.executors.BackgroundTaskHandler;
import com.haulmont.cuba.gui.executors.BackgroundWorker;
import com.haulmont.cuba.web.App;
import com.haulmont.cuba.web.gui.WebTimer;
import com.haulmont.cuba.web.gui.WebWindow;
import com.vaadin.ui.Component;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static com.google.common.base.Preconditions.checkNotNull;
@ -31,42 +26,53 @@ import static com.google.common.base.Preconditions.checkNotNull;
*
* @author artamonov
*/
public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListener {
public class WebBackgroundWorker implements BackgroundWorker {
private static final int UI_TIMER_UPDATE_MS = 500;
private WatchDog watchDogThread;
private WatchDog watchDog;
public WebBackgroundWorker() {
watchDogThread = new WebWatchDog();
watchDog = new WebWatchDog();
}
@Override
public <T> BackgroundTaskHandler handle(final BackgroundTask<T> task) {
checkNotNull(task);
App appInstance = App.getInstance();
// UI timer
WebTimer pingTimer = new WebTimer(UI_TIMER_UPDATE_MS, true);
// create task executor
final WebTaskExecutor<T> taskExecutor = new WebTaskExecutor<T>(appInstance, task, pingTimer);
// add thread to taskSet
appInstance.addBackgroundTask(taskExecutor);
// create task handler
TaskExecutor<T> taskExecutor = new WebTaskExecutor<T>(task, pingTimer);
final TaskHandler<T> taskHandler = new TaskHandler<T>(taskExecutor, watchDogThread);
final TaskHandler<T> taskHandler = new TaskHandler<T>(taskExecutor, watchDog);
// add timer to AppWindow for UI ping
pingTimer.addTimerListener(new com.haulmont.cuba.gui.components.Timer.TimerListener() {
private long intentVersion = 0;
@Override
public void onTimer(Timer timer) {
// handle intents
if (!taskHandler.isCancelled()) {
if (intentVersion != taskExecutor.getIntentVersion()) {
intentVersion = taskExecutor.getIntentVersion();
taskExecutor.handleIntents();
}
}
// if completed
if (taskHandler.isDone()) {
task.done();
timer.stopTimer();
} else {
if (!taskHandler.isCancelled()) {
IFrame frame = task.getOwnerWindow().getFrame();
Component webWindow = ((WebWindow) frame).getComponent();
webWindow.requestRepaint();
}
}
}
@ -75,34 +81,29 @@ public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListene
// Do nothing
}
});
App.getInstance().addTimer(pingTimer, task.getOwnerWindow());
appInstance.addTimer(pingTimer, task.getOwnerWindow());
task.getOwnerWindow().addListener(new Window.CloseListener() {
@Override
public void windowClosed(String actionId) {
taskHandler.cancel(true);
}
});
return taskHandler;
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
// Do nothing
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
// Purge session tasks and threads
}
/**
* WatchDog
*/
private class WebWatchDog extends Thread implements WatchDog{
private class WebWatchDog extends Thread implements WatchDog {
private static final int WATCHDOG_INTERVAL = 100;
private static final int WATCHDOG_INTERVAL = 2000;
private volatile boolean watching = false;
private ReentrantLock watchLock;
private Set<TaskHandler> watches;
private final Set<TaskHandler> watches;
private WebWatchDog() {
watchLock = new ReentrantLock();
watches = new LinkedHashSet<TaskHandler>();
}
@ -113,33 +114,32 @@ public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListene
cleanupTasks();
}
} catch (Exception ignored) {
throw new RuntimeException(ignored);
}
}
private void cleanupTasks() throws Exception {
TimeUnit.MILLISECONDS.sleep(WATCHDOG_INTERVAL);
watchLock.lock();
synchronized (watches) {
long actual = TimeProvider.currentTimestamp().getTime();
long actual = TimeProvider.currentTimestamp().getTime();
List<TaskHandler> forRemove = new LinkedList<TaskHandler>();
for (TaskHandler task : watches) {
if (task.isCancelled() || task.isDone()) {
forRemove.add(task);
} else if (task.checkHangup(actual)) {
cancelTask(task);
forRemove.add(task);
List<TaskHandler> forRemove = new LinkedList<TaskHandler>();
for (TaskHandler task : watches) {
if (task.isCancelled() || task.isDone()) {
forRemove.add(task);
} else if (task.checkHangup(actual)) {
cancelTask(task);
forRemove.add(task);
}
}
watches.removeAll(forRemove);
}
watches.removeAll(forRemove);
watchLock.unlock();
}
private void cancelTask(TaskHandler task) {
task.cancel(true);
task.close();
}
private void startWatching() {
@ -148,15 +148,12 @@ public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListene
}
public void manageTask(TaskHandler backroundTask) {
watchLock.lock();
watches.add(backroundTask);
if (!watching) {
startWatching();
synchronized (watches) {
watches.add(backroundTask);
}
watchLock.unlock();
if (!watching)
startWatching();
}
}
@ -165,33 +162,60 @@ public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListene
*/
private class WebTaskExecutor<T> extends Thread implements TaskExecutor<T> {
private App app;
private BackgroundTask<T> runnableTask;
private WebTimer pingTimer;
private volatile boolean canceled = false;
private volatile boolean done = false;
private WebTaskExecutor(BackgroundTask<T> runnableTask, WebTimer pingTimer) {
private volatile long intentVersion = 0;
private final List<T> intents = Collections.synchronizedList(new LinkedList<T>());
private WebTaskExecutor(App app, BackgroundTask<T> runnableTask, WebTimer pingTimer) {
this.runnableTask = runnableTask;
this.pingTimer = pingTimer;
this.app = app;
runnableTask.setProgressHandler(this);
}
@Override
public void run() {
runnableTask.setInterrupted(false);
runnableTask.run();
done = true;
// Is done
if (!runnableTask.isInterrupted())
done = true;
// Remove from executions
app.removeBackgroundTask(this);
}
@Override
public void handleProgress(T ... changes) {
runnableTask.progress(Arrays.asList(changes));
public void handleProgress(T... changes) {
synchronized (intents) {
intentVersion++;
intents.addAll(Arrays.asList(changes));
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
public boolean cancelExecution(boolean mayInterruptIfRunning) {
boolean canceled = false;
runnableTask.setInterrupted(true);
if (super.isAlive() && mayInterruptIfRunning) {
// Interrupt
interrupt();
canceled = isInterrupted();
// Check
canceled = isInterrupted() || isDone();
// Remove task from execution
if (canceled)
app.removeBackgroundTask(this);
this.canceled = canceled;
}
if ((pingTimer != null) && canceled) {
pingTimer.stopTimer();
@ -216,5 +240,15 @@ public class WebBackgroundWorker implements BackgroundWorker, HttpSessionListene
public boolean isDone() {
return done;
}
public long getIntentVersion() {
return intentVersion;
}
public void handleIntents() {
synchronized (intents) {
runnableTask.progress(intents);
}
}
}
}

View File

@ -35,6 +35,8 @@
<bean id="cuba_FileUploading" class="com.haulmont.cuba.gui.upload.FileUploading"/>
<bean id="cuba_BackgroundWorker" class="com.haulmont.cuba.web.gui.utils.WebBackgroundWorker"/>
<!-- MBeans registration -->
<bean id="cuba_web_MBeanExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">

View File

@ -18,6 +18,10 @@
<listener-class>com.haulmont.cuba.web.sys.WebAppContextLoader</listener-class>
</listener>
<listener>
<listener-class>com.haulmont.cuba.web.gui.utils.BackgroundWorkerListener</listener-class>
</listener>
<servlet>
<servlet-name>cuba_servlet</servlet-name>
<servlet-class>com.haulmont.cuba.web.sys.CubaApplicationServlet