diff --git a/README.md b/README.md
index 681cb5e5500e2760a48e5eae8a39f85624435bac..d73da6e6dc4ef6960743edae33cf05ba4231252c 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,3 @@ This will create the `build/docs/asciidoctor` directory which contains an index.
 To generate the technical documentation type `gradle javadoc`.
 This will create the `build/docs/javadoc` directory which contains an index.html file that can be viewed in your favorite web-browser.
 
-## Future work:
-1. Move geoserver configuration from xml-files in `etc/geoserver_config` to calls done using geoserver-shell.
-   By this it should be easily usable in the vagrant testbox.
diff --git a/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java b/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java
index 6f2fe4ac9d905a7bde6313ad1a960ff6639351e0..6a0b20b2dd2aa6c4dee6ed3e7e8449b0adb926d0 100644
--- a/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java
+++ b/src/main/java/it/unibz/inf/isochrone/config/ConfigDataset.java
@@ -71,84 +71,84 @@ public class ConfigDataset {
 	@TypeTransformers(PointTransformer.class)
 	private Point clientPoi;
 
-	@NotNull(message = "Please enter a value for the mandatory field dimLower1")
+	@NotNull
 	@PropertyValue("sql.spatial.dim1.lower")
 	private Double dimLower1;
 
-	@NotNull(message = "Please enter a value for the mandatory field dimLower2")
+	@NotNull
 	@PropertyValue("sql.spatial.dim2.lower")
 	private Double dimLower2;
 
-	@NotNull(message = "Please enter a value for the mandatory field dimUpper1")
+	@NotNull
 	@PropertyValue("sql.spatial.dim1.upper")
 	private Double dimUpper1;
 
-	@NotNull(message = "Please enter a value for the mandatory field dimUpper2")
+	@NotNull
 	@PropertyValue("sql.spatial.dim2.upper")
 	private Double dimUpper2;
 
-	@NotNull(message = "Please enter a value for the mandatory field serverSRID")
+	@NotNull
 	@PropertyValue("sql.spatial.srid")
 	private Integer serverSRID;
 
-	@NotNull(message = "Please enter a value for the mandatory field distanceTolerance")
+	@NotNull
 	@PropertyValue("par.distance_tolerance")
 	private Integer distanceTolerance;
 
-	@NotNull(message = "Please enter a value for the mandatory field indexAreaBuffer")
+	@NotNull
 	@PropertyValue("idx.isoAreaBuffer")
 	private String indexIsoAreaBuffer;
 
-	@NotNull(message = "Please enter a value for the mandatory field indexIsoLinks")
+	@NotNull
 	@PropertyValue("idx.isoLinks")
 	private String indexIsoLinks;
 
-	@NotNull(message = "Please enter a value for the mandatory field indexIsoNodes")
+	@NotNull
 	@PropertyValue("idx.isoNodes")
 	private String indexIsoNodes;
 
 	// TODO: This is not used (mail to t.gummerer and j.gamper)
-//	@NotNull(message = "Please enter a value for the mandatory field tableBuilding")
+//	@NotNull
 //	@PropertyValue("tbl.building")
 //	private String tableBuilding;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableDateCodes")
+	@NotNull
 	@PropertyValue("tbl.dateCodes")
 	private String tableDaymarker;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableLinks")
+	@NotNull
 	@PropertyValue("tbl.links")
 	private String tableEdges;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableIsoAreaBuffer")
+	@NotNull
 	@PropertyValue("tbl.isoAreaBuffer")
 	private String tableIsoAreaBuffer;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableIsoLinks")
+	@NotNull
 	@PropertyValue("tbl.isoLinks")
 	private String tableIsoLinks;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableIsoNodes")
+	@NotNull
 	@PropertyValue("tbl.isoNodes")
 	private String tableIsoNodes;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableIsoNodesAnotations")
+	@NotNull
 	@PropertyValue("tbl.isoNodesAnnotations")
 	private String tableIsoNodesAnnotations;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableRoutes")
+	@NotNull
 	@PropertyValue("tbl.routes")
 	private String tableRoutes;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableTimes")
+	@NotNull
 	@PropertyValue("tbl.times")
 	private String tableSchedules;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableNodes")
+	@NotNull
 	@PropertyValue("tbl.nodes")
 	private String tableVertex;
 
-	@NotNull(message = "Please enter a value for the mandatory field tableVertexDensity")
+	@NotNull
 	@PropertyValue("tbl.vertex.density")
 	private String tableVertexDensity;
 
diff --git a/src/main/java/it/unibz/inf/isoga/web/ConfigClient.java b/src/main/java/it/unibz/inf/isoga/config/ConfigClient.java
similarity index 99%
rename from src/main/java/it/unibz/inf/isoga/web/ConfigClient.java
rename to src/main/java/it/unibz/inf/isoga/config/ConfigClient.java
index 16fa1620fe30c4b59cb69f0a12b1a225c1185cfb..8a0ee0ef1e8c7a1b21e33250d49279c50559855d 100644
--- a/src/main/java/it/unibz/inf/isoga/web/ConfigClient.java
+++ b/src/main/java/it/unibz/inf/isoga/config/ConfigClient.java
@@ -1,4 +1,4 @@
-package it.unibz.inf.isoga.web;
+package it.unibz.inf.isoga.config;
 
 import it.unibz.inf.isochrone.config.ConfigDataset;
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
diff --git a/src/main/java/it/unibz/inf/isochrone/config/ConfigGeoserver.java b/src/main/java/it/unibz/inf/isoga/config/ConfigGeoserver.java
similarity index 98%
rename from src/main/java/it/unibz/inf/isochrone/config/ConfigGeoserver.java
rename to src/main/java/it/unibz/inf/isoga/config/ConfigGeoserver.java
index d98f02c9f76bb132a67ac5924cb62e1821510c4e..db0581f3be5d699f0ed4a4e7ae753a66c1cc5d2f 100644
--- a/src/main/java/it/unibz/inf/isochrone/config/ConfigGeoserver.java
+++ b/src/main/java/it/unibz/inf/isoga/config/ConfigGeoserver.java
@@ -1,4 +1,4 @@
-package it.unibz.inf.isochrone.config;
+package it.unibz.inf.isoga.config;
 
 import it.geosolutions.geoserver.rest.GeoServerRESTManager;
 import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
diff --git a/src/main/java/it/unibz/inf/isoga/coverage/CoverageBuilder.java b/src/main/java/it/unibz/inf/isoga/coverage/CoverageBuilder.java
index e6bb6dd5b9a6548f1ad7429f52f2f3938dfadcb8..c5a1bed4b5143ec690b8b00d4deaf787f7055f5a 100644
--- a/src/main/java/it/unibz/inf/isoga/coverage/CoverageBuilder.java
+++ b/src/main/java/it/unibz/inf/isoga/coverage/CoverageBuilder.java
@@ -1,9 +1,9 @@
 package it.unibz.inf.isoga.coverage;
 
 import it.unibz.inf.isochrone.util.EnumContainer.Mode;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.db.DatabaseWeb;
 import it.unibz.inf.isoga.util.MathHelper;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java b/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java
index 37d8867b3561855afb702d88593b4b0d45361b42..fdad36456b2526187df214cac5dee4b16fdf9532 100644
--- a/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java
+++ b/src/main/java/it/unibz/inf/isoga/db/DatabaseWeb.java
@@ -9,6 +9,7 @@ import it.unibz.inf.isochrone.network.Node;
 import it.unibz.inf.isochrone.util.EnumContainer.Direction;
 import it.unibz.inf.isochrone.util.EnumContainer.Mode;
 import it.unibz.inf.isochrone.util.Point;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.coverage.IsoEdge;
 import it.unibz.inf.isoga.geometry.AbstractLineString;
 import it.unibz.inf.isoga.geometry.PgLineString;
@@ -16,7 +17,6 @@ import it.unibz.inf.isoga.network.QueryNode;
 import it.unibz.inf.isoga.network.Schedule;
 import it.unibz.inf.isoga.util.PgHelper;
 import it.unibz.inf.isoga.util.QueryPointCache;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
diff --git a/src/main/java/it/unibz/inf/isoga/db/DbUtility.java b/src/main/java/it/unibz/inf/isoga/db/DbUtility.java
index c36dabcd86648bc1d2532c25652313bbb358285d..cc22fdc260f744693d4f144eba4735bce29f4a39 100644
--- a/src/main/java/it/unibz/inf/isoga/db/DbUtility.java
+++ b/src/main/java/it/unibz/inf/isoga/db/DbUtility.java
@@ -3,13 +3,13 @@ package it.unibz.inf.isoga.db;
 import it.unibz.inf.isochrone.config.ConfigDataset;
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
 import it.unibz.inf.isochrone.util.EnumContainer.QueryType;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.network.RouteEntity;
 import it.unibz.inf.isoga.service.dto.ResponsePoiFeature;
 import it.unibz.inf.isoga.service.dto.ResponsePoiFeature.PoiFeature;
 import it.unibz.inf.isoga.service.dto.ResponseWps;
 import it.unibz.inf.isoga.service.dto.WpsFeature;
 import it.unibz.inf.isoga.service.dto.WpsStatistic;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.CallableStatement;
 import java.sql.Connection;
diff --git a/src/main/java/it/unibz/inf/isoga/network/MemoryBBoxOutput.java b/src/main/java/it/unibz/inf/isoga/network/MemoryBBoxOutput.java
index eb76555155375b6148f6fb12c85770ba63f13da4..afbf79bce88d48882f012fc5a145faf157c415fb 100644
--- a/src/main/java/it/unibz/inf/isoga/network/MemoryBBoxOutput.java
+++ b/src/main/java/it/unibz/inf/isoga/network/MemoryBBoxOutput.java
@@ -4,9 +4,9 @@ import it.unibz.inf.isochrone.config.ConfigDataset;
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
 import it.unibz.inf.isochrone.network.MemoryOutput;
 import it.unibz.inf.isochrone.network.Node;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.db.DatabaseWeb;
 import it.unibz.inf.isoga.geometry.BBox;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
diff --git a/src/main/java/it/unibz/inf/isoga/service/AbstractService.java b/src/main/java/it/unibz/inf/isoga/service/AbstractService.java
index f28de62dabb6f2e63f5b99b279e241465619d979..a1604c9b72f8caa5d2fb81f0ac4eb5aa0de8eff8 100644
--- a/src/main/java/it/unibz/inf/isoga/service/AbstractService.java
+++ b/src/main/java/it/unibz/inf/isoga/service/AbstractService.java
@@ -3,13 +3,13 @@ package it.unibz.inf.isoga.service;
 import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
 import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder;
 import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder;
-import it.unibz.inf.isochrone.config.ConfigGeoserver;
+import it.unibz.inf.isoga.config.ConfigClient;
+import it.unibz.inf.isoga.config.ConfigGeoserver;
 import it.unibz.inf.isoga.db.DbUtility;
 import it.unibz.inf.isoga.db.TableEntry;
 import it.unibz.inf.isoga.geometry.BBox;
 import it.unibz.inf.isoga.service.dto.IRequest;
 import it.unibz.inf.isoga.service.dto.IResponse;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.Connection;
 
diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java b/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java
index eb161872837623378a5fe64f3fe15400666fe896..fdc7e8e6ca12b4728e7573790293a0fb6993ec54 100644
--- a/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java
+++ b/src/main/java/it/unibz/inf/isoga/service/ServiceConfiguration.java
@@ -4,9 +4,9 @@ package it.unibz.inf.isoga.service;
 import it.unibz.inf.isochrone.config.ConfigDataset;
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.service.dto.RequestConfiguration;
 import it.unibz.inf.isoga.service.dto.ResponseConfiguration;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.Connection;
 import java.util.ArrayList;
@@ -27,6 +27,10 @@ public class ServiceConfiguration extends AbstractService<RequestConfiguration,
 		super(RequestConfiguration.class, ResponseConfiguration.class);
 	}
 
