diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java
index 0c226e28ef3e5753e59f68d71a1c626fc3756747..ecb89be098456f5740bd19e59f90e99257550566 100644
--- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java
@@ -2,15 +2,11 @@ package cz.it4i.fiji.haas;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
 import java.util.Calendar;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.List;
-import java.util.Properties;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -29,8 +25,6 @@ import net.imagej.updater.util.Progress;
 
 public class Job {
 
-	private static final String JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY = "job.needDownload";
-
 	private static final String JOB_NAME = "job.name";
 
 	public static boolean isJobPath(Path p) {
@@ -47,27 +41,32 @@ public class Job {
 	private Supplier<HaaSClient> haasClientSupplier;
 
 	// private JobState state;
-	private Boolean needsDownload;
+	//private Boolean needsDownload;
 	private JobInfo jobInfo;
 	private Long jobId;
 
-	private String name;
+	
+	private PropertyHolder propertyHolder;
 
 	public Job(String name, Path basePath, Supplier<HaaSClient> haasClientSupplier) throws IOException {
 		this(haasClientSupplier);
 		HaaSClient client = this.haasClientSupplier.get();
 		long id = client.createJob(name, Collections.emptyList());
 		jobDir = basePath.resolve("" + id);
-		this.name = name;
+		propertyHolder = new PropertyHolder(jobDir.resolve(JOB_INFO_FILE));
 		Files.createDirectory(jobDir);
-		updateNeedsDownload();
+		setName(name);
+		
+	}
+
+	public void setName(String name) {
+		setProperty(JOB_NAME, name);
 	}
 
-	public Job(Path p, Supplier<HaaSClient> haasClientSupplier) throws IOException {
+	public Job(Path p, Supplier<HaaSClient> haasClientSupplier) {
 		this(haasClientSupplier);
 		jobDir = p;
-		loadJobInfo();
-		updateNeedsDownload();
+		propertyHolder = new PropertyHolder(jobDir.resolve(JOB_INFO_FILE));
 	}
 
 	public void uploadFiles(Iterable<UploadingFile> files, Progress notifier) {
@@ -87,13 +86,11 @@ public class Job {
 		client.submitJob(jobId);
 	}
 
-	private Job(Supplier<HaaSClient> haasClientSupplier) throws IOException {
+	private Job(Supplier<HaaSClient> haasClientSupplier) {
 		this.haasClientSupplier = haasClientSupplier;
 	}
 
-	public boolean needsDownload() {
-		return needsDownload != null && needsDownload;
-	}
+	
 
 	synchronized public long getJobId() {
 		if (jobId == null) {
@@ -103,7 +100,7 @@ public class Job {
 	}
 
 	public void download(Progress notifier) {
-		download(x -> true, notifier, false);
+		download(x -> true, notifier);
 	}
 
 	public Path storeDataInWorkdirectory(UploadingFile uploadingFile) throws IOException {
@@ -114,19 +111,8 @@ public class Job {
 		return result;
 	}
 
-	synchronized public void download(Predicate<String> predicate, Progress notifier, boolean allowAgain) {
-		if (!allowAgain && !needsDownload()) {
-			throw new IllegalStateException("Job: " + getJobId() + " doesn't need download");
-		}
+	synchronized public void download(Predicate<String> predicate, Progress notifier) {
 		haasClientSupplier.get().download(getJobId(), jobDir, predicate, new P_ProgressNotifierAdapter(notifier));
-		if(!allowAgain) {
-			needsDownload = false;
-			try {
-				saveJobinfo();
-			} catch (IOException e) {
-				log.error(e);
-			}
-		}
 	}
 
 	public JobState getState() {
@@ -157,14 +143,12 @@ public class Job {
 		return Files.newInputStream(jobDir.resolve(name));
 	}
 
-	public void setProperty(String name, String value) throws IOException {
-		Properties prop = loadPropertiesIfExists();
-		prop.setProperty(name, value);
-		storeProperties(prop);
+	public void setProperty(String name, String value) {
+		propertyHolder.setValue(name, value);
 	}
 
-	public String getProperty(String name) throws IOException {
-		return loadPropertiesIfExists().getProperty(name);
+	public String getProperty(String name) {
+		return propertyHolder.getValue(name);
 	}
 
 	public void updateInfo() {
@@ -174,49 +158,7 @@ public class Job {
 	public Path getDirectory() {
 		return jobDir;
 	}
-
-	synchronized private void updateNeedsDownload() throws IOException {
-		if (needsDownload == null
-				&& EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled).contains(getState())) {
-			needsDownload = true;
-		}
-		saveJobinfo();
-	}
-
-	private synchronized void saveJobinfo() throws IOException {
-		Properties prop = loadPropertiesIfExists();
-		if (needsDownload != null) {
-			prop.setProperty(JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY, needsDownload.toString());
-		}
-		prop.setProperty(JOB_NAME, name);
-		storeProperties(prop);
-	}
-
-	private void storeProperties(Properties prop) throws IOException {
-		try (OutputStream ow = Files.newOutputStream(jobDir.resolve(JOB_INFO_FILE),
-				StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE)) {
-			prop.store(ow, null);
-		}
-	}
-
-	private synchronized void loadJobInfo() throws IOException {
-		Properties prop = loadPropertiesIfExists();
-		if (prop.containsKey(JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY)) {
-			needsDownload = Boolean.parseBoolean(prop.getProperty(JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY));
-		}
-		name = prop.getProperty(JOB_NAME);
-	}
-
-	private Properties loadPropertiesIfExists() throws IOException {
-		Properties prop = new Properties();
-		if (Files.exists(jobDir.resolve(JOB_INFO_FILE))) {
-			try (InputStream is = Files.newInputStream(jobDir.resolve(JOB_INFO_FILE))) {
-				prop.load(is);
-			}
-		}
-		return prop;
-	}
-
+	
 	private JobInfo getJobInfo() {
 		if (jobInfo == null) {
 			updateJobInfo();
@@ -226,11 +168,6 @@ public class Job {
 
 	private void updateJobInfo() {
 		jobInfo = haasClientSupplier.get().obtainJobInfo(getJobId());
-		try {
-			updateNeedsDownload();
-		} catch (IOException e) {
-			log.error(e.getMessage(), e);
-		}
 	}
 
 	private static boolean isValidPath(Path path) {
diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/JobManager.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/JobManager.java
index c26976353527ff393ad39c3dcade59cc0e88991c..fe2d9dddfba0ce2d25c2a777b05509b997362479 100644
--- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/JobManager.java
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/JobManager.java
@@ -63,20 +63,17 @@ public class JobManager {
 		return result;
 	}
 
-	public Iterable<JobInfo> getJobsNeedingDownload() {
-		return () -> jobs.stream().filter(j -> j.needsDownload()).map(j -> new JobInfo(j)).iterator();
-	}
-
-	public Collection<JobInfo> getJobs() throws IOException {
+	public Collection<JobInfo> getJobs() {
 		if (jobs == null) {
 			jobs = new LinkedList<>();
-			Files.list(this.workDirectory).filter(p -> Files.isDirectory(p) && Job.isJobPath(p)).forEach(p -> {
-				try {
-					jobs.add(new Job(p, this::getHaasClient));
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-			});
+			try {
+				Files.list(this.workDirectory).filter(p -> Files.isDirectory(p) && Job.isJobPath(p)).forEach(p -> {
+						jobs.add(new Job(p, this::getHaasClient));
+					
+				});
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
 		}
 		return jobs.stream().map(j -> new JobInfo(j)).collect(Collectors.toList());
 	}
@@ -146,10 +143,6 @@ public class JobManager {
 			return job.getState();
 		}
 
-		public boolean needsDownload() {
-			return job.needsDownload();
-		}
-
 		public String getCreationTime() {
 			return getStringFromTimeSafely(job.getCreationTime());
 		}
@@ -163,11 +156,11 @@ public class JobManager {
 		}
 
 		public void downloadData(Progress notifier) {
-			downloadData(x -> true, notifier, false);
+			downloadData(x -> true, notifier);
 		}
 
-		public void downloadData(Predicate<String> predicate, Progress notifier, boolean allowAgain) {
-			job.download(predicate, notifier, allowAgain);
+		public void downloadData(Predicate<String> predicate, Progress notifier) {
+			job.download(predicate, notifier);
 			fireValueChangedEvent();
 
 		}
@@ -202,12 +195,12 @@ public class JobManager {
 			return job.openLocalFile(name);
 		}
 
-		public void setProperty(String name, String value) throws IOException {
+		public void setProperty(String name, String value) {
 			job.setProperty(name, value);
 
 		}
 
-		public String getProperty(String name) throws IOException {
+		public String getProperty(String name) {
 			return job.getProperty(name);
 		}
 
diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/PropertyHolder.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/PropertyHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3ccf7bc6614ed7551dac840b3efb355468df364
--- /dev/null
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/PropertyHolder.java
@@ -0,0 +1,62 @@
+package cz.it4i.fiji.haas;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Properties;
+
+public class PropertyHolder {
+	private Path storage;
+	private Properties properties;
+
+	public PropertyHolder(Path storage) {
+		super();
+		this.storage = storage;
+	}
+
+	public String getValue(String key) {
+		Properties properties = getProperties();
+		return properties.getProperty(key);
+	}
+
+	public void setValue(String key, String value) {
+		Properties prop = getProperties();
+		prop.setProperty(key, value);
+		try {
+			storeProperties(prop);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private Properties getProperties() {
+		if (properties == null) {
+			try {
+				properties = loadPropertiesIfExists();
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+		}
+		return properties;
+	}
+
+	private Properties loadPropertiesIfExists() throws IOException {
+		Properties prop = new Properties();
+		if (Files.exists(storage)) {
+			try (InputStream is = Files.newInputStream(storage)) {
+				prop.load(is);
+			}
+		}
+		return prop;
+	}
+
+	private void storeProperties(Properties prop) throws IOException {
+		try (OutputStream ow = Files.newOutputStream(storage, StandardOpenOption.TRUNCATE_EXISTING,
+				StandardOpenOption.CREATE)) {
+			prop.store(ow, null);
+		}
+	}
+}
diff --git a/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/commands/CheckStatusOfHaaS.java b/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/commands/CheckStatusOfHaaS.java
index 28961641813b04c9b9ee8f359c500197489c93ae..49fcbf48144941299d47150a04374ea6c9673c84 100644
--- a/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/commands/CheckStatusOfHaaS.java
+++ b/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/commands/CheckStatusOfHaaS.java
@@ -2,7 +2,6 @@ package cz.it4i.fiji.haas_snakemake_spim.commands;
 
 import java.awt.Frame;
 import java.io.File;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collection;
@@ -51,29 +50,27 @@ public class CheckStatusOfHaaS implements Command {
 
 	@Override
 	public void run() {
-		try {
-			jobManager = new JobManager(getWorkingDirectoryPath(),TestingConstants.getSettings());
-			if (uiService.isHeadless()) {
-				downloadAll();
-			} else {
-				CheckStatusOfHaaSWindow window;
-				window = ModalDialogs.doModal(new CheckStatusOfHaaSWindow(getFrame(), context),WindowConstants.DISPOSE_ON_CLOSE);
-				ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(window),WindowConstants.DO_NOTHING_ON_CLOSE);
-				dialog.setTitle("Downloading info about jobs");
-				Collection<JobInfo> jobs = jobManager.getJobs();
-				int count = 0;
-				for (JobInfo ji : jobs) {
-					String item;
-					dialog.addItem(item = "job id:" + ji.getId());
-					window.addJob(ji);
-					dialog.itemDone(item);
-					dialog.setCount(count, jobs.size());
-					count++;
-				}
-				dialog.done();
+		jobManager = new JobManager(getWorkingDirectoryPath(), TestingConstants.getSettings());
+		if (uiService.isHeadless()) {
+			downloadAll();
+		} else {
+			CheckStatusOfHaaSWindow window;
+			window = ModalDialogs.doModal(new CheckStatusOfHaaSWindow(getFrame(), context),
+					WindowConstants.DISPOSE_ON_CLOSE);
+			ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(window),
+					WindowConstants.DO_NOTHING_ON_CLOSE);
+			dialog.setTitle("Downloading info about jobs");
+			Collection<JobInfo> jobs = jobManager.getJobs();
+			int count = 0;
+			for (JobInfo ji : jobs) {
+				String item;
+				dialog.addItem(item = "job id:" + ji.getId());
+				window.addJob(ji);
+				dialog.itemDone(item);
+				dialog.setCount(count, jobs.size());
+				count++;
 			}
-		} catch (IOException e) {
-			log.error(e);
+			dialog.done();
 		}
 
 	}
@@ -92,7 +89,7 @@ public class CheckStatusOfHaaS implements Command {
 	}
 
 	private void downloadAll() {
-		for (JobInfo id : jobManager.getJobsNeedingDownload()) {
+		for (JobInfo id : jobManager.getJobs()) {
 			System.out.println("Job " + id.getId() + " needs download");
 			jobManager.downloadJob(id.getId(), new DummyProgress());
 		}
diff --git a/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/ui/CheckStatusOfHaaSController.java b/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/ui/CheckStatusOfHaaSController.java
index 38092ad763dcea820b46ae9e882b6e27b710a8a0..6e73eb6b7d24162c799ffaa597d551be88a80775 100644
--- a/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/ui/CheckStatusOfHaaSController.java
+++ b/haas-snakemake-spim/src/main/java/cz/it4i/fiji/haas_snakemake_spim/ui/CheckStatusOfHaaSController.java
@@ -69,7 +69,7 @@ public class CheckStatusOfHaaSController implements FXFrame.Controller {
 				}
 				JobInfo job = jobs.getSelectionModel().getSelectedItem();
 
-				if (job != null && job.needsDownload()) {
+				if (job != null) {
 					download.setDisable(false);
 				} else {
 					download.setDisable(true);
@@ -80,7 +80,7 @@ public class CheckStatusOfHaaSController implements FXFrame.Controller {
 
 	private void initTable() {
 		setCellValueFactory(0, j -> j.getId().toString());
-		setCellValueFactory(1, j -> j.getState().toString() + (j.needsDownload() ? " - needs download" : ""));
+		setCellValueFactory(1, j -> j.getState().toString());
 		setCellValueFactory(2, j -> j.getCreationTime().toString());
 		setCellValueFactory(3, j -> j.getStartTime().toString());
 		setCellValueFactory(4, j -> j.getEndTime().toString());
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java
index 9f4ee84015e440a668e12371e454a49405016087..79b2e16d31df381f765d5993e5e949734ef53325 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java
@@ -85,8 +85,7 @@ public class ManageSPIMBenchmark implements Command {
 		// Launch ImageJ as usual.
 		final ImageJ ij = new ImageJ();
 		ij.launch(args);
-
-		//ij.command().run(ManageSPIMBenchmark.class, true);
+		ij.command().run(ManageSPIMBenchmark.class, true);
 	}
 
 }
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java
index 5f9282957fc03623f594014949eb7b2ea71fdf52..4fb7751e8b2a7ded9cfc2725c5e3be78623d4059 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java
@@ -33,6 +33,8 @@ import net.imagej.updater.util.Progress;
 
 public class BenchmarkJobManager {
 
+	private static final String JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY = "job.needDownload";
+	
 	private static Logger log = LoggerFactory
 			.getLogger(cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.class);
 
@@ -51,6 +53,7 @@ public class BenchmarkJobManager {
 			String outputName = getOutputName(jobInfo.openLocalFile(Constants.CONFIG_YAML));
 			jobInfo.submit();
 			jobInfo.setProperty(Constants.SPIM_OUTPUT_FILENAME_PATTERN, outputName);
+			setDownloaded(false);
 		}
 
 		public JobState getState() {
@@ -59,19 +62,18 @@ public class BenchmarkJobManager {
 
 		public void downloadData(Progress progress) throws IOException {
 			JobInfo ji = jobInfo;
-			if (ji.needsDownload()) {
-				if (ji.getState() == JobState.Finished) {
-					String filePattern = ji.getProperty(Constants.SPIM_OUTPUT_FILENAME_PATTERN);
-					ji.downloadData(downloadFinishedData(filePattern), progress, false);
-				} else if (ji.getState() == JobState.Failed) {
-					ji.downloadData(downloadFailedData(), progress, false);
-				}
+			if (ji.getState() == JobState.Finished) {
+				String filePattern = ji.getProperty(Constants.SPIM_OUTPUT_FILENAME_PATTERN);
+				ji.downloadData(downloadFinishedData(filePattern), progress);
+			} else if (ji.getState() == JobState.Failed) {
+				ji.downloadData(downloadFailedData(), progress);
 			}
+			setDownloaded(true);
 		}
 
 		public void downloadStatistics(Progress progress) throws IOException {
 			JobInfo ji = jobInfo;
-			ji.downloadData(BenchmarkJobManager.downloadStatistics(), progress, true);
+			ji.downloadData(BenchmarkJobManager.downloadStatistics(), progress);
 			Path resultFile = ji.getDirectory().resolve(Constants.BENCHMARK_RESULT_FILE);
 			if (resultFile != null)
 				BenchmarkJobManager.formatResultFile(resultFile);
@@ -125,7 +127,7 @@ public class BenchmarkJobManager {
 		}
 
 		public boolean downloaded() {
-			return !jobInfo.needsDownload();
+			return getDownloaded();
 		}
 
 		public Job update() {
@@ -136,6 +138,16 @@ public class BenchmarkJobManager {
 		public Path getDirectory() {
 			return jobInfo.getDirectory();
 		}
+		
+
+		private void setDownloaded(boolean b) {
+			jobInfo.setProperty(JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY, b + "");
+		}
+		
+		private boolean getDownloaded() {
+			String downloadedStr = jobInfo.getProperty(JOB_HAS_DATA_TO_DOWNLOAD_PROPERTY);
+			return downloadedStr != null && Boolean.parseBoolean(downloadedStr);
+		}
 	}
 
 	private JobManager jobManager;
@@ -151,10 +163,10 @@ public class BenchmarkJobManager {
 	}
 
 	public Collection<Job> getJobs() throws IOException {
-
 		return jobManager.getJobs().stream().map(this::convertJob).collect(Collectors.toList());
 	}
 
+
 	private HaaSClient.UploadingFile getUploadingFile() {
 		return new UploadingFileFromResource("", Constants.CONFIG_YAML);
 	}
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java
index 06779ad9b2b18522c326b6422896a557ad820907..2dcdc852be4c5132da36037174118f856e30e3e9 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java
@@ -4,7 +4,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 public interface Constants {
-	long HAAS_UPDATE_TIMEOUT = 1000;
+	long HAAS_UPDATE_TIMEOUT = 30000;
 	String HAAS_JOB_NAME = "HaaSSPIMBenchmark";
 	int HAAS_CLUSTER_NODE_TYPE = 6;
 	int HAAS_TEMPLATE_ID = 4;
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/FXFrameExecutorService.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/FXFrameExecutorService.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfe5eaf1b768fd34b675da0cb7402e534804d7df
--- /dev/null
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/FXFrameExecutorService.java
@@ -0,0 +1,17 @@
+package cz.it4i.fiji.haas_spim_benchmark.core;
+
+import java.util.concurrent.Executor;
+
+import cz.it4i.fiji.haas.ui.FXFrame;
+
+public class FXFrameExecutorService implements Executor{
+
+	
+	@Override
+	public void execute(Runnable command) {
+		FXFrame.runOnFxThread(() -> {
+			command.run();
+		});
+	}
+
+}
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java
index d1b196b3d8d7145cfe10c3b97a0ba08acc209366..e02876ccc5aba1044a04b452d48d078cbc62985d 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java
@@ -11,8 +11,11 @@ import java.util.Map;
 import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -32,6 +35,7 @@ import cz.it4i.fiji.haas_java_client.JobState;
 import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager;
 import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.Job;
 import cz.it4i.fiji.haas_spim_benchmark.core.Constants;
+import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService;
 import javafx.fxml.FXML;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableView;
@@ -54,7 +58,9 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 
 	private Window root;
 
-	private ExecutorService executorService;
+	private ExecutorService executorServiceUI;
+	private ExecutorService executorServiceWS;
+	private Executor executorServiceFX = new FXFrameExecutorService();
 
 	private Timer timer;
 
@@ -63,7 +69,8 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 
 	@Override
 	public void init(Window frame) {
-		executorService = Executors.newSingleThreadExecutor();
+		executorServiceWS = Executors.newSingleThreadExecutor();
+		executorServiceUI = Executors.newSingleThreadExecutor();
 		timer = new Timer();
 		timer.scheduleAtFixedRate(new TimerTask() {
 			@Override
@@ -91,89 +98,108 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 
 	private void initMenu() {
 		TableViewContextMenu<Job> menu = new TableViewContextMenu<>(jobs);
-		menu.addItem("Create job", x -> executeJobActionAsync("Creating job", false, p -> manager.createJob()), j -> true);
-		menu.addItem("Start job", job -> executeJobActionAsync("Starting job", p -> job.startJob(p)),
-				job -> notNullValue(job, j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished));
-		menu.addItem("Download result", job -> executeJobActionAsync("Downloading data", p -> job.downloadData(p)),
+		menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()),
+				j -> true);
+		menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> job.startJob(p)),
+				job -> notNullValue(job,
+						j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished));
+		menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.downloadData(p)),
 				job -> notNullValue(job,
 						j -> EnumSet.of(JobState.Failed, JobState.Finished).contains(j.getState()) && !j.downloaded()));
 		menu.addItem("Download statistics",
-				job -> executeJobActionAsync("Downloading data", p -> job.downloadStatistics(p)),
-				job -> notNullValue(job, j -> j.getState() == JobState.Finished));		
-		
-		menu.addItem("Show output", j -> new JobOutputView(root, executorService, j, Constants.HAAS_UPDATE_TIMEOUT),
+				job -> executeWSCallAsync("Downloading data", p -> job.downloadStatistics(p)),
+				job -> notNullValue(job, j -> j.getState() == JobState.Finished));
+
+		menu.addItem("Show output", j -> new JobOutputView(root, executorServiceUI, j, Constants.HAAS_UPDATE_TIMEOUT),
 				job -> notNullValue(job,
 						j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Running).contains(j.getState())));
-		menu.addItem("Open", j->open(j), x->true);
+		menu.addItem("Open", j -> open(j), x -> true);
 		menu.addItem("Update table", job -> updateJobs(), j -> true);
 
 	}
 
 	private void open(Job j) {
-		executorService.execute(() -> {
-		Desktop desktop = Desktop.getDesktop();
-		try {
-			desktop.open(j.getDirectory().toFile());
-		} catch (IOException e) {
-			log.error(e.getMessage(), e);
-		}});
-	}
-	
-	private void executeJobActionAsync(String title, P_JobAction action) {
-		executeJobActionAsync(title, true, action);
+		executorServiceUI.execute(() -> {
+			Desktop desktop = Desktop.getDesktop();
+			try {
+				desktop.open(j.getDirectory().toFile());
+			} catch (IOException e) {
+				log.error(e.getMessage(), e);
+			}
+		});
 	}
 
-	private void executeJobActionAsync(String title, boolean update, P_JobAction action) {
-		executorService.execute(() -> {
+	private <V> void executeAsync(Executor executor, Callable<V> action, Consumer<V> postAction) {
+		executor.execute(() -> {
+			V result;
 			try {
-				ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(root, title),
-						WindowConstants.DO_NOTHING_ON_CLOSE);
-				action.doAction(dialog);
-				dialog.done();
-				if(update) {
-					updateJobs();
-				}
-			} catch (IOException e) {
+				result = action.call();
+				postAction.accept(result);
+			} catch (Exception e) {
 				log.error(e.getMessage(), e);
 			}
+			
 		});
 	}
 
+	private void executeWSCallAsync(String title, P_JobAction action) {
+		executeWSCallAsync(title, true, action);
+	}
+
+	private void executeWSCallAsync(String title, boolean update, P_JobAction action) {
+		executeAsync(executorServiceWS, (Callable<Void>) ()->{
+			ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(root, title),
+					WindowConstants.DO_NOTHING_ON_CLOSE);
+			action.doAction(dialog);
+			dialog.done();
+			return null;
+		}, x-> {if(update)  updateJobs(); });
+	}
+
 	private void updateJobs() {
 		updateJobs(true);
 	}
 
 	private void updateJobs(boolean showProgress) {
-		executorService.execute(() -> {
+		executorServiceUI.execute(() -> {
 			Progress progress = showProgress
 					? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"),
 							WindowConstants.DO_NOTHING_ON_CLOSE)
 					: new DummyProgress();
-
-			Set<Job> old = new HashSet<Job>(jobs.getItems());
-			Map<Job, Job> actual;
 			try {
-				actual = manager.getJobs().stream().map(job -> job.update())
-						.collect(Collectors.toMap(job -> job, job -> job));
-			} catch (IOException e) {
-				throw new RuntimeException(e);
+				manager.getJobs().forEach(job -> job.update());
+			} catch (IOException e1) {
+				throw new RuntimeException(e1);
 			}
-			for (Job job : old) {
-				if (!actual.containsKey(job)) {
-					jobs.getItems().remove(job);
-				} else {
-					job.update(actual.get(job));
+			executorServiceUI.execute(() -> {
+				
+
+				Set<Job> old = new HashSet<Job>(jobs.getItems());
+				Map<Job, Job> actual;
+				try {
+					actual = manager.getJobs().stream().
+							collect(Collectors.toMap(job -> job, job -> job));
+				} catch (IOException e) {
+					throw new RuntimeException(e);
 				}
-			}
-			progress.done();
-			FXFrame.runOnFxThread(() -> {
-				for (Job job : actual.keySet()) {
-					if (!old.contains(job)) {
-						jobs.getItems().add(job);
+				for (Job job : old) {
+					if (!actual.containsKey(job)) {
+						jobs.getItems().remove(job);
+					} else {
+						job.update(actual.get(job));
 					}
 				}
+				progress.done();
+				executorServiceFX.execute(() -> {
+					for (Job job : actual.keySet()) {
+						if (!old.contains(job)) {
+							jobs.getItems().add(job);
+						}
+					}
+				});
 			});
 		});
+		
 	}
 
 	private void initTable() {
@@ -196,7 +222,8 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 	}
 
 	private void dispose() {
-		executorService.shutdown();
+		executorServiceUI.shutdown();
+		executorServiceWS.shutdown();
 		timer.cancel();
 	}
 }