diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java
index d210a4f4575f278890277e47b89868ee46f0515a..ada57f4df3f4bd9cf3fe995a7929e562607fbb2a 100644
--- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java
@@ -6,37 +6,44 @@ import java.util.Map;
 import java.util.function.Consumer;
 import java.util.function.Function;
 
+import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus;
 import javafx.beans.value.ObservableValue;
 
 public class ObservableValueRegistry<T> {
 
-	private Function<T, Boolean> updateFunction;
-	private Function<T, Boolean> validateFunction;
+	private Function<T,UpdateStatus> updateFunction;
 	private Consumer<T> removeConsumer;
 	
 	
-	public ObservableValueRegistry(Function<T, Boolean> validateFunction, Function<T, Boolean> updateFunction,
+	public ObservableValueRegistry(Function<T, UpdateStatus> updateFunction,
 			Consumer<T> removeConsumer) {
 		super();
-		this.validateFunction = validateFunction;
 		this.updateFunction = updateFunction;
-		this.removeConsumer = removeConsumer;
+		this.removeConsumer = t-> {
+			removeConsumer.accept(t);
+			remove(t);
+		};
+		
 	}
 
 	private Map<T,UpdatableObservableValue<T>> map = new HashMap<>(); 
 	
 	public  ObservableValue<T> addIfAbsent(T value) {
-		UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction, validateFunction));
+		UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction));
 		return uov;
 	}
 	