+	public static String getActionName() {
+		return "getConfiguration";
+	}
+
 	// Public methods
 
 	@Override
diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java b/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java
index 9cd8ed124083d7a3327e250e0ea9812674a349be..c894d500b720e77dad09a06a3af3fe254672bf9c 100644
--- a/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java
+++ b/src/main/java/it/unibz/inf/isoga/service/ServiceFeatureInfo.java
@@ -2,12 +2,12 @@ package it.unibz.inf.isoga.service;
 
 
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.db.DbUtility;
 import it.unibz.inf.isoga.network.RouteEntity;
 import it.unibz.inf.isoga.service.dto.RequestFeatureInfo;
 import it.unibz.inf.isoga.service.dto.ResponseFeatureInfo;
 import it.unibz.inf.isoga.service.dto.ResponseFeatureInfo.Entry;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.util.Calendar;
 import java.util.SortedMap;
diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java b/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java
index 3aa22490ae1d62625bfa51ea86d384113228a20f..414425ab1e97519bafa1bf6f7cfa8be1a6c38e41 100644
--- a/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java
+++ b/src/main/java/it/unibz/inf/isoga/service/ServiceIsochrone.java
@@ -10,6 +10,7 @@ import it.unibz.inf.isochrone.config.ConfigIsochrone;
 import it.unibz.inf.isochrone.network.Location;
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
 import it.unibz.inf.isochrone.util.Query;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.coverage.CoverageBuilder;
 import it.unibz.inf.isoga.db.DatabaseWeb;
 import it.unibz.inf.isoga.db.DbUtility;
@@ -18,7 +19,6 @@ import it.unibz.inf.isoga.network.QueryNode;
 import it.unibz.inf.isoga.service.dto.RequestIsochrone;
 import it.unibz.inf.isoga.service.dto.ResponseIsochrone;
 import it.unibz.inf.isoga.service.dto.ResponseIsochrone.TimingLog;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import java.sql.Connection;
 import java.util.Collection;
diff --git a/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java b/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java
index f82c4cb707be61024716310356a3a273425b039e..82470c9330ebe5e1db23961bb32a747c747b71ea 100644
--- a/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java
+++ b/src/main/java/it/unibz/inf/isoga/service/ServicePoiFeature.java
@@ -3,10 +3,10 @@ package it.unibz.inf.isoga.service;
 
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.db.DbUtility;
 import it.unibz.inf.isoga.service.dto.RequestPoiFeature;
 import it.unibz.inf.isoga.service.dto.ResponsePoiFeature;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import javax.websocket.Session;
 
diff --git a/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java b/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java
index 94fe24199ce09b68c899e451887a1acce3071787..d9f55f8738be506e2fe2083a642f69335571ada5 100644
--- a/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java
+++ b/src/main/java/it/unibz/inf/isoga/service/ServiceWps.java
@@ -3,11 +3,11 @@ package it.unibz.inf.isoga.service;
 
 import it.unibz.inf.isochrone.util.EnumContainer.Dataset;
 import it.unibz.inf.isochrone.util.EnumContainer.QueryType;
+import it.unibz.inf.isoga.config.ConfigClient;
 import it.unibz.inf.isoga.db.DbUtility;
 import it.unibz.inf.isoga.db.SqlQuery;
 import it.unibz.inf.isoga.service.dto.RequestWps;
 import it.unibz.inf.isoga.service.dto.ResponseWps;
-import it.unibz.inf.isoga.web.ConfigClient;
 
 import javax.websocket.Session;
 
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/IRequest.java b/src/main/java/it/unibz/inf/isoga/service/dto/IRequest.java
index 5e9b14bb41c607ffda22b270f072974d9c39b18a..de37bcc48d132d27e6dce29fe305ab02b3bf449b 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/IRequest.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/IRequest.java
@@ -1,6 +1,5 @@
 package it.unibz.inf.isoga.service.dto;
 
