diff --git a/tdt4140-gr1800/pom.xml b/tdt4140-gr1800/pom.xml
index 1102480cdca09923ce759f1d199befb9914eaeed..b6427db7b693bc2a5ac790827999ac08592bd079 100644
--- a/tdt4140-gr1800/pom.xml
+++ b/tdt4140-gr1800/pom.xml
@@ -15,6 +15,9 @@
 		<module>app.core</module>
 		<module>FxMapControl</module>
 		<module>app.ui</module>
+		<!-- 
 		<module>web.server</module>
+		 -->
+		<module>web.server.jaxrs</module>
 	</modules>
 </project>
\ No newline at end of file
diff --git a/tdt4140-gr1800/web.server.jaxrs/.classpath b/tdt4140-gr1800/web.server.jaxrs/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..d46faf10ed6b222a00963f1db7c75123572c051c
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/.classpath
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/tdt4140-gr1800/web.server.jaxrs/.project b/tdt4140-gr1800/web.server.jaxrs/.project
new file mode 100644
index 0000000000000000000000000000000000000000..df8b92f9c9f141b4c188332767e413208f1ed392
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>tdt4140.gr1800.web.server.jaxrs.jaxrs.jaxrs</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.jdt.core.prefs b/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..13b3428acd87c3f94042e61eed221c15ce682bfa
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,13 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.m2e.core.prefs b/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..f897a7f1cb2389f85fe6381425d29f0a9866fb65
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/tdt4140-gr1800/web.server.jaxrs/README.md b/tdt4140-gr1800/web.server.jaxrs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1f4c88b7fc26fd3339ab360af4e00ea0631be5d5
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/README.md
@@ -0,0 +1 @@
+# web.server.jaxrs module - Web server providing a REST API to domain data, using JAX-RS implemented by Jersey
diff --git a/tdt4140-gr1800/web.server.jaxrs/pom.xml b/tdt4140-gr1800/web.server.jaxrs/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..16a2cb050868b53d2b4eae73862d249e37bf85a7
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/pom.xml
@@ -0,0 +1,158 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<artifactId>tdt4140-gr1800.web.server.jaxrs</artifactId>
+	<packaging>war</packaging>
+
+	<parent>
+		<groupId>tdt4140-gr1800</groupId>
+		<artifactId>tdt4140-gr1800</artifactId>
+		<version>0.0.1-SNAPSHOT</version>
+	</parent>
+
+	<properties>
+        <jetty.version>9.4.8.v20171121</jetty.version>
+        <jersey.version>2.26</jersey.version>
+    </properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>tdt4140-gr1800</groupId>
+			<artifactId>tdt4140-gr1800.app.core</artifactId>
+			<version>0.0.1-SNAPSHOT</version>
+		</dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+
+		<!--
+		Needed as of v. 2.26
+		See https://stackoverflow.com/questions/44088493/jersey-stopped-working-with-injectionmanagerfactory-not-found
+		 -->
+		<dependency>
+		    <groupId>org.glassfish.jersey.inject</groupId>
+		    <artifactId>jersey-hk2</artifactId>
+            <version>${jersey.version}</version>
+		</dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-servlet</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        
+        <!-- to use Jackson as provider for JSON media type -->
+        <dependency>
+    			<groupId>org.glassfish.jersey.media</groupId>
+    			<artifactId>jersey-media-json-jackson</artifactId>
+    			<version>2.26</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+			<version>2.9.3</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>2.9.3</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-annotations</artifactId>
+			<version>2.9.3</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.12</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.jacoco</groupId>
+				<artifactId>jacoco-maven-plugin</artifactId>
+				<version>0.8.0</version>
+				<executions>
+					<execution>
+						<id>pre-unit-test</id>
+						<goals>
+							<goal>prepare-agent</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>post-unit-test</id>
+						<phase>test</phase>
+						<goals>
+							<goal>report</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-maven-plugin -->
+				<groupId>org.eclipse.jetty</groupId>
+				<artifactId>jetty-maven-plugin</artifactId>
+				<version>9.4.8.v20171121</version>
+				<configuration>
+					<webApp>
+                        <contextPath>/jax-rs</contextPath>
+                    </webApp>				
+					<scanIntervalSeconds>0</scanIntervalSeconds>
+					<stopKey>stopMe</stopKey>
+					<stopPort>9966</stopPort>
+					<systemProperties>
+						<systemProperty>
+							<name>data.locations</name>
+							<value>file:${project.basedir}/src/test/resources/tdt4140/gr1800/web/server/geoLocations.json</value>
+						</systemProperty>
+					</systemProperties>
+				</configuration>
+				<executions>
+					<execution>
+						<id>start-jetty</id>
+						<phase>pre-integration-test</phase>
+						<goals>
+							<goal>start</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>stop-jetty</id>
+						<phase>post-integration-test</phase>
+						<goals>
+							<goal>stop</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-failsafe-plugin</artifactId>                                                              <!-- for starting jetty for integration tests -->
+				<version>2.16</version>
+				<executions>
+					<execution>
+						<id>integration-test</id>
+						<goals>
+							<goal>integration-test</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>verify</id>
+						<goals>
+							<goal>verify</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoObjectMapperProvider.java b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoObjectMapperProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..b61ee97a3c6a01119cb22d7bedb64d33eeea68cd
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoObjectMapperProvider.java
@@ -0,0 +1,57 @@
+package tdt4140.gr1800.web.server.jaxrs;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import tdt4140.gr1800.app.core.GeoLocation;
+import tdt4140.gr1800.app.core.GeoLocations;
+import tdt4140.gr1800.app.core.LatLong;
+import tdt4140.gr1800.app.core.Person;
+import tdt4140.gr1800.app.db.IdProvider;
+import tdt4140.gr1800.app.json.GeoLocationDeserializer;
+import tdt4140.gr1800.app.json.GeoLocationSerializer;
+import tdt4140.gr1800.app.json.GeoLocationsDeserializer;
+import tdt4140.gr1800.app.json.GeoLocationsSerializer;
+import tdt4140.gr1800.app.json.LatLongDeserializer;
+import tdt4140.gr1800.app.json.LatLongSerializer;
+import tdt4140.gr1800.app.json.PersonDeserializer;
+import tdt4140.gr1800.app.json.PersonSerializer;
+
+@Provider
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class GeoObjectMapperProvider implements ContextResolver<ObjectMapper> {
+
+	private final ObjectMapper objectMapper;
+	private final PersonSerializer personSerializer;
+
+	public GeoObjectMapperProvider() {
+		personSerializer = new PersonSerializer();
+		final SimpleModule module = new SimpleModule()
+				.addSerializer(new LatLongSerializer())
+				.addSerializer(new GeoLocationSerializer())
+				.addSerializer(new GeoLocationsSerializer())
+				.addSerializer(personSerializer)
+				.addDeserializer(LatLong.class, new LatLongDeserializer())
+				.addDeserializer(GeoLocation.class, new GeoLocationDeserializer())
+				.addDeserializer(GeoLocations.class, new GeoLocationsDeserializer())
+				.addDeserializer(Person.class, new PersonDeserializer());
+		objectMapper = new ObjectMapper()
+				.registerModule(module);
+	}
+
+	public void setPersonIdProvider(final IdProvider<Person> idProvider) {
+		personSerializer.setIdProvider(idProvider);
+	}
+
+	@Override
+	public ObjectMapper getContext(final Class<?> type) {
+		return objectMapper;
+	}
+}
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoService.java b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoService.java
new file mode 100644
index 0000000000000000000000000000000000000000..164715e459e7c5ce56a6f81fd35a9fbe381d876f
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoService.java
@@ -0,0 +1,137 @@
+package tdt4140.gr1800.web.server.jaxrs;
+
+import java.util.Collection;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Providers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tdt4140.gr1800.app.core.GeoLocations;
+import tdt4140.gr1800.app.core.Person;
+import tdt4140.gr1800.app.db.IDbAccess;
+
+@Path("geo")
+public class GeoService {
+
+	@Inject
+	IDbAccess dbAccess;
+
+	protected IDbAccess getDbAccess() {
+		return dbAccess;
+	}
+
+	@Context
+	private Providers providers;
+
+	@PostConstruct
+	protected void ensureIdProvider() {
+		final ContextResolver<ObjectMapper> resolver = providers.getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);
+		if (resolver instanceof GeoObjectMapperProvider) {
+			((GeoObjectMapperProvider) resolver).setPersonIdProvider(getDbAccess().getPersonIdProvider());
+		}
+	}
+
+	// REST URL structure, according to https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>
+
+	// GET variants
+	// persons: Get all Person objects. Do we allow that? Should we return a list of <id> values or all the person entities (with some subset of properties)
+	// persons/<id>: Get a specific Person object
+	// persons/name or email: Get a specific Person object, with the provided name or email (with a '@')
+	// persons/<id>/geoLocations: Get all the GeoLocations objects, with (some subset of) properties
+	// persons/<id>/geoLocations/<num>: Get a specific GeoLocations object
+	// persons/<id>/geoLocations/<num>/geoLocations: Get all GeoLocation objects, with (some subset of) properties
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Get a specific GeoLocation object
+
+	@GET
+	@Path("/persons")
+	@Produces(MediaType.APPLICATION_JSON)
+	public Collection<Person> getPersons() {
+		//		System.out.println("getPersons");
+		return getDbAccess().getAllPersons(false);
+	}
+
+	@GET
+	@Path("/persons/{id}")
+	@Produces(MediaType.APPLICATION_JSON)
+	public Person getPerson(@PathParam("id") final String idOrKey) {
+		//		System.out.println("getPerson: " + idOrKey);
+		Person person = null;
+		try {
+			final Integer num = Integer.valueOf(idOrKey);
+			person = getDbAccess().getPerson(num, false);
+		} catch (final NumberFormatException e) {
+			person = (idOrKey.contains("@") ? getDbAccess().getPersonByEmail(idOrKey, false) : getDbAccess().getPersonByName(idOrKey, false));
+		}
+		return person;
+	}
+
+	@GET
+	@Path("/persons/{id}/geoLocations")
+	@Produces(MediaType.APPLICATION_JSON)
+	public Collection<GeoLocations> getGeoLocations(@PathParam("id") final String idOrKey) throws RuntimeException {
+		//		System.out.println("getGeoLocations: " + idOrKey);
+		final Person person = getDbAccess().getPerson(Integer.valueOf(idOrKey), false);
+		return getDbAccess().getGeoLocations(person, false);
+	}
+
+	@GET
+	@Path("/persons/{id}/geoLocations/{num}")
+	@Produces(MediaType.APPLICATION_JSON)
+	public GeoLocations getGeoLocation(@PathParam("id") final int id, @PathParam("num") final int num) throws RuntimeException {
+		//		System.out.println("getGeoLocation: " + id + "," + num);
+		final Person person = getDbAccess().getPerson(id, false);
+		final int geoNum = 0;
+		for (final GeoLocations geoLocations : getDbAccess().getGeoLocations(person, false)) {
+			if (geoNum == num) {
+				return geoLocations;
+			}
+		}
+		return null;
+	}
+
+	// POST variants
+	// persons: Create a new Person object, with properties in the payload
+	// persons/<id>: Not allowed
+	// persons/<id>/geoLocations: Create a new GeoLocations object, with properties in the payload
+	// persons/<id>/geoLocations/<num>: Not allowed
+	// persons/<id>/geoLocations/<num>/geoLocations: Create a new GeoLocation object, with properties in the payload
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Not allowed
+
+	@POST
+	@Path("/persons")
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Produces(MediaType.APPLICATION_JSON)
+	public Person createPerson(final Person person, @Context final Providers providers) {
+		final Person dbPerson = getDbAccess().createPerson(person.getName(), person.getEmail());
+		return dbPerson;
+	}
+
+
+	// PUT variants
+	// persons: Not allowed
+	// persons/<id>: Update specific Person object
+	// persons/<id>/geoLocations: Not allowed
+	// persons/<id>/geoLocations/<num>: Update specific GeoLocations object
+	// persons/<id>/geoLocations/<num>/geoLocations: Not allowed
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Update specific GeoLocation object
+
+	// DELETE variants
+	// persons: Not allowed
+	// persons/<id>: Delete specific Person object
+	// persons/<id>/geoLocations: Delete all GeoLocations objects?
+	// persons/<id>/geoLocations/<num>: Delete specific GeoLocations object
+	// persons/<id>/geoLocations/<num>/geoLocations: Delete all GeoLocation objects?
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Delete specific GeoLocation object
+}
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceConfig.java b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..703d0bf5d90f9dff9eab65a10d2d0ef9a35599bf
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/main/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceConfig.java
@@ -0,0 +1,72 @@
+package tdt4140.gr1800.web.server.jaxrs;
+
+import java.sql.SQLException;
+
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import tdt4140.gr1800.app.db.DbAccessImpl;
+import tdt4140.gr1800.app.db.IDbAccess;
+
+public class GeoServiceConfig extends ResourceConfig {
+
+	public GeoServiceConfig() {
+
+		packages("tdt4140.gr1800.web.server.jaxrs");
+		register(GeoService.class);
+		register(GeoObjectMapperProvider.class);
+		register(JacksonFeature.class);
+
+
+		// https://stackoverflow.com/questions/16216759/dependency-injection-with-jersey-2-0
+		register(new AbstractBinder() {
+			@Override
+			protected void configure() {
+				bind(getDbAccess()).to(IDbAccess.class);
+			}
+		});
+	}
+
+
+	private IDbAccess dbAccess;
+
+	public IDbAccess getDbAccess() {
+		if (dbAccess == null) {
+			String dbConnectionUrl = "jdbc:hsqldb:mem:" + getClass().getName();
+			final Object dbConnectionParam = getProperty("dbConnectionURL");
+			if (dbConnectionParam != null) {
+				dbConnectionUrl = String.valueOf(dbConnectionParam);
+			}
+			try {
+				final DbAccessImpl dbAccess = new DbAccessImpl(dbConnectionUrl);
+				dbAccess.executeStatements("schema.sql", false);
+				this.dbAccess = dbAccess;
+			} catch (final SQLException e) {
+				throw new RuntimeException("Error when initializing database connection (" + dbConnectionUrl + "): " + e, e);
+			}
+		}
+		return dbAccess;
+	}
+
+	//	private ObjectMapper objectMapper;
+	//
+	//	public ObjectMapper getObjectMapper() {
+	//		if (objectMapper == null) {
+	//			final PersonSerializer personSerializer = new PersonSerializer();
+	//			personSerializer.setIdProvider(getDbAccess().getPersonIdProvider());
+	//			final SimpleModule module = new SimpleModule()
+	//					.addSerializer(new LatLongSerializer())
+	//					.addSerializer(new GeoLocationSerializer())
+	//					.addSerializer(new GeoLocationsSerializer())
+	//					.addSerializer(personSerializer)
+	//					.addDeserializer(LatLong.class, new LatLongDeserializer())
+	//					.addDeserializer(GeoLocation.class, new GeoLocationDeserializer())
+	//					.addDeserializer(GeoLocations.class, new GeoLocationsDeserializer())
+	//					.addDeserializer(Person.class, new PersonDeserializer());
+	//			objectMapper = new ObjectMapper()
+	//					.registerModule(module);
+	//		}
+	//		return objectMapper;
+	//	}
+}
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/main/webapp/WEB-INF/web.xml b/tdt4140-gr1800/web.server.jaxrs/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000000000000000000000000000000000..083954205f6f235e2b053a4c7efc1fdb64e691ab
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+	metadata-complete="false" version="3.1">
+
+	<!--
+	https://stackoverflow.com/questions/38639425/basic-jersey-webservice-with-maven-jetty-plugin
+	 -->
+	<servlet>
+		<servlet-name>Jersey REST Service</servlet-name>
+		<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+		<init-param>
+			<param-name>javax.ws.rs.Application</param-name>
+			<param-value>tdt4140.gr1800.web.server.jaxrs.GeoServiceConfig</param-value>
+		</init-param>
+		<!-- 
+        <init-param>
+            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
+            <param-value>true</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+		 -->
+	</servlet>
+
+	<servlet-mapping>
+        <servlet-name>Jersey REST Service</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+</web-app>
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/test/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceIT.java b/tdt4140-gr1800/web.server.jaxrs/src/test/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceIT.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c7bc64ae85fa38bb794d8628fb8540d135a0d02
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/test/java/tdt4140/gr1800/web/server/jaxrs/GeoServiceIT.java
@@ -0,0 +1,145 @@
+package tdt4140.gr1800.web.server.jaxrs;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.NumericNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.ValueNode;
+
+import tdt4140.gr1800.app.core.Person;
+
+public class GeoServiceIT {
+
+	private ObjectMapper objectMapper;
+
+	@Before
+	public void setUp() {
+		objectMapper = new GeoObjectMapperProvider().getContext(getClass());
+	}
+
+	private HttpURLConnection createUrlConnection(final String path) {
+		try {
+			return (HttpURLConnection) (new URL("http://localhost:8080/jax-rs/geo/" + path).openConnection());
+		} catch (final MalformedURLException e) {
+			throw new RuntimeException(e);
+		} catch (final IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	protected Collection<Person> getPersons(final ArrayNode arrayNode) throws JsonProcessingException {
+		final Collection<Person> persons = new ArrayList<Person>();
+		for (final JsonNode childNode : arrayNode) {
+			persons.add(objectMapper.treeToValue(childNode, Person.class));
+		}
+		return persons;
+	}
+
+	protected int testPerson(final InputStream input, final Person person) throws Exception {
+		final JsonNode jsonTree = objectMapper.readTree(input);
+		Assert.assertTrue(jsonTree instanceof ObjectNode);
+		Assert.assertTrue(((ObjectNode) jsonTree).has("id"));
+		final JsonNode idNode = ((ObjectNode) jsonTree).get("id");
+		Assert.assertTrue(idNode instanceof ValueNode);
+		final int id = (idNode instanceof NumericNode ? ((NumericNode) idNode).asInt() : Integer.valueOf(idNode.asText()));
+		Assert.assertTrue(isPerson(person, objectMapper.treeToValue(jsonTree, Person.class)));
+		return id;
+	}
+
+	protected void testGetPerson(final int id, final Person person) throws Exception {
+		final HttpURLConnection con = createUrlConnection("persons/" + id);
+		con.setRequestMethod("GET");
+		con.setDoInput(true);
+		try (InputStream conIn = con.getInputStream()) {
+			testPerson(conIn, person);
+		}
+	}
+
+	protected boolean isPerson(final Person person, final Person conPerson) {
+		return person.getName().equals(conPerson.getName()) && person.getEmail().equals(conPerson.getEmail());
+	}
+
+	protected void testGetPersons(final Person... persons) throws Exception {
+		final HttpURLConnection con = createUrlConnection("persons");
+		con.setRequestMethod("GET");
+		con.setDoInput(true);
+		try (InputStream conIn = con.getInputStream()) {
+			final JsonNode jsonTree = objectMapper.readTree(conIn);
+			Assert.assertTrue(jsonTree instanceof ArrayNode);
+			final Collection<Person> conPersons = getPersons((ArrayNode) jsonTree);
+			outer:  for (final Person person : persons) {
+				for (final Person conPerson : conPersons) {
+					if (isPerson(person, conPerson)) {
+						continue outer;
+					}
+				}
+				Assert.fail();
+			}
+		}
+	}
+
+	@Test
+	public void testCreatePersonGetPerson() throws Exception {
+		final Person person = new Person();
+		person.setName("Hallvard");
+		person.setEmail("hal@ntnu.no");
+		final HttpURLConnection con = createUrlConnection("persons");
+		con.setRequestMethod("POST");
+		con.setDoOutput(true);
+		con.setDoInput(true);
+		final ByteArrayOutputStream out = new ByteArrayOutputStream();
+		objectMapper.writeValue(out, person);
+		out.close();
+		final byte[] bytes = out.toByteArray();
+		con.setFixedLengthStreamingMode(bytes.length);
+		con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
+		con.connect();
+		try (OutputStream conOut = con.getOutputStream()) {
+			conOut.write(bytes);
+		}
+		try (InputStream conIn = con.getInputStream()) {
+			final int id = testPerson(conIn, person);
+			testGetPerson(id, person);
+		}
+	}
+
+	@Test
+	public void testCreatePersonGetPersons() throws Exception {
+		final Person person = new Person();
+		person.setName("Hallvard");
+		person.setEmail("hallvard.traetteberg@gmail.com");
+		final HttpURLConnection con = createUrlConnection("persons");
+		con.setRequestMethod("POST");
+		con.setDoOutput(true);
+		con.setDoInput(true);
+		final ByteArrayOutputStream out = new ByteArrayOutputStream();
+		objectMapper.writeValue(out, person);
+		out.close();
+		final byte[] bytes = out.toByteArray();
+		con.setFixedLengthStreamingMode(bytes.length);
+		con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
+		con.connect();
+		try (OutputStream conOut = con.getOutputStream()) {
+			conOut.write(bytes);
+		}
+		try (InputStream conIn = con.getInputStream()) {
+			testGetPersons(person);
+		}
+	}
+}
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-route.gpx b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-route.gpx
new file mode 100644
index 0000000000000000000000000000000000000000..a006258ea21c91c5dedcb385650ec4abbee0ae9e
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-route.gpx
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<gpx
+  version="1.0"
+  creator="VB Net GPS:  vermeiren-willy@pandora.be"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://www.topografix.com/GPX/1/0"
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+
+<metadata>
+	<bounds minlat="51.396017" minlon="4.498043" maxlat="51.430402" maxlon="4.556108"/>
+</metadata>
+
+<wpt lat="51.39709" lon="4.501519">
+   <name>START</name>
+</wpt>
+
+<rte>
+  <name>Achterbroek naar De Maatjes   13 km RT</name>
+    <rtept lat="51.39709" lon="4.501519">
+      <name>1</name>
+      <cmt>1</cmt>
+    </rtept>
+    <rtept lat="51.398635" lon="4.502678">
+      <name>2</name>
+      <cmt>2</cmt>
+    </rtept>
+    <rtept lat="51.405072" lon="4.498043">
+      <name>3</name>
+      <cmt>3</cmt>
+    </rtept>
+    <rtept lat="51.417346" lon="4.515038">
+      <name>4</name>
+      <cmt>4</cmt>
+    </rtept>
+    <rtept lat="51.41932" lon="4.513879">
+      <name>5</name>
+      <cmt>5</cmt>
+    </rtept>
+    <rtept lat="51.421552" lon="4.523535">
+      <name>6</name>
+      <cmt>6</cmt>
+    </rtept>
+    <rtept lat="51.423011" lon="4.522848">
+      <name>7</name>
+      <cmt>7</cmt>
+    </rtept>
+    <rtept lat="51.423826" lon="4.5295">
+      <name>8</name>
+      <cmt>8</cmt>
+    </rtept>
+    <rtept lat="51.427002" lon="4.528513">
+      <name>9</name>
+      <cmt>9</cmt>
+    </rtept>
+    <rtept lat="51.430402" lon="4.552363">
+      <name>10</name>
+      <cmt>10</cmt>
+    </rtept>
+    <rtept lat="51.426229" lon="4.555399">
+      <name>11</name>
+      <cmt>11</cmt>
+    </rtept>
+    <rtept lat="51.426015" lon="4.554734">
+      <name>12</name>
+      <cmt>12</cmt>
+    </rtept>
+    <rtept lat="51.423569" lon="4.556108">
+      <name>13</name>
+      <cmt>13</cmt>
+    </rtept>
+    <rtept lat="51.41932" lon="4.546237">
+      <name>14</name>
+      <cmt>14</cmt>
+    </rtept>
+    <rtept lat="51.410952" lon="4.534092">
+      <name>15</name>
+      <cmt>15</cmt>
+    </rtept>
+    <rtept lat="51.406231" lon="4.543018">
+      <name>16</name>
+      <cmt>16</cmt>
+    </rtept>
+    <rtept lat="51.396695" lon="4.515966">
+      <name>17</name>
+      <cmt>17</cmt>
+    </rtept>
+    <rtept lat="51.396017" lon="4.515853">
+      <name>18</name>
+      <cmt>18</cmt>
+    </rtept>
+    <rtept lat="51.397133" lon="4.502635">
+      <name>19</name>
+      <cmt>19</cmt>
+    </rtept>
+</rte>
+</gpx>
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-track.gpx b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-track.gpx
new file mode 100644
index 0000000000000000000000000000000000000000..755f740e02199462cfa12b8a5243c73f49258786
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/Achterbroek-track.gpx
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<gpx
+  version="1.0"
+  creator="VB Net GPS:  vermeiren-willy@pandora.be"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://www.topografix.com/GPX/1/0"
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+
+<metadata>
+	<bounds minlat="51.396017" minlon="4.498043" maxlat="51.430402" maxlon="4.556108"/>
+</metadata>
+
+<wpt lat="51.39709" lon="4.501519">
+   <name>START</name>
+</wpt>
+
+<trk>
+  <name>Achterbroek naar De Maatjes   13 km TR</name>
+  <trkseg>
+    <trkpt lat="51.39709" lon="4.501519">
+      <name>1</name>
+    </trkpt>
+    <trkpt lat="51.397705" lon="4.501452">
+      <name>2</name>
+    </trkpt>
+    <trkpt lat="51.398635" lon="4.502678">
+      <name>3</name>
+    </trkpt>
+    <trkpt lat="51.404042" lon="4.498472">
+      <name>4</name>
+    </trkpt>
+    <trkpt lat="51.405072" lon="4.498043">
+      <name>5</name>
+    </trkpt>
+    <trkpt lat="51.405456" lon="4.499259">
+      <name>6</name>
+    </trkpt>
+    <trkpt lat="51.417346" lon="4.515038">
+      <name>7</name>
+    </trkpt>
+    <trkpt lat="51.41932" lon="4.513879">
+      <name>8</name>
+    </trkpt>
+    <trkpt lat="51.421552" lon="4.523535">
+      <name>9</name>
+    </trkpt>
+    <trkpt lat="51.423011" lon="4.522848">
+      <name>10</name>
+    </trkpt>
+    <trkpt lat="51.423826" lon="4.5295">
+      <name>11</name>
+    </trkpt>
+    <trkpt lat="51.427002" lon="4.528513">
+      <name>12</name>
+    </trkpt>
+    <trkpt lat="51.427131" lon="4.534478">
+      <name>13</name>
+    </trkpt>
+    <trkpt lat="51.426819" lon="4.53744">
+      <name>14</name>
+    </trkpt>
+    <trkpt lat="51.430402" lon="4.552363">
+      <name>15</name>
+    </trkpt>
+    <trkpt lat="51.426229" lon="4.555399">
+      <name>16</name>
+    </trkpt>
+    <trkpt lat="51.426015" lon="4.554734">
+      <name>17</name>
+    </trkpt>
+    <trkpt lat="51.423569" lon="4.556108">
+      <name>18</name>
+    </trkpt>
+    <trkpt lat="51.423097" lon="4.553981">
+      <name>19</name>
+    </trkpt>
+    <trkpt lat="51.41932" lon="4.546237">
+      <name>20</name>
+    </trkpt>
+    <trkpt lat="51.410952" lon="4.534092">
+      <name>21</name>
+    </trkpt>
+    <trkpt lat="51.406231" lon="4.543018">
+      <name>22</name>
+    </trkpt>
+    <trkpt lat="51.396695" lon="4.515966">
+      <name>23</name>
+    </trkpt>
+    <trkpt lat="51.396017" lon="4.515853">
+      <name>24</name>
+    </trkpt>
+    <trkpt lat="51.396858" lon="4.506495">
+      <name>25</name>
+    </trkpt>
+    <trkpt lat="51.397133" lon="4.502635">
+      <name>26</name>
+    </trkpt>
+  </trkseg>
+</trk>
+</gpx>
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/geoLocations.json b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/geoLocations.json
new file mode 100644
index 0000000000000000000000000000000000000000..bfda7a4524d5419067f9a0dba069740402aff30d
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/geoLocations.json
@@ -0,0 +1,17 @@
+[
+  {
+    "name" : "1",
+    "locations" : [
+      { "latitude" : "63", "longitude" : "10" },
+      [ "63.1", "10.1" ]
+    ]
+  },
+  {
+    "name" : "2",
+    "path" : "true",
+    "locations" : [
+      { "latitude" : "64", "longitude" : "11" },
+      [ "64.1", "11.1" ]
+    ]
+  }
+]
diff --git a/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/sample1.gpx b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/sample1.gpx
new file mode 100644
index 0000000000000000000000000000000000000000..79b840dd8808e6834ce6ef5fed1a6b428b3d0767
--- /dev/null
+++ b/tdt4140-gr1800/web.server.jaxrs/src/test/resources/tdt4140/gr1800/web/server/sample1.gpx
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
+  <metadata>
+    <link href="http://www.garmin.com">
+      <text>Garmin International</text>
+    </link>
+    <time>2009-10-17T22:58:43Z</time>
+  </metadata>
+  <trk>
+    <name>Example GPX Document</name>
+    <trkseg>
+      <trkpt lat="47.644548" lon="-122.326897">
+        <ele>4.46</ele>
+        <time>2009-10-17T18:37:26Z</time>
+      </trkpt>
+      <trkpt lat="47.644548" lon="-122.33">
+        <ele>4.94</ele>
+        <time>2009-10-17T18:37:31Z</time>
+      </trkpt>
+      <trkpt lat="47.65" lon="-122.33">
+        <ele>6.87</ele>
+        <time>2009-10-17T18:37:34Z</time>
+      </trkpt>
+    </trkseg>
+  </trk>
+</gpx>
diff --git a/tdt4140-gr1800/web.server/src/main/java/tdt4140/gr1800/web/server/GeoServlet.java b/tdt4140-gr1800/web.server/src/main/java/tdt4140/gr1800/web/server/GeoServlet.java
index b4cf14893cce046fa05b7b9d0dd94709d984e4a2..2fc6c0ee04be2d1bf8ef14f4950395584dd345a2 100644
--- a/tdt4140-gr1800/web.server/src/main/java/tdt4140/gr1800/web/server/GeoServlet.java
+++ b/tdt4140-gr1800/web.server/src/main/java/tdt4140/gr1800/web/server/GeoServlet.java
@@ -3,7 +3,9 @@ package tdt4140.gr1800.web.server;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Iterator;
 
 import javax.servlet.ServletException;
@@ -91,23 +93,33 @@ public class GeoServlet extends HttpServlet {
 	// persons/<id>/geoLocations: Get all the GeoLocations objects, with (some subset of) properties
 	// persons/<id>/geoLocations/<num>: Get a specific GeoLocations object
 	// persons/<id>/geoLocations/<num>/geoLocations: Get all GeoLocation objects, with (some subset of) properties
-	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Get a specific GeoLocations object
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Get a specific GeoLocation object
 
 	@Override
 	protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-		final HttpMethod method = new GetMethod(rootEntity);
+		doRequest(request, new GetMethod(rootEntity), false, true, response);
+	}
+
+	protected void doRequest(final HttpServletRequest request, final HttpMethod method, final boolean jsonInput, final boolean jsonOutput, final HttpServletResponse response) throws ServletException, IOException {
+		final JsonNode jsonNode = (jsonInput ? objectMapper.readTree(request.getInputStream()) : null);
+		method.setPayload(jsonNode);
 		final Object result = method.doMethod(getPathSegments(request));
 		if (result == null) {
 			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
 		} else {
-			respondWithJson(response, result);
+			response.setStatus(HttpServletResponse.SC_OK);
+			if (jsonOutput) {
+				respondWithJson(response, result);
+			} else {
+				response.setStatus(HttpServletResponse.SC_OK);
+			}
 		}
 	}
 
 	protected void respondWithJson(final HttpServletResponse response, final Object result) {
 		response.setContentType("application/json");
-		response.setStatus(HttpServletResponse.SC_OK);
 		try (OutputStream output = response.getOutputStream()) {
+			response.setStatus(HttpServletResponse.SC_OK);
 			objectMapper.writerWithDefaultPrettyPrinter().writeValue(output, result);
 		} catch (final Exception e) {
 			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
@@ -119,8 +131,10 @@ public class GeoServlet extends HttpServlet {
 		if (path == null) {
 			throw new ServletException("Path cannot be empty");
 		}
-		final Iterator<String> segments = Arrays.asList(path.split("\\/")).iterator();
-		return segments;
+		final Collection<String> segments = new ArrayList<String>(Arrays.asList(path.split("\\/")));
+		// remove empty segments
+		while (segments.remove(""));
+		return segments.iterator();
 	}
 
 	// POST variants
@@ -133,15 +147,7 @@ public class GeoServlet extends HttpServlet {
 
 	@Override
 	protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-		final HttpMethod method = new PostMethod(rootEntity);
-		final JsonNode jsonNode = objectMapper.readTree(request.getInputStream());
-		method.setPayload(jsonNode);
-		final Object result = method.doMethod(getPathSegments(request));
-		if (result == null) {
-			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-		} else {
-			respondWithJson(response, result);
-		}
+		doRequest(request, new PostMethod(rootEntity), true, true, response);
 	}
 
 	// PUT variants
@@ -150,19 +156,11 @@ public class GeoServlet extends HttpServlet {
 	// persons/<id>/geoLocations: Not allowed
 	// persons/<id>/geoLocations/<num>: Update specific GeoLocations object
 	// persons/<id>/geoLocations/<num>/geoLocations: Not allowed
-	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Update specific GeoLocations object
+	// persons/<id>/geoLocations/<num>/geoLocations/<num>: Update specific GeoLocation object
 
 	@Override
 	protected void doPut(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-		final HttpMethod method = new PutMethod(rootEntity);
-		final JsonNode jsonNode = objectMapper.readTree(request.getInputStream());
-		method.setPayload(jsonNode);
-		final Object result = method.doMethod(getPathSegments(request));
-		if (result == null) {
-			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-		} else {
-			respondWithJson(response, result);
-		}
+		doRequest(request, new PutMethod(rootEntity), true, true, response);
 	}
 
 	// DELETE variants
@@ -175,12 +173,6 @@ public class GeoServlet extends HttpServlet {
 
 	@Override
 	protected void doDelete(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-		final HttpMethod method = new DeleteMethod(rootEntity);
-		final Object result = method.doMethod(getPathSegments(request));
-		if (result == null) {
-			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-		} else {
-			respondWithJson(response, result);
-		}
+		doRequest(request, new DeleteMethod(rootEntity), false, true, response);
 	}
 }