-	public ObservableValue<T> remove(T value) {
+	public ObservableValue<T> get(T value) {
+		return map.get(value);
+	}
+	
+	private ObservableValue<T> remove(T value) {
 		return map.get(value);
 	}
 	
 	public void update() {
 		for (UpdatableObservableValue<T> value : new LinkedList<>(map.values())) {
-			if(!value.update()) {
+			if(value.update() == UpdateStatus.Deleted) {
 				removeConsumer.accept(value.getValue());
 			}
 		}
diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java
index 3bd8930da1e6dbe718c8cadeb8bb106210ab947c..41c9dedab6674af2303bd664c8a2f5ec23edb0d1 100644
--- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java
@@ -6,16 +6,21 @@ import javafx.beans.value.ObservableValueBase;
 
 public class UpdatableObservableValue<T> extends ObservableValueBase<T>{
 
+	public enum UpdateStatus {
+		Deleted,
+		Updated,
+		NotUpdated
+	}
+	
 	private T wrapped;
-	private Function<T,Boolean> updateFunction;
-	private Function<T,Boolean> validateFunction;
+	private Function<T,UpdateStatus> updateFunction;
 	
 	
-	public UpdatableObservableValue(T wrapped, Function<T, Boolean> updateFunction, Function<T, Boolean> validateFunction) {
+	public UpdatableObservableValue(T wrapped, Function<T, UpdateStatus> updateFunction) {
 		super();
 		this.wrapped = wrapped;
 		this.updateFunction = updateFunction;
-		this.validateFunction = validateFunction;
+		
 	}
 
 	@Override
@@ -24,14 +29,38 @@ public class UpdatableObservableValue<T> extends ObservableValueBase<T>{
 		return wrapped;
 	}
 
-	public boolean update() {
-		if(!validateFunction.apply(wrapped)) {
-			return false;
-		}
-		if(updateFunction.apply(wrapped)) {
+	public UpdateStatus update() {
+		UpdateStatus status = updateFunction.apply(wrapped);
+		switch (status) {
+		case Updated:
 			fireValueChangedEvent();
+		default:
+			return status;
 		}
+
+	}
+	@Override
+	public int hashCode() {
+		return wrapped.hashCode();
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		@SuppressWarnings("unchecked")
+		UpdatableObservableValue<T> other = (UpdatableObservableValue<T>) obj;
+		if (wrapped == null) {
+			if (other.wrapped != null)
+				return false;
+		} else if (!wrapped.equals(other.wrapped))
+			return false;
 		return 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 ef0058bd2819e88c09a48aeb92023f70794d3b31..eeb218aa001c44cdd7fc7cc0655df445de1c33de 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,7 +33,6 @@ import cz.it4i.fiji.haas_java_client.HaaSClient;
 import cz.it4i.fiji.haas_java_client.JobState;
 import cz.it4i.fiji.haas_java_client.Settings;
 import cz.it4i.fiji.haas_java_client.SynchronizableFileType;
-import javafx.beans.value.ObservableValueBase;
 import net.imagej.updater.util.Progress;
 
 public class BenchmarkJobManager {
@@ -46,10 +45,9 @@ public class BenchmarkJobManager {
 	private JobManager jobManager;
 	
 
-	public final class BenchmarkJob extends ObservableValueBase<BenchmarkJob> implements HaaSOutputSource {
+	public final class BenchmarkJob implements HaaSOutputSource {
 		
 		private Job job;
-		private JobState oldState;
 		
 		private HaaSOutputHolder outputOfSnakemake;
 
@@ -67,11 +65,12 @@ public class BenchmarkJobManager {
 				return false;
 			}
 		};
-
+		
+		
 		public BenchmarkJob(Job job) {
 			super();
 			this.job = job;
-			outputOfSnakemake = new HaaSOutputHolderImpl(getValue(), SynchronizableFileType.StandardErrorFile);
+			outputOfSnakemake = new HaaSOutputHolderImpl(this, SynchronizableFileType.StandardErrorFile);
 		}
 
 		public void startJob(Progress progress) throws IOException {
@@ -79,12 +78,11 @@ public class BenchmarkJobManager {
 			String outputName = getOutputName(job.openLocalFile(Constants.CONFIG_YAML));
 			job.submit();
 			job.setProperty(Constants.SPIM_OUTPUT_FILENAME_PATTERN, outputName);
-			fireValueChangedEvent();
 			setDownloaded(false);
 		}
 
 		public JobState getState() {
-			return oldState = job.getState();
+			return job.getState();
 		}
 
 		public void downloadData(Progress progress) throws IOException {
@@ -94,13 +92,12 @@ public class BenchmarkJobManager {
 			} else if (job.getState() == JobState.Failed) {
 				job.download(downloadFailedData(), progress);
 			}
-			fireValueChangedEvent();
+			
 			setDownloaded(true);
 		}
 
 		public void downloadStatistics(Progress progress) throws IOException {			
 			job.download(BenchmarkJobManager.downloadStatistics(), progress);
-			fireValueChangedEvent();
 			Path resultFile = job.getDirectory().resolve(Constants.BENCHMARK_RESULT_FILE);
 			if (resultFile != null)
 				BenchmarkJobManager.formatResultFile(resultFile);
@@ -130,11 +127,6 @@ public class BenchmarkJobManager {
 			return time != null ? time.getTime().toString() : "N/A";
 		}
 
-		@Override
-		public BenchmarkJob getValue() {
-			return this;
-		}
-
 		@Override
 		public int hashCode() {
 			return Long.hashCode(job.getId());
@@ -149,11 +141,6 @@ public class BenchmarkJobManager {
 			return false;
 		}
 
-		public void update(BenchmarkJob benchmarkJob) {
-			job = benchmarkJob.job;
-			if (benchmarkJob.job.getState() != oldState)
-				fireValueChangedEvent();
-		}
 		
 		public boolean downloaded() {
 			return getDownloaded();
@@ -161,11 +148,9 @@ public class BenchmarkJobManager {
 
 		public BenchmarkJob update() {
 			job.updateInfo();
-			if (!job.getState().equals(oldState))
-				fireValueChangedEvent();
 			return this;
 		}
-
+	
 		public Path getDirectory() {
 			return job.getDirectory();
 		}
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 cd35978fd422aa0ba1ec822de5d6d31faae4e110..7606d57caa4eba642e00cdd97fab09108ea5665a 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
@@ -5,9 +5,9 @@ import java.awt.Window;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.EnumSet;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -17,7 +17,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.function.Function;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 import javax.swing.WindowConstants;
 
@@ -34,22 +33,23 @@ import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager;
 import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob;
 import cz.it4i.fiji.haas_spim_benchmark.core.Constants;
 import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService;
+import javafx.beans.value.ObservableValue;
 import javafx.fxml.FXML;
 import javafx.scene.control.TableView;
 import net.imagej.updater.util.Progress;
 
 public class BenchmarkSPIMController implements FXFrame.Controller {
 
-	private static boolean notNullValue(BenchmarkJob j, Predicate<BenchmarkJob> pred) {
-		if (j == null) {
+	private static boolean notNullValue(ObservableValue<BenchmarkJob> j, Predicate<BenchmarkJob> pred) {
+		if (j == null || j.getValue() == null) {
 			return false;
 		} else {
-			return pred.test(j);
+			return pred.test(j.getValue());
 		}
 	}
 
 	@FXML
-	private TableView<BenchmarkJob> jobs;
+	private TableView<ObservableValue<BenchmarkJob>> jobs;
 
 	private BenchmarkJobManager manager;
 
@@ -60,6 +60,7 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 	private Executor executorServiceFX = new FXFrameExecutorService();
 
 	private Timer timer;
+	private ObservableBenchmarkJobRegistry registry;
 
 	private static Logger log = LoggerFactory
 			.getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.BenchmarkSPIMController.class);
@@ -94,15 +95,15 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 	}
 
 	private void initMenu() {
-		TableViewContextMenu<BenchmarkJob> menu = new TableViewContextMenu<>(jobs);
+		TableViewContextMenu<ObservableValue<BenchmarkJob>> menu = new TableViewContextMenu<>(jobs);
 		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)),
+		menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> job.getValue().startJob(p)),
 				job -> notNullValue(job,
 						j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished));
 
 		menu.addItem("Show progress", job -> {
 			try {
-				new SPIMPipelineProgressViewWindow(root, job).setVisible(true);
+				new SPIMPipelineProgressViewWindow(root, job.getValue()).setVisible(true);
 			} catch (IOException e) {
 				// TODO Auto-generated catch block
 				log.error(e.getMessage(), e);
@@ -110,17 +111,19 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 		}, job -> notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Finished
 				|| j.getState() == JobState.Failed));
 
-		menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.downloadData(p)),
+		menu.addItem("Download result",
+				job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadData(p)),
 				job -> notNullValue(job,
 						j -> EnumSet.of(JobState.Failed, JobState.Finished).contains(j.getState()) && !j.downloaded()));
 		menu.addItem("Download statistics",
-				job -> executeWSCallAsync("Downloading data", p -> job.downloadStatistics(p)),
+				job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadStatistics(p)),
 				job -> notNullValue(job, j -> j.getState() == JobState.Finished));
 
-		menu.addItem("Show output", j -> new JobOutputView(root, executorServiceUI, j, Constants.HAAS_UPDATE_TIMEOUT),
+		menu.addItem("Show output",
+				j -> new JobOutputView(root, executorServiceUI, j.getValue(), 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.getValue()), x -> true);
 		menu.addItem("Update table", job -> updateJobs(), j -> true);
 
 	}
@@ -158,46 +161,36 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
 	}
 
 	private void updateJobs(boolean showProgress) {
-		executorServiceUI.execute(() -> {
-			Progress progress = showProgress
-					? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"),
-							WindowConstants.DO_NOTHING_ON_CLOSE)
-					: new DummyProgress();
-			try {
-				manager.getJobs().forEach(job -> job.update());
-			} catch (IOException e1) {
-				throw new RuntimeException(e1);
-			}
+		executorServiceWS.execute(() -> {
+
+			registry.update();
 			executorServiceUI.execute(() -> {
+				Progress progress = showProgress
+						? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"),
+								WindowConstants.DO_NOTHING_ON_CLOSE)
+						: new DummyProgress();
 
-				Set<BenchmarkJob> old = new HashSet<BenchmarkJob>(jobs.getItems());
-				Map<BenchmarkJob, BenchmarkJob> actual;
 				try {
-					actual = manager.getJobs().stream().collect(Collectors.toMap(job -> job, job -> job));
-				} catch (IOException e) {
-					throw new RuntimeException(e);
-				}
-				for (BenchmarkJob job : old) {
-					if (!actual.containsKey(job)) {
-						jobs.getItems().remove(job);
-					} else {
-						job.update(actual.get(job));
+					Collection<BenchmarkJob> jobs = manager.getJobs();
+					Set<ObservableValue<BenchmarkJob>> actual = new HashSet<>(this.jobs.getItems());
+					for (BenchmarkJob bj : jobs) {
+						ObservableValue<BenchmarkJob> value = registry.addIfAbsent(bj);
+						if (!actual.contains(value)) {
+							this.jobs.getItems().add(value);
+						}
 					}
+				} catch (IOException e) {
+					log.error(e.getMessage(), e);
 				}
+
 				progress.done();
-				executorServiceFX.execute(() -> {
-					for (BenchmarkJob job : actual.keySet()) {
-						if (!old.contains(job)) {
-							jobs.getItems().add(job);
-						}
-					}
-				});
+
 			});
 		});
-
 	}
 
 	private void initTable() {
+		registry = new ObservableBenchmarkJobRegistry(bj -> jobs.getItems().remove(registry.get(bj)));
 		setCellValueFactory(0, j -> j.getId() + "");
 		setCellValueFactory(1, j -> j.getState().toString());
 		setCellValueFactory(2, j -> j.getCreationTime().toString());
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..93a0664514d743387e4a45486315ae69ed27221b
--- /dev/null
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableBenchmarkJobRegistry.java
@@ -0,0 +1,26 @@
+package cz.it4i.fiji.haas_spim_benchmark.ui;
+
+import java.nio.file.Files;
+import java.util.function.Consumer;
+
+import cz.it4i.fiji.haas.ui.ObservableValueRegistry;
+import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus;
+import cz.it4i.fiji.haas_java_client.JobState;
+import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob;
+
+public class ObservableBenchmarkJobRegistry extends ObservableValueRegistry<BenchmarkJob> {
+
+	public ObservableBenchmarkJobRegistry(Consumer<BenchmarkJob> removeConsumer) {
+		super(t -> update(t), removeConsumer);
+	}
+
+	private static UpdateStatus update(BenchmarkJob t) {
+		JobState oldState = t.getState();
+		t.update();
+		if (!Files.isDirectory(t.getDirectory())) {
+			return UpdateStatus.Deleted;
+		}
+		return oldState != t.getState() ? UpdateStatus.Updated : UpdateStatus.NotUpdated;
+	}
+
+}
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java
index 71876913b7daa56044916f17b844330e6f216967..595a057f5640d53d22c6d10745169da585a5e0ea 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/ObservableTaskRegistry.java
@@ -3,26 +3,26 @@ package cz.it4i.fiji.haas_spim_benchmark.ui;
 import java.util.function.Consumer;
 
 import cz.it4i.fiji.haas.ui.ObservableValueRegistry;
+import cz.it4i.fiji.haas.ui.UpdatableObservableValue.UpdateStatus;
 import cz.it4i.fiji.haas_java_client.JobState;
 import cz.it4i.fiji.haas_spim_benchmark.core.Task;
 import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation;
 
-public class ObservableTaskRegistry extends ObservableValueRegistry<Task>{
+public class ObservableTaskRegistry extends ObservableValueRegistry<Task> {
 
-	public ObservableTaskRegistry(
-			Consumer<Task> removeConsumer) {
-		super(x->true, t->update(t), removeConsumer);
+	public ObservableTaskRegistry(Consumer<Task> removeConsumer) {
+		super(t -> update(t), removeConsumer);
 	}
 
-	private static boolean update(Task t) {
-		boolean result = true;
+	private static UpdateStatus update(Task t) {
+		boolean updated = false;
 		t.update();
-		for(TaskComputation tc: t.getComputations()) {
+		for (TaskComputation tc : t.getComputations()) {
 			JobState oldState = tc.getState();
 			tc.update();
-			result &= oldState == tc.getState();
+			updated |= oldState != tc.getState();
 		}
-		return result;
+		return updated ? UpdateStatus.Updated : UpdateStatus.NotUpdated;
 	}
 
 	
diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java
index 90cb1147eb28b679ca5014d879bd64d0ab87155a..d71b0839026caea333c10a89a34d110837ac87fc 100644
--- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java
+++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java
@@ -43,7 +43,7 @@ public class SPIMPipelineProgressViewController implements FXFrame.Controller {
 
 	public void setBenchmarkJob(BenchmarkJob job) {
 		this.job = job;
-		registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.remove(task)));
+		registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.get(task)));
 		fillTable();
 	}