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 e5c81b4b9857a49e3d28f5dd605c565b7cde3ff5..193e41d607b6ecdec64cef0a1a091f3209ebdef3 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
@@ -3,7 +3,6 @@ package cz.it4i.fiji.haas;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.Calendar;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -12,6 +11,7 @@ import org.scijava.Context;
 
 import cz.it4i.fiji.haas_java_client.HaaSClient;
 import cz.it4i.fiji.haas_java_client.JobState;
+import javafx.beans.value.ObservableValueBase;
 
 public class JobManager {
 
@@ -74,7 +74,7 @@ public class JobManager {
 		return haasClient;
 	}
 
-	public static class JobInfo {
+	public static class JobInfo extends ObservableValueBase<JobInfo> {
 
 		private Job job;
 		
@@ -102,5 +102,10 @@ public class JobManager {
 		public String getEndTime() {
 			return job.getEndTime().getTime().toString();
 		}
+
+		@Override
+		public JobInfo getValue() {
+			return this;
+		}
 	}
 }
diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/CheckStatusOfHaaSController.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/CheckStatusOfHaaSController.java
index 48c4bdeac193741f37d96afce76cba2e09d62b9e..55b671abde85d5c424512a033eced0ce1ae3ee28 100644
--- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/CheckStatusOfHaaSController.java
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/CheckStatusOfHaaSController.java
@@ -2,12 +2,12 @@ package cz.it4i.fiji.haas.ui;
 
 
 
+import java.util.function.Function;
+
 import org.scijava.log.LogService;
 import org.scijava.plugin.Parameter;
 
 import cz.it4i.fiji.haas.JobManager.JobInfo;
-import javafx.beans.InvalidationListener;
-import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.event.EventHandler;
 import javafx.fxml.FXML;
@@ -16,9 +16,7 @@ import javafx.scene.control.MenuItem;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableColumn.CellDataFeatures;
 import javafx.scene.control.TableView;
-import javafx.scene.control.cell.PropertyValueFactory;
 import javafx.scene.input.ContextMenuEvent;
-import javafx.util.Callback;
 
 public class CheckStatusOfHaaSController {
 	
@@ -37,15 +35,14 @@ public class CheckStatusOfHaaSController {
 		jobs.getItems().add(job);
 	}
 	
-	@SuppressWarnings("unchecked")
 	public void init() {
 		ContextMenu cm = new ContextMenu();
 		MenuItem download = new MenuItem("Download");
 		cm.getItems().add(download);
-		((TableColumn<JobInfo, String>)jobs.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<JobInfo,String>("id"));
-		((TableColumn<JobInfo, String>)jobs.getColumns().get(1)).setCellValueFactory(new P_Factory());
-		((TableColumn<JobInfo, String>)jobs.getColumns().get(2)).setCellValueFactory(new PropertyValueFactory<JobInfo,String>("startTime"));
-		((TableColumn<JobInfo, String>)jobs.getColumns().get(3)).setCellValueFactory(new PropertyValueFactory<JobInfo,String>("endTime"));
+		setCellValueFactory(0,j->j.getId().toString());
+		setCellValueFactory(1,j->j.getState().toString() + (j.needsDownload()?" - needs download":""));
+		setCellValueFactory(2,j->j.getStartTime().toString());
+		setCellValueFactory(3,j->j.getEndTime().toString());
 		jobs.setContextMenu(cm);
 		jobs.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
 
@@ -68,45 +65,13 @@ public class CheckStatusOfHaaSController {
 		logService.info("init");
 	}
 	
-	
-	
-	private class P_Factory implements Callback<CellDataFeatures<JobInfo, String>, ObservableValue<String>> {
-
-		@Override
-		public ObservableValue<String> call(final CellDataFeatures<JobInfo, String> param) {
-			return new ObservableValue<String>() {
-
-				@Override
-				public void addListener(InvalidationListener listener) {
-					
-					
-				}
-
-				@Override
-				public void removeListener(InvalidationListener listener) {
-					
-					
-				}
-
-				@Override
-				public void addListener(ChangeListener<? super String> listener) {
-					
-					
-				}
-
-				@Override
-				public void removeListener(ChangeListener<? super String> listener) {
-					
-					
-				}
-
-				@Override
-				public String getValue() {
-					 JobInfo ji = param.getValue();
-					 return ji.getState().toString() + (ji.needsDownload()?" - needs download":"");
-				}
-			};
-		}
+	@SuppressWarnings("unchecked")
+	private void setCellValueFactory(int index, Function<JobInfo,String> mapper) {
+		((TableColumn<JobInfo, String>)jobs.getColumns().get(index)).setCellValueFactory(f->getObservableValue(f, mapper));
 		
 	}
+
+	private ObservableValue<String> getObservableValue(CellDataFeatures<JobInfo, String> feature, Function<JobInfo,String> mapper) {
+		return new ObservableValueAdapter<JobInfo,String>(feature.getValue(), mapper);
+	}
 }
diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueAdapter.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..116c0290b8d361942928c6d1298bcd01a386d3a8
--- /dev/null
+++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueAdapter.java
@@ -0,0 +1,62 @@
+package cz.it4i.fiji.haas.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+
+public class ObservableValueAdapter<S, T> implements ObservableValue<T> {
+
+	private ObservableValue<S> adapted;
+
+	private Function<S, T> transformation;
+
+	private Map<ChangeListener<? super T>, ChangeListener<? super S>> mapOfListeners = new HashMap<>();
+
+	public ObservableValueAdapter(ObservableValue<S> decorated, Function<S, T> map) {
+		super();
+		this.adapted = decorated;
+		this.transformation = map;
+	}
+
+	@Override
+	public void addListener(InvalidationListener listener) {
+		adapted.addListener(listener);
+
+	}
+
+	@Override
+	public void removeListener(InvalidationListener listener) {
+		adapted.removeListener(listener);
+
+	}
+
+	@Override
+	public void addListener(ChangeListener<? super T> listener) {
+		ChangeListener<S> wrapped = new ChangeListener<S>() {
+
+			@Override
+			public void changed(ObservableValue<? extends S> observable, S oldValue, S newValue) {
+				listener.changed(ObservableValueAdapter.this, transformation.apply(oldValue),
+						transformation.apply(newValue));
+			}
+		};
+		mapOfListeners.put(listener, wrapped);
+		adapted.addListener(wrapped);
+
+	}
+
+	@Override
+	public void removeListener(ChangeListener<? super T> listener) {
+		adapted.removeListener(mapOfListeners.get(listener));
+	}
+
+	@Override
+	public T getValue() {
+		return transformation.apply(adapted.getValue());
+	}
+
+}