-
 public interface IRequest {
 	void setAction(final String action);
 }
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/IResponse.java b/src/main/java/it/unibz/inf/isoga/service/dto/IResponse.java
index 067d9362e47699dad14b4b69a1815e1257ad0ae3..6f5e546642c5fe868a619ff830a7410caad6f2f9 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/IResponse.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/IResponse.java
@@ -2,4 +2,5 @@ package it.unibz.inf.isoga.service.dto;
 
 public interface IResponse {
 	String getAction();
+	int getHttpState();
 }
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/RequestConfiguration.java b/src/main/java/it/unibz/inf/isoga/service/dto/RequestConfiguration.java
index f7476fe035569c4d4306484ac3576e49e142dc38..079fedd70bb278fe35a715ce302a61e929baa3d9 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/RequestConfiguration.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/RequestConfiguration.java
@@ -6,8 +6,8 @@ public class RequestConfiguration implements IRequest {
 
 	public RequestConfiguration() { }
 
+	@JsonProperty
 	@Override
-	@JsonProperty(required = true)
 	public void setAction(final String action) {
 		if (action == null || !action.trim().equals("getConfiguration")) {
 			throw new IllegalStateException("Invalid request action");
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/RequestFeatureInfo.java b/src/main/java/it/unibz/inf/isoga/service/dto/RequestFeatureInfo.java
index 5fc4b0054e8390c23c0935f4a9e8db68650a2cd3..49c5978edc645467e73c4171371638c0024381a2 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/RequestFeatureInfo.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/RequestFeatureInfo.java
@@ -1,18 +1,27 @@
 package it.unibz.inf.isoga.service.dto;
 
+import javax.validation.constraints.NotNull;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class RequestFeatureInfo implements IRequest {
 	private int stopId;
 
+	// Constructors
+
 	public RequestFeatureInfo() { }
 
+	// Getter
+
+	@NotNull
 	public int getStopId() {
 		return stopId;
 	}
 
+	// Setter
+
+	@JsonProperty
 	@Override
-	@JsonProperty(required = true)
 	public void setAction(final String action) {
 		if (action == null || !action.trim().equals("getFeatureInfo")) {
 			throw new IllegalStateException("Invalid request action");
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/RequestIsochrone.java b/src/main/java/it/unibz/inf/isoga/service/dto/RequestIsochrone.java
index 5e8503e089068566aa273b249158337eed3e38a8..c6f1e0b96ad81e7e184f13815ac30b7e762cf5f9 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/RequestIsochrone.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/RequestIsochrone.java
@@ -11,6 +11,8 @@ import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Collection;
 
+import javax.validation.constraints.NotNull;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class RequestIsochrone implements IRequest {
@@ -34,6 +36,7 @@ public class RequestIsochrone implements IRequest {
 
 	// Getter
 
+	@NotNull
 	public String getAlgorithm() {
 		return algorithm;
 	}
@@ -42,11 +45,21 @@ public class RequestIsochrone implements IRequest {
 		return coverageMode;
 	}
 
+	@NotNull
 	public Dataset getDataset() {
+		if (datasetString == null) {
+			return null;
+		}
+
 		return Dataset.valueOf(datasetString.toUpperCase());
 	}
 
+	@NotNull
 	public Calendar getDate() {
+		if (dateString == null || timeString == null) {
+			return null;
+		}
+
 		final Calendar date = Calendar.getInstance();
 		final Calendar time = Calendar.getInstance();
 		try {
@@ -64,11 +77,17 @@ public class RequestIsochrone implements IRequest {
 		return date;
 	}
 
+	@NotNull
 	public Direction getDirection() {
+		if (directionString == null) {
+			return null;
+		}
+
 		return Direction.valueOf(directionString.toUpperCase());
 	}
 
-	public boolean isExpiringMode() {
+	@NotNull
+	public Boolean isExpiringMode() {
 		if (expirationMode == null) {
 			return false;
 		}
@@ -76,6 +95,7 @@ public class RequestIsochrone implements IRequest {
 		return expirationMode;
 	}
 
+	@NotNull
 	public long getDmax() {
 		if (dmax == null) {
 			return 0L;
@@ -83,35 +103,29 @@ public class RequestIsochrone implements IRequest {
 		return dmax;
 	}
 
+	@NotNull
 	public Mode getMode() {
+		if (modeString == null) {
+			return null;
+		}
+
 		return Mode.valueOf(modeString.toUpperCase());
 	}
 
+	@NotNull
 	public Collection<QueryNode> getQueryPoints() {
 		return queryPoints;
 	}
 
-	public Calendar getTime() {
-		Calendar time = Calendar.getInstance();
-		try {
-			final DateFormat timeFormatter = new SimpleDateFormat(FORMAT_CLIENT_TIME);
-			time.setTimeInMillis(timeFormatter.parse(timeString).getTime());
-		} catch (final ParseException e) {
-			e.printStackTrace();
-			time = null;
-		}
-
-		return time;
-	}
-
-	public double getSpeed() {
+	@NotNull
+	public Double getSpeed() {
 		return speed;
 	}
 
 	// Setter
 
+	@JsonProperty
 	@Override
-	@JsonProperty(required = true)
 	public void setAction(final String action) {
 		if (action == null || !action.trim().equals("getIsochrone")) {
 			throw new IllegalStateException("Invalid request action");
@@ -148,12 +162,12 @@ public class RequestIsochrone implements IRequest {
 		this.dmax = dmax;
 	}
 
-	@JsonProperty(required = true)
+	@JsonProperty
 	public void setExpirationMode(final Boolean expirationMode) {
 		this.expirationMode = expirationMode;
 	}
 
-	@JsonProperty(required = true, value = "mode")
+	@JsonProperty(value = "mode")
 	public void setModeString(final String modeString) {
 		this.modeString = modeString;
 	}
@@ -163,7 +177,7 @@ public class RequestIsochrone implements IRequest {
 		this.queryPoints = queryPoints;
 	}
 
-	@JsonProperty(required = true)
+	@JsonProperty
 	public void setSpeed(final Double speed) {
 		this.speed = speed;
 	}
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/RequestPoiFeature.java b/src/main/java/it/unibz/inf/isoga/service/dto/RequestPoiFeature.java
index 900d586a2322e1c1d059f0cb2bf09cf595097361..c2b47eafa0323c6f80cc76b937ead0ff4bbff0d7 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/RequestPoiFeature.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/RequestPoiFeature.java
@@ -6,14 +6,20 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class RequestPoiFeature implements IRequest {
 	private String query;
 
+	// Constructors
+
 	public RequestPoiFeature() { }
 
+	// Getter
+
 	public String getQuery() {
 		return query.trim();
 	}
 
+	// Setter
+
+	@JsonProperty
 	@Override
-	@JsonProperty(required = true)
 	public void setAction(final String action) {
 		if (action == null || !action.trim().equals("getPOIFeatures")) {
 			throw new IllegalStateException("Invalid request action");
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/RequestWps.java b/src/main/java/it/unibz/inf/isoga/service/dto/RequestWps.java
index 364bfaf88243a92ccaf8b41b9423582946e48f64..f703ffe744ae5db7aaf4161504881f5950ed2b5e 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/RequestWps.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/RequestWps.java
@@ -7,8 +7,12 @@ public class RequestWps implements IRequest {
 	private String spatialPredicate;
 	private String sqlQuery;
 
+	// Constructors
+
 	public RequestWps() { }
 
+	// Getter
+
 	public String getCoverageTable() {
 		return coverageTable.trim();
 	}
@@ -21,8 +25,10 @@ public class RequestWps implements IRequest {
 		return sqlQuery.trim();
 	}
 
+	// Setter
+
+	@JsonProperty
 	@Override
-	@JsonProperty(required = true)
 	public void setAction(final String action) {
 		if (action == null || !action.trim().equals("getIsochroneWPS")) {
 			throw new IllegalStateException("Invalid request action");
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseConfiguration.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseConfiguration.java
index 8b19891d2ba2932ec95a7230c58a17fe46bbb7a4..8808249b5858658d89a3f09320a4c8a1f20de00e 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseConfiguration.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseConfiguration.java
@@ -1,35 +1,50 @@
 package it.unibz.inf.isoga.service.dto;
 
 import it.unibz.inf.isochrone.config.ConfigDataset;
-import it.unibz.inf.isochrone.config.ConfigGeoserver;
+import it.unibz.inf.isoga.config.ConfigGeoserver;
+import it.unibz.inf.isoga.service.ServiceConfiguration;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ResponseConfiguration implements IResponse {
 	private final String mapserverUrl;
 	private final Collection<ConfigDataset> defaultDatasets;
 
+	// Consturctors
+
 	public ResponseConfiguration() {
 		defaultDatasets = new ArrayList<ConfigDataset>();
 		mapserverUrl = ConfigGeoserver.getInstance().getRenderServerURL();
 	}
 
+	// Public methods
+
 	public void addDSetConfig(final ConfigDataset dsetConfig) {
 		defaultDatasets.add(dsetConfig);
 	}
 
+	// Getter
+
 	@Override
 	@JsonProperty
 	public String getAction() {
-		return "getConfiguration";
+		return ServiceConfiguration.getActionName();
 	}
 
 	@JsonProperty
-	public String getMessageType() {
-		return "configuration";
+	public Collection<ConfigDataset> getDefaultDatasets() {
+		return defaultDatasets;
+	}
+
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		return HttpStatus.SC_OK;
 	}
 
 	@JsonProperty
@@ -38,7 +53,7 @@ public class ResponseConfiguration implements IResponse {
 	}
 
 	@JsonProperty
-	public Collection<ConfigDataset> getDefaultDatasets() {
-		return defaultDatasets;
+	public String getMessageType() {
+		return "configuration";
 	}
 }
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseError.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseError.java
new file mode 100644
index 0000000000000000000000000000000000000000..10d0633f79ebd18c5ecd2b902818fa33fce94e77
--- /dev/null
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseError.java
@@ -0,0 +1,58 @@
+package it.unibz.inf.isoga.service.dto;
+
+import it.unibz.inf.isoga.web.IllegalRequestException;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.commons.httpclient.HttpStatus;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ResponseError implements IResponse {
+	private final String action;
+	private final Throwable t;
+
+	// Constructors
+
+	public ResponseError(final Throwable t) {
+		this(t, "UNKNOWN_ACTION");
+	}
+
+	public ResponseError(final Throwable t, final String action) {
+		this.action = action;
+		this.t = t;
+	}
+
+	// Getter
+
+	@JsonProperty
+	@Override
+	public String getAction() {
+		return action;
+	}
+
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		if (t instanceof IllegalRequestException) {
+			return HttpStatus.SC_BAD_REQUEST;
+		}
+
+		return HttpStatus.SC_INTERNAL_SERVER_ERROR;
+	}
+
+	@JsonProperty
+	public String getMessage() {
+		return t.getMessage();
+	}
+
+	@JsonProperty
+	public Collection<String> getDetails() {
+		if (t instanceof IllegalRequestException) {
+			return ((IllegalRequestException) t).getDetails();
+		}
+
+		return Collections.emptyList();
+	}
+}
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseFeatureInfo.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseFeatureInfo.java
index 898820f62a1a6629f8c1dbf79eef10925438343c..285b2e0c8e36cc7f6baa802f398a3eaa00206554 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseFeatureInfo.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseFeatureInfo.java
@@ -5,6 +5,8 @@ import it.unibz.inf.isoga.network.RouteEntity;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ResponseFeatureInfo implements IResponse {
@@ -34,23 +36,35 @@ public class ResponseFeatureInfo implements IResponse {
 		}
 	}
 
+	// Constructors
+
 	public ResponseFeatureInfo() {
 		vertexAnnotationList = new ArrayList<Entry>();
 	}
 
+	// Public methods
+
 	public void addEntry(final Entry entry) {
 		vertexAnnotationList.add(entry);
 	}
 
-	@JsonProperty(value = "vertexAnnotation")
-	public Collection<Entry> getVertexAnnotations() {
-		return vertexAnnotationList;
-	}
+	// Getter
 
-	@Override
 	@JsonProperty
+	@Override
 	public String getAction() {
 		return "getFeatureInfo";
 	}
 
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		return HttpStatus.SC_OK;
+	}
+
+	@JsonProperty(value = "vertexAnnotation")
+	public Collection<Entry> getVertexAnnotations() {
+		return vertexAnnotationList;
+	}
+
 }
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseIsochrone.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseIsochrone.java
index 642fd01b7d82eb460fa11060cea7788b2eb07fa6..f9d3a8bf0482266b4d07951b390b86011da67db4 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseIsochrone.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseIsochrone.java
@@ -2,6 +2,8 @@ package it.unibz.inf.isoga.service.dto;
 
 import it.unibz.inf.isoga.geometry.BBox;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ResponseIsochrone implements IResponse {
@@ -35,15 +37,11 @@ public class ResponseIsochrone implements IResponse {
 		}
 	}
 
+	// Constructors
+
 	public ResponseIsochrone() { }
 
-	public void setBoundingBox(final BBox boundingBox) {
-		this.boundingBox = boundingBox;
-	}
-
-	public void setLog(final TimingLog log) {
-		this.log = log;
-	}
+	// Getter
 
 	@Override
 	@JsonProperty
@@ -56,9 +54,25 @@ public class ResponseIsochrone implements IResponse {
 		return boundingBox;
 	}
 
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		return HttpStatus.SC_OK;
+	}
+
 	@JsonProperty(value = "logging")
 	public TimingLog getLog() {
 		return log;
 	}
 
+	// Setter
+
+	public void setBoundingBox(final BBox boundingBox) {
+		this.boundingBox = boundingBox;
+	}
+
+	public void setLog(final TimingLog log) {
+		this.log = log;
+	}
+
 }
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponsePoiFeature.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponsePoiFeature.java
index acc98533a9102a7cdb493dd8353e17b218f052d8..2c06306f93228b0f3cf2eeb7569d857a71e2647f 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/ResponsePoiFeature.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponsePoiFeature.java
@@ -3,6 +3,8 @@ package it.unibz.inf.isoga.service.dto;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ResponsePoiFeature implements IResponse {
@@ -29,14 +31,20 @@ public class ResponsePoiFeature implements IResponse {
 		}
 	}
 
+	// Constructor
+
 	public ResponsePoiFeature() {
 		featureCollection = new ArrayList<PoiFeature>();
 	}
 
+	// Public methods
+
 	public void addFeature(final PoiFeature f) {
 		featureCollection.add(f);
 	}
 
+	// Getter
+
 	@Override
 	@JsonProperty
 	public String getAction() {
@@ -53,11 +61,19 @@ public class ResponsePoiFeature implements IResponse {
 		return featureCollection.size();
 	}
 
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		return HttpStatus.SC_OK;
+	}
+
 	@JsonProperty
 	public String getType() {
 		return type;
 	}
 
+	// Setter
+
 	public void setType(final String type) {
 		this.type = type;
 	}
diff --git a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseWps.java b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseWps.java
index f558c0de0a1d4cd73e662ed5021e44f1cbcc934f..277532ed0fbc806f4e723fb9e4bca2ca689d0326 100644
--- a/src/main/java/it/unibz/inf/isoga/service/dto/ResponseWps.java
+++ b/src/main/java/it/unibz/inf/isoga/service/dto/ResponseWps.java
@@ -3,6 +3,8 @@ package it.unibz.inf.isoga.service.dto;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class ResponseWps implements IResponse {
@@ -13,6 +15,8 @@ public class ResponseWps implements IResponse {
 	private double sum = 0.0d;
 	private final Collection<WpsFeature> featureCollection;
 
+	// Constructor
+
 	public ResponseWps(final String queryType) {
 		this.queryType = queryType;
 		this.columnLabels = new ArrayList<WpsColumnLabel>();
@@ -22,10 +26,15 @@ public class ResponseWps implements IResponse {
 	public void addColumnLabel(final String columnLabel, final String columnType) {
 		this.columnLabels.add(new WpsColumnLabel(columnLabel, columnType));
 	}
+
+	// Public methods
+
 	public void addFeature(final WpsFeature f) {
 		featureCollection.add(f);
 	}
 
+	// Getter
+
 	@Override
 	@JsonProperty
 	public String getAction() {
@@ -42,6 +51,17 @@ public class ResponseWps implements IResponse {
 		return featureCollection;
 	}
 
+	@JsonProperty
+	@Override
+	public int getHttpState() {
+		return HttpStatus.SC_OK;
+	}
+
+	@JsonProperty
+	public int getJoinedCount() {
+		return featureCollection.size();
+	}
+
 	@JsonProperty
 	public String getQueryType() {
 		return queryType;
@@ -52,20 +72,17 @@ public class ResponseWps implements IResponse {
 		return statistic;
 	}
 
-	@JsonProperty
-	public String getType() {
-		return type;
+	@JsonProperty(value = "joinedSum")
+	public double getSum() {
+		return sum;
 	}
 
 	@JsonProperty
-	public int getJoinedCount() {
-		return featureCollection.size();
+	public String getType() {
+		return type;
 	}
 
-	@JsonProperty(value = "joinedSum")
-	public double getSum() {
-		return sum;
-	}
+	// Setter
 
 	public void setStatistic(final WpsStatistic statistic) {
 		this.statistic = statistic;
diff --git a/src/main/java/it/unibz/inf/isoga/web/GeoserverHelper.java b/src/main/java/it/unibz/inf/isoga/web/GeoserverHelper.java
index b4ec85089c5daad88d12d4a32bbe2b85b54e03b1..379536f505646a9957ecfed36c00080cb4fbb4c7 100644
--- a/src/main/java/it/unibz/inf/isoga/web/GeoserverHelper.java
+++ b/src/main/java/it/unibz/inf/isoga/web/GeoserverHelper.java
@@ -8,7 +8,7 @@ import it.geosolutions.geoserver.rest.decoder.RESTLayerList;
 import it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder;
 import it.geosolutions.geoserver.rest.manager.GeoServerRESTStoreManager;
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
-import it.unibz.inf.isochrone.config.ConfigGeoserver;
+import it.unibz.inf.isoga.config.ConfigGeoserver;
 import it.unibz.inf.isoga.db.DbUtility;
 
 import java.sql.Connection;
diff --git a/src/main/java/it/unibz/inf/isoga/web/IllegalRequestException.java b/src/main/java/it/unibz/inf/isoga/web/IllegalRequestException.java
new file mode 100644
index 0000000000000000000000000000000000000000..00daad79714faf97341ec752f08df9103ee70bbe
--- /dev/null
+++ b/src/main/java/it/unibz/inf/isoga/web/IllegalRequestException.java
@@ -0,0 +1,33 @@
+package it.unibz.inf.isoga.web;
+
+import it.unibz.inf.isoga.service.dto.IRequest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+
+public class IllegalRequestException extends Exception {
+	private static final long serialVersionUID = -777987841949391195L;
+	private Collection<String> details;
+
+	// constructor
+
+	public IllegalRequestException(final String message) {
+		super(message);
+	}
+
+	public <T extends IRequest> IllegalRequestException(final String string, final Set<ConstraintViolation<T>> validationErrors) {
+		details = new ArrayList<String>(validationErrors.size());
+		for (ConstraintViolation<? extends IRequest> constraintViolation : validationErrors) {
+			details.add(constraintViolation.getPropertyPath() + " " + constraintViolation.getMessage());
+		}
+	}
+
+	// Getter
+
+	public Collection<String> getDetails() {
+		return details;
+	}
+}
diff --git a/src/main/java/it/unibz/inf/isoga/web/InternalSocketException.java b/src/main/java/it/unibz/inf/isoga/web/InternalSocketException.java
new file mode 100644
index 0000000000000000000000000000000000000000..0caafa9cd5780b217c882c3c75b3e1e139d451ec
--- /dev/null
+++ b/src/main/java/it/unibz/inf/isoga/web/InternalSocketException.java
@@ -0,0 +1,9 @@
+package it.unibz.inf.isoga.web;
+
+public class InternalSocketException extends Exception {
+	private static final long serialVersionUID = -777987841949391195L;
+
+	public InternalSocketException(final String message) {
+		super(message);
+	}
+}
diff --git a/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java b/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java
index ddb8eaca908581f359889be823a107d906ebc7fd..b8f38432bbdbd2cb4204d3f28824cbcf78e6563a 100644
--- a/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java
+++ b/src/main/java/it/unibz/inf/isoga/web/JsonWebsocket.java
@@ -1,8 +1,9 @@
 package it.unibz.inf.isoga.web;
 
 import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
-import it.unibz.inf.isochrone.config.ConfigGeoserver;
 import it.unibz.inf.isochrone.config.ConfigIsochrone;
+import it.unibz.inf.isoga.config.ConfigClient;
+import it.unibz.inf.isoga.config.ConfigGeoserver;
 import it.unibz.inf.isoga.db.DbUtility;
 import it.unibz.inf.isoga.db.TableEntry;
 import it.unibz.inf.isoga.service.IService;
@@ -13,6 +14,7 @@ import it.unibz.inf.isoga.service.ServicePoiFeature;
 import it.unibz.inf.isoga.service.ServiceWps;
 import it.unibz.inf.isoga.service.dto.IRequest;
 import it.unibz.inf.isoga.service.dto.IResponse;
+import it.unibz.inf.isoga.service.dto.ResponseError;
 
 import java.io.IOException;
 import java.nio.charset.Charset;
@@ -20,9 +22,15 @@ import java.sql.Connection;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
 import javax.websocket.CloseReason;
 import javax.websocket.OnClose;
+import javax.websocket.OnError;
 import javax.websocket.OnMessage;
 import javax.websocket.OnOpen;
 import javax.websocket.Session;
@@ -52,62 +60,6 @@ public class JsonWebsocket {
 
 	// Websocket methods
 
-	@OnOpen
-	public void onOpen(final Session session) {
-		final String clientId = session.getId();
-		LOGGER.debug("Websocket: Session \"" + clientId + "\" opened");
-	}
-
-	@OnMessage
-	public <S extends IService<T, U>, T extends IRequest, U extends IResponse> String onMessage(final Session session, final String message) {
-		final String clientId = session.getId();
-		LOGGER.debug("Websocket: Message from client \"" + clientId + "\": " + message);
-
-		final boolean emptyRequest = (message == null || message.trim().length() <= 0);
-		if (emptyRequest) {
-			throw new IllegalArgumentException("Invalid request given... empty object");
-		}
-
-		final ObjectMapper mapper = new ObjectMapper();
-		mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
-
-		JsonNode requestJsonNode = null;
-		try {
-			requestJsonNode = mapper.readValue(message.getBytes(REQUEST_CONTENT_CHARSET), JsonNode.class);
-		} catch (final IOException e) {
-			throw new IllegalArgumentException("Invalid request given... can not be parsed to json object");
-		}
-
-		final Class<S> aService = this.<S, T, U>getService(requestJsonNode);
-		if (aService == null) {
-			throw new IllegalArgumentException("Invalid request message given... referenced service could not be found");
-		}
-
-		S service = null;
-		try {
-			service = aService.newInstance();
-		} catch (InstantiationException | IllegalAccessException e) {
-			e.printStackTrace();
-		}
-		if (service == null) {
-			throw new IllegalStateException("Referenced service \"" + aService.getClass().getSimpleName() + "\" could not be created!");
-		}
-
-		T request = null;
-		try {
-			request = mapper.readValue(message, service.getRequestClass());
-		} catch (IOException e) {
-			throw new IllegalStateException("Invalid request object... can not generate request object from json data");
-		}
-
-		try {
-			return mapper.writeValueAsString(service.onJsonMessage(session, request));
-		} catch (JsonProcessingException e) {
-			LOGGER.warn(e.getLocalizedMessage());
-			throw new IllegalStateException("Invalid JSON... can not generate response");
-		}
-	}
-
 	@OnClose
 	public void onClose(final Session session, final CloseReason closeReason) {
 		final Connection connection = ConfigIsochrone.getInstance().getConnection();
@@ -137,21 +89,102 @@ public class JsonWebsocket {
 		LOGGER.debug("Websocket: Session \"" + clientId + "\" closed: " + closeReason);
 	}
 
-	// Private methods
+	@OnError
+    public void onError(final Session session, final Throwable throwable) {
+    	LOGGER.warn("Error for client \"" + session.getId() + "\"");
+    	throwable.printStackTrace();
+    }
+
+	@OnMessage
+	public <S extends IService<T, U>, T extends IRequest, U extends IResponse> String onMessage(final Session session, final String message) {
+		final String clientId = session.getId();
+		LOGGER.debug("Websocket: Message from client \"" + clientId + "\": " + message);
+
+		final ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
+
+		S service = null;
+		try {
+			service = createService(mapper, message);
+			final T request = createRequest(mapper, message, service);
+			final U response = service.onJsonMessage(session, request);
+			return writeResponse(mapper, response);
+		} catch (Exception e) {
+			return writeResponseError(mapper, service, e);
+		}
+	}
+
+	@OnOpen
+	public void onOpen(final Session session) {
+		final String clientId = session.getId();
+		LOGGER.debug("Websocket: Session \"" + clientId + "\" opened");
+	}
+
+	// Private static methods
+
+	private static <S extends IService<T, U>, T extends IRequest, U extends IResponse> T createRequest(final ObjectMapper mapper, final String msg, final S service) throws IllegalRequestException {
+		T request = null;
+		try {
+			request = mapper.readValue(msg, service.getRequestClass());
+		} catch (IOException e) {
+			throw new IllegalRequestException("Invalid request object... can not generate request object from json data");
+		}
+
+		final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+		final Set<ConstraintViolation<T>> validationErrors = validator.validate(request);
+		if (!validationErrors.isEmpty()) {
+			throw new IllegalRequestException("Invalid request object... client json data invalid", validationErrors);
+		}
+
+		return request;
+	}
+
+    private static <S extends IService<T, U>, T extends IRequest, U extends IResponse> S createService(final ObjectMapper mapper, final String msg)
+			throws IllegalRequestException, InternalSocketException {
+		final boolean emptyRequest = (msg == null || msg.trim().length() <= 0);
+		if (emptyRequest) {
+			throw new IllegalRequestException("Invalid request given... empty object");
+		}
+
+		JsonNode requestJsonNode = null;
+		try {
+			requestJsonNode = mapper.readValue(msg.getBytes(REQUEST_CONTENT_CHARSET), JsonNode.class);
+		} catch (final IOException e) {
+			throw new IllegalRequestException("Invalid request given... can not be parsed to json object");
+		}
+
+		final Class<S> aService = JsonWebsocket.<S, T, U>getService(requestJsonNode);
+		if (aService == null) {
+			throw new IllegalRequestException("Invalid request message given... referenced service could not be found");
+		}
+
+		S service = null;
+		try {
+			service = aService.newInstance();
+		} catch (InstantiationException | IllegalAccessException e) {
+			e.printStackTrace();
+		}
+
+		if (service == null) {
+			throw new InternalSocketException("Referenced service \"" + aService.getClass().getSimpleName() + "\" could not be created!");
+		}
+
+		return service;
+	}
 
-	private <S extends IService<T, U>, T extends IRequest, U extends IResponse> Class<S> getService(final JsonNode jsonNode) {
+	private static <S extends IService<T, U>, T extends IRequest, U extends IResponse> Class<S> getService(final JsonNode jsonNode) throws IllegalRequestException {
 		if (!jsonNode.has("action")) {
-			return null;
+			throw new IllegalRequestException("Invalid request message given... no service action defined");
 		}
 
 		final JsonNode actionNode = jsonNode.get("action");
 		if (!actionNode.isTextual()) {
-			return null;
+			throw new IllegalRequestException("Invalid request message given... referenced service is of invalid type");
 		}
 
 		final String action = actionNode.asText();
 		if (action == null || action.trim().length() <=  0) {
-			return null;
+			throw new IllegalRequestException("Invalid request message given... referenced service is empty");
 		}
 
 		// TODO: Can this be done without suppressing warnings belonging to raw type?
@@ -160,4 +193,41 @@ public class JsonWebsocket {
 		return returnClass;
 	}
 
+	private static <U extends IResponse> String writeResponse(final ObjectMapper mapper, final U response) throws InternalSocketException {
+		final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+		final Set<ConstraintViolation<U>> validationErrors = validator.validate(response);
+		if (!validationErrors.isEmpty()) {
+			throw new InternalSocketException("Invalid response object... can not generate response");
+		}
+
+		try {
+			return mapper.writeValueAsString(response);
+		} catch (JsonProcessingException e) {
+			LOGGER.warn(e.getLocalizedMessage());
+			throw new InternalSocketException("Can not write response");
+		}
+	}
+
+	private static <S extends IService<T, U>, T extends IRequest, U extends IResponse> String writeResponseError(final ObjectMapper mapper, final S service, final Exception e) {
+		ResponseError response = null;
+		if (service != null) {
+			Set<Entry<String, Class<? extends IService<? extends IRequest, ? extends IResponse>>>> entrySet = AVAILABLE_SERVICES.entrySet();
+			for (Entry<String, Class<? extends IService<? extends IRequest, ? extends IResponse>>> entry : entrySet) {
+				if (entry.getValue() == service.getClass()) {
+					response = new ResponseError(e, entry.getKey());
+				}
+			}
+		}
+
+		if (response == null) {
+			response = new ResponseError(e);
+		}
+
+		try {
+			return writeResponse(mapper, response);
+		} catch (InternalSocketException e1) {
+			LOGGER.error("Could not write valid error json to client");
+			return "{\"action\": \"UNKNOWN_ACTION\", \"httpState\": 400}";
+		}
+	}
 }
diff --git a/src/main/webapp/js/isochrone/initHelper.js b/src/main/webapp/js/isochrone/initHelper.js
index ef6a171af2a5a4135c7b9b3f1149a63b52a60018..6353b05b0e0da62b18352df3c093d6111fb86417 100644
--- a/src/main/webapp/js/isochrone/initHelper.js
+++ b/src/main/webapp/js/isochrone/initHelper.js
@@ -1,6 +1,7 @@
-define(['jQuery', 'console', 'map/isoMap', 'service/websocket', 'service/serviceConfiguration', 'isochrone/searchExtender', 'jQueryUI', 'jQueryUI-timepicker'], function($, logger, IsoMap, Websocket, ServiceConfiguration, SearchExtender) {
+define(['jQuery', 'console', 'map/isoMap', 'service/websocket', 'service/serviceIsochrone', 'service/serviceConfiguration', 'isochrone/searchExtender', 'jQueryUI', 'jQueryUI-timepicker'], function($, logger, IsoMap, Websocket, ServiceIsochrone, ServiceConfiguration, SearchExtender) {
 	function InitHelper() {
-		var config = null;
+		var serviceConfig = null;
+		var serviceIsochrone = null;
 		var isoMap = null;
 		var ws = null;
 
@@ -13,8 +14,9 @@ define(['jQuery', 'console', 'map/isoMap', 'service/websocket', 'service/service
 			isoMap.locateAndDraw();
 
 			ws = new Websocket();
-			config = new ServiceConfiguration(ws);
-			config.getFromServer();
+			serviceConfig = new ServiceConfiguration(ws);
+			serviceConfig.initFromServer(); // prepares ConfigurationInstance
+			serviceIsochrone = new ServiceIsochrone(ws);
 
 			$(document).on('isomap_draw', extendSearch.bind(this));
 		};
@@ -49,11 +51,11 @@ define(['jQuery', 'console', 'map/isoMap', 'service/websocket', 'service/service
 		// Private methods
 
 		function extendSearch() {
-			var mapElem = isoMap.getMap(),
-				searchExtender;
+			var searchExtender = new SearchExtender(isoMap.getMap(), function(point) {
+				serviceIsochrone.sentRequest(point);
+			});
 
-			searchExtender = new SearchExtender(mapElem);
-			searchExtender.extendResult(isoMap.getMap());
+			searchExtender.extendResult();
 		}
 	}
 
diff --git a/src/main/webapp/js/isochrone/searchExtender.js b/src/main/webapp/js/isochrone/searchExtender.js
index 9902704f8c5231d2173e36fdb157f47cc05dee30..77bb3be9a5c1945720f7f0a6e47edf6fcfae41b1 100644
--- a/src/main/webapp/js/isochrone/searchExtender.js
+++ b/src/main/webapp/js/isochrone/searchExtender.js
@@ -1,14 +1,16 @@
 define(['jQuery', 'map/isoMap', 'isochrone/configuration'], function($, isoMap, Configuration) {
-	function SearchExtender(map) {
+	function SearchExtender(m, callback) {
+		var callbackFn = null;
 		var geosearchEventName = 'geosearch_showresult';
-		var m = null;
+		var map = null;
 
 		// Constructors
 
-		m = map;
+		callbackFn = callback;
+		map = m;
 
 		this.extendResult = function() {
-			m.on(geosearchEventName, onSearchResult.bind(this));
+			map.on(geosearchEventName, onSearchResult.bind(this));
 		};
 
 		// Private methods
@@ -61,11 +63,11 @@ define(['jQuery', 'map/isoMap', 'isochrone/configuration'], function($, isoMap,
 				iconIsochrone = null,
 				li;
 
-			if (!data.queryPoint) {
+			if (!data.point) {
 				return;
 			}
 
-			dSetConfigs = getDSetConfigs(data.queryPoint);
+			dSetConfigs = getDSetConfigs(data.point);
 			if (!dSetConfigs) {
 				return;
 			}
@@ -77,10 +79,12 @@ define(['jQuery', 'map/isoMap', 'isochrone/configuration'], function($, isoMap,
 			iconIsochrone.id = 'icon-isochrone';
 			iconIsochrone.className = 'icon-isochrone';
 			iconIsochrone.appendChild(document.createTextNode('Isochrone'));
+
 			divIcons.className = 'geosearch-result-icons';
 			divIcons.appendChild(iconIsochrone);
 
 			$(divIcons).insertBefore(li);
+			$(iconIsochrone).on('click', callbackFn.bind(this, data.point));
 		}
 	}
 
diff --git a/src/main/webapp/js/map/control/geosearch.js b/src/main/webapp/js/map/control/geosearch.js
index c4546b7e2b68fe15c31de61e7648cfac8b36e400..a94ce192f93913414c56f0b48fc7af4cede8a92c 100644
--- a/src/main/webapp/js/map/control/geosearch.js
+++ b/src/main/webapp/js/map/control/geosearch.js
@@ -247,6 +247,11 @@ define(['leaflet'], function(L) {
 			}
 		},
 
+		_onSearchClick: function () {
+			var queryBox = document.getElementById('leaflet-control-geosearch-qry');
+			this.geosearch(queryBox.value);
+		},
+
 		_onSuggestClick: function (e) {
 			var suggestId = e.target.id,
 				suggestIndex = -1,
@@ -265,12 +270,6 @@ define(['leaflet'], function(L) {
 			}
 		},
 
-		_onSearchClick: function () {
-			var queryBox = document.getElementById('leaflet-control-geosearch-qry');
-
-			this.geosearch(queryBox.value);
-		},
-
 		_processResults: function(results) {
 			if (results instanceof Array) {
 				this._processForwardResults(results);
@@ -341,7 +340,7 @@ define(['leaflet'], function(L) {
 			elem.appendChild(li);
 			elem.style.display = 'block';
 
-			this._map.fireEvent('geosearch_showresult', {element: elem, queryPoint: L.latLng({lat: parseFloat(result.lat), lon: parseFloat(result.lon)})});
+			this._map.fireEvent('geosearch_showresult', {element: elem, point: L.latLng({lat: parseFloat(result.lat), lon: parseFloat(result.lon)})});
 		},
 
 		_setSuggestList: function(results) {
diff --git a/src/main/webapp/js/service/serviceConfiguration.js b/src/main/webapp/js/service/serviceConfiguration.js
index d6749707ce64e8d9594f25f51187cdeb5f4606b5..9c7433c5a351ed30ae12942e94b243f36db74bb6 100644
--- a/src/main/webapp/js/service/serviceConfiguration.js
+++ b/src/main/webapp/js/service/serviceConfiguration.js
@@ -9,9 +9,11 @@ define(['jQuery', 'leaflet', 'console', 'isochrone/configuration'], function($,
 
 		// Public methods
 
-		this.getFromServer = function() {
+		this.initFromServer = function() {
 			$(document).on(actionName, onServerResponse.bind(this));
-			websocket.sendWsMessage('{"action" : "' + actionName + '"}');
+			websocket.sendWsMessage({
+				action: actionName
+			});
 		};
 
 		// Private methods
diff --git a/src/main/webapp/js/service/serviceIsochrone.js b/src/main/webapp/js/service/serviceIsochrone.js
new file mode 100644
index 0000000000000000000000000000000000000000..012f7272a5d212c814c1b4096037c6cd2c069ce3
--- /dev/null
+++ b/src/main/webapp/js/service/serviceIsochrone.js
@@ -0,0 +1,32 @@
+define(['jQuery', 'leaflet', 'console', 'isochrone/configuration'], function($, L, logger, Configuration) {
+	function ServiceIsochrone(ws) {
+		var actionName = 'getIsochrone';
+		var websocket = null;
+
+		// Constructor
+
+		websocket = ws;
+
+		// Public methods
+
+		this.sentRequest = function(point) {
+			var config = Configuration.getInstance();
+
+			$(document).on(actionName, onServerResponse.bind(this));
+			websocket.sendWsMessage({
+				action: actionName,
+				date: new Date()
+			});
+		};
+
+		// Private methods
+
+
+		function onServerResponse(data) {
+			console.debug(data.log);
+		}
+
+	}
+
+	return ServiceIsochrone;
+});
diff --git a/src/main/webapp/js/service/websocket.js b/src/main/webapp/js/service/websocket.js
index e38286e823591e301d00adf07918df532a73b909..80fd1ef61dda5beb22290d3b25b1b341538d8f20 100644
--- a/src/main/webapp/js/service/websocket.js
+++ b/src/main/webapp/js/service/websocket.js
@@ -31,9 +31,15 @@ define(['jQuery', 'console'], function($, logger) {
 		 *
 		 * @param msg {String} message to send
 		 */
-		this.sendWsMessage = function(msg) {
+		this.sendWsMessage = function(/* {String/Object} */msg) {
 			if (websocket.readyState === websocket.OPEN) {
-				websocket.send(msg);
+				if (typeof msg == 'string' || msg instanceof String) {
+					// msg is a string... send as is
+					websocket.send(msg);
+				} else {
+					// msg is an object... convert object to JSON before sending
+					websocket.send(JSON.stringify(msg));
+				}
 			} else if (websocket.readyState === websocket.CONNECTING) {
 				setTimeout(this.sendWsMessage.bind(this, msg), 100);
 			} else {
@@ -61,6 +67,16 @@ define(['jQuery', 'console'], function($, logger) {
 				return;
 			}
 
+			if (!jsonResponse.httpState) {
+				logger.warn('Invalid server response. No httpState attribute set');
+				return;
+			}
+
+			if (jsonResponse.httpState !== 200) {
+				onError(evt);
+				return;
+			}
+
 			var e = jQuery.Event(jsonResponse.action, jsonResponse);
 			$(document).trigger(e);
 		}