diff --git a/lombok.config b/lombok.config
new file mode 100644
index 0000000000000000000000000000000000000000..d07dd9b0e2b0281fbf514a968b9451cb6af62f93
--- /dev/null
+++ b/lombok.config
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+lombok.log.fieldName=LOG
+lombok.log.slf4j.flagUsage = ERROR
+lombok.log.log4j.flagUsage = ERROR
+lombok.data.flagUsage = ERROR
+lombok.nonNull.exceptionType = IllegalArgumentException
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 6772822cf565a491dc69b2ff6a29f000fae4dad9..45252f6f8c192a2c2193b81a2af6ee47bf9b8813 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,6 +91,20 @@
 			<version>${mapstruct-processor.version}</version>
 		</dependency>
 
+		<!-- commons -->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
+		</dependency>
+
 		<!-- mongock -->
 		<dependency>
 			<groupId>io.mongock</groupId>
diff --git a/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceDeserializer.java b/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a6a78f0d9dbfaba065908fa153d61f83d785933
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceDeserializer.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import de.ozgcloud.common.datatype.StringBasedValue;
+import lombok.Getter;
+
+abstract class AbstractLinkedResourceDeserializer extends StdDeserializer<Object> implements ContextualDeserializer {
+
+	private static final long serialVersionUID = 1L;
+
+	@Getter
+	private BeanProperty beanProperty;
+
+	@Getter
+	private final JavaType targetType;
+
+	protected AbstractLinkedResourceDeserializer() {
+		super(Object.class);
+		targetType = null;
+	}
+
+	protected AbstractLinkedResourceDeserializer(BeanProperty beanProperty) {
+		super(Object.class);
+		this.beanProperty = beanProperty;
+		this.targetType = beanProperty.getType();
+	}
+
+	@Override
+	public Object deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
+		if (jsonParser.isExpectedStartArrayToken()) {
+			Collection<Object> idList = targetType.getRawClass().isAssignableFrom(Set.class) ? new HashSet<>() : new ArrayList<>();
+
+			while (!jsonParser.nextToken().isStructEnd()) {
+				idList.add(extractId(jsonParser.getText()));
+			}
+			return idList;
+		} else {
+			return extractId(jsonParser.getText());
+		}
+	}
+
+	Object extractId(String url) {
+		Class<?> type;
+		if (targetType.isCollectionLikeType()) {
+			type = targetType.getContentType().getRawClass();
+		} else {
+			type = targetType.getRawClass();
+		}
+
+		if (String.class.isAssignableFrom(type)) {
+			return extractStringId(url);
+		}
+		if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type)) {
+			return extractLongId(url);
+		}
+		if (StringBasedValue.class.isAssignableFrom(type)) {
+			return extractStringBasedValue(type, url);
+		}
+		return buildByBuilder(url);
+	}
+
+	abstract Object buildByBuilder(String url);
+
+	public static Long extractLongId(String uri) {
+		var trimedUri = StringUtils.trimToNull(uri);
+		if (Objects.isNull(trimedUri)) {
+			return null;
+		}
+		return Long.parseLong(URLDecoder.decode(trimedUri.substring(trimedUri.lastIndexOf('/') + 1), StandardCharsets.UTF_8));
+	}
+
+	private StringBasedValue extractStringBasedValue(Class<?> type, String url) {
+		String value = extractStringId(url);
+		Method fromMethod;
+		try {
+			fromMethod = type.getMethod("from", String.class);
+		} catch (NoSuchMethodException e) {
+			throw new IllegalStateException(
+					String.format("Cannot generate Id from type '%s'. Missing 'from' Method.", targetType.getRawClass().getSimpleName()));
+		}
+		try {
+			return (StringBasedValue) fromMethod.invoke(null, value);
+		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+			throw new IllegalStateException(
+					String.format("Cannot generate Id from type '%s'. Error calling 'from' Method.", targetType.getRawClass().getSimpleName()),
+					e);
+		}
+	}
+
+	public static String extractStringId(String url) {
+		return URLDecoder.decode(url.substring(url.lastIndexOf('/') + 1), StandardCharsets.UTF_8);
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceSerializer.java b/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e7ff8b53699d3c1f6d473f8992a20ddb548917b
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/AbstractLinkedResourceSerializer.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+
+abstract class AbstractLinkedResourceSerializer extends JsonSerializer<Object> implements ContextualSerializer {
+	@Override
+	public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+
+		if (value instanceof Collection) {
+			gen.writeStartArray();
+			((Collection<?>) value).forEach(val -> writeObject(gen, buildLink(val)));
+			gen.writeEndArray();
+		} else {
+			writeObject(gen, buildLink(value));
+		}
+	}
+
+	abstract String buildLink(Object id);
+
+	abstract IdExtractor<Object> getExtractor();
+
+	void writeObject(JsonGenerator gen, Object value) {
+		try {
+			gen.writeObject(value);
+		} catch (IOException e) {
+			throw new TechnicalException("Error writing String to json", e);
+		}
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/CollectionModelBuilder.java b/src/main/java/de/ozgcloud/admin/common/CollectionModelBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6976eac3335b4251b2b9e4bd4aeeb02f3b8112b
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/CollectionModelBuilder.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.springframework.hateoas.CollectionModel;
+import org.springframework.hateoas.Link;
+
+import lombok.RequiredArgsConstructor;
+
+public class CollectionModelBuilder<T> {
+
+	private final Iterable<T> entities;
+
+	private final List<Link> links = new LinkedList<>();
+
+	private CollectionModelBuilder(Iterable<T> entities) {
+		this.entities = entities;
+	}
+
+	public static <T> CollectionModelBuilder<T> fromEntities(Iterable<T> entities) {
+		return new CollectionModelBuilder<>(entities);
+	}
+
+	public static <T> CollectionModelBuilder<T> fromEntities(Stream<T> entities) {
+		return new CollectionModelBuilder<>(entities.toList());
+	}
+
+	public CollectionModelBuilder<T> addLink(Link link) {
+		links.add(link);
+		return this;
+	}
+
+	public ConditionalLinkAdder ifMatch(BooleanSupplier guard) {
+		return new ConditionalLinkAdder(guard.getAsBoolean());
+	}
+
+	public ConditionalLinkAdder ifMatch(Predicate<? super Iterable<T>> predicate) {
+		return new ConditionalLinkAdder(predicate.test(entities));
+	}
+
+	public CollectionModel<T> buildModel() {
+		var builtModel = CollectionModel.of(entities);
+		builtModel.add(links);
+		return builtModel;
+	}
+
+	@RequiredArgsConstructor
+	public class ConditionalLinkAdder {
+
+		public final boolean conditionFulfilled;
+
+		public CollectionModelBuilder<T> addLink(Link link) {
+			if (conditionFulfilled) {
+				links.add(link);
+			}
+			return CollectionModelBuilder.this;
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/common/IdBuilder.java b/src/main/java/de/ozgcloud/admin/common/IdBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..17e590d1935ca727f001834823bfd26b4476b5fe
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/IdBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+class IdBuilder implements ObjectBuilder<Object> {
+
+	@Override
+	public Object build(Object id) {
+		return id;
+	}
+
+	@Override
+	public ObjectBuilder<Object> constructContextAware(BeanProperty property) {
+		return new IdBuilder();
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/IdExtractor.java b/src/main/java/de/ozgcloud/admin/common/IdExtractor.java
new file mode 100644
index 0000000000000000000000000000000000000000..baed5fa621ee3e38bc11844b3e02abb7e4fbdf22
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/IdExtractor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+@FunctionalInterface
+public interface IdExtractor<T> {
+	String extractId(T object);
+}
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/common/LinkedResource.java b/src/main/java/de/ozgcloud/admin/common/LinkedResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..f06b9786f97aab1f42ecb583c447edbdf16f50d7
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/LinkedResource.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.core.annotation.AliasFor;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+
+@JacksonAnnotationsInside
+@JsonSerialize(using = LinkedResourceSerializer.class)
+@JsonDeserialize(using = LinkedResourceDeserializer.class)
+public @interface LinkedResource {
+
+	Class<?> controllerClass();
+
+	Class<? extends IdExtractor<Object>> extractor() default ToStringExtractor.class;
+
+	@AliasFor(annotation = JsonDeserialize.class, attribute = "builder")
+	Class<? extends ObjectBuilder<Object>> builder() default IdBuilder.class;
+}
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/common/LinkedResourceDeserializer.java b/src/main/java/de/ozgcloud/admin/common/LinkedResourceDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f312a3035ee1c85426cc1230e5ef8a58bb2dec1
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/LinkedResourceDeserializer.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.commons.lang3.reflect.ConstructorUtils;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+
+public class LinkedResourceDeserializer extends AbstractLinkedResourceDeserializer {
+
+	private static final long serialVersionUID = 1L;
+
+	private LinkedResource annotation;
+
+	protected LinkedResourceDeserializer() {
+		super();
+	}
+
+	protected LinkedResourceDeserializer(BeanProperty beanProperty) {
+		super(beanProperty);
+		this.annotation = beanProperty.getAnnotation(LinkedResource.class);
+	}
+
+	@Override
+	Object buildByBuilder(String url) {
+		ObjectBuilder<?> builder;
+		try {
+			builder = ConstructorUtils.invokeConstructor(annotation.builder()).constructContextAware(getBeanProperty());
+		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
+			throw new TechnicalException("Error instanciating Builder.", e);
+		}
+		return builder.build(extractStringId(url));
+	}
+
+	@Override
+	public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
+		return new LinkedResourceDeserializer(property);
+	}
+
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/LinkedResourceSerializer.java b/src/main/java/de/ozgcloud/admin/common/LinkedResourceSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..698bfb2904de5f7bb4261c05c6fc4b74ba2d9ef8
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/LinkedResourceSerializer.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.commons.lang3.reflect.ConstructorUtils;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+public class LinkedResourceSerializer extends AbstractLinkedResourceSerializer {
+
+	private LinkedResource annotation;
+
+	private LinkedResourceSerializer(LinkedResource annotation) {
+		this.annotation = annotation;
+	}
+
+	@Override
+	public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
+		return new LinkedResourceSerializer(property.getAnnotation(LinkedResource.class));
+	}
+
+	@Override
+	String buildLink(Object id) {
+		return linkTo(annotation.controllerClass()).slash(getExtractor().extractId(id)).toString();
+	}
+
+	@Override
+	IdExtractor<Object> getExtractor() {
+		try {
+			return ConstructorUtils.invokeConstructor(annotation.extractor());
+		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
+			throw new TechnicalException("Error instanciating IdExtractor", e);
+		}
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/ModelBuilder.java b/src/main/java/de/ozgcloud/admin/common/ModelBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..11f4c3c001fe908ed2f02b2100399ffb2670084a
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/ModelBuilder.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.hateoas.Link;
+import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+public class ModelBuilder<T> {
+
+	private static final Map<Class<?>, Map<Object, List<Field>>> ANNOTATED_FIELDS_BY_ANNOTATION = new ConcurrentHashMap<>();
+
+	private final T entity;
+	private final EntityModel<T> model;
+
+	private final List<Link> links = new LinkedList<>();
+	private final List<Function<EntityModel<T>, EntityModel<T>>> mapper = new LinkedList<>();
+
+	private ModelBuilder(T entity) {
+		this.entity = entity;
+		this.model = null;
+	}
+
+	private ModelBuilder(EntityModel<T> model) {
+		this.entity = null;
+		this.model = model;
+	}
+
+	public static <T> ModelBuilder<T> fromEntity(T entity) {
+		return new ModelBuilder<>(entity);
+	}
+
+	public static <T> ModelBuilder<T> fromModel(EntityModel<T> model) {
+		return new ModelBuilder<>(model);
+	}
+
+	public ModelBuilder<T> addLink(Link link) {
+		links.add(link);
+		return this;
+	}
+
+	public ModelBuilder<T> addLink(Optional<Link> link) {
+		link.ifPresent(links::add);
+		return this;
+	}
+
+	public ModelBuilder<T> addLinks(Link... links) {
+		this.links.addAll(Arrays.asList(links));
+		return this;
+	}
+
+	public ModelBuilder<T> addLinks(Collection<Link> links) {
+		this.links.addAll(links);
+		return this;
+	}
+
+	public ConditionalLinkAdder ifMatch(Predicate<T> predicate) {
+		return new ConditionalLinkAdder(predicate.test(Objects.isNull(entity) ? model.getContent() : entity));
+	}
+
+	public ConditionalLinkAdder ifMatch(BooleanSupplier guard) {
+		return new ConditionalLinkAdder(guard.getAsBoolean());
+	}
+
+	public ModelBuilder<T> map(UnaryOperator<EntityModel<T>> mapper) {
+		this.mapper.add(mapper);
+		return this;
+	}
+
+	public EntityModel<T> buildModel() {
+		var filteredLinks = links.stream().filter(Objects::nonNull).collect(Collectors.toSet());
+
+		EntityModel<T> buildedModel = Objects.isNull(model) ? EntityModel.of(entity) : model;
+		buildedModel = buildedModel.add(filteredLinks);
+
+		addLinkByLinkedResourceAnnotationIfMissing(buildedModel);
+
+		return applyMapper(buildedModel);
+	}
+
+	private EntityModel<T> applyMapper(EntityModel<T> resource) {
+		Iterator<Function<EntityModel<T>, EntityModel<T>>> i = mapper.iterator();
+		EntityModel<T> result = resource;
+		while (i.hasNext()) {
+			result = i.next().apply(result);
+		}
+		return result;
+	}
+
+	private void addLinkByLinkedResourceAnnotationIfMissing(EntityModel<T> resource) {
+		getFields(LinkedResource.class).stream()
+				.filter(field -> shouldAddLink(resource, field))
+				.forEach(field -> handleLinkedResourceField(resource, field));
+	}
+
+	private void handleLinkedResourceField(EntityModel<T> resource, Field field) {
+		getEntityFieldValue(field).map(Object::toString).filter(StringUtils::isNotBlank).ifPresent(val -> resource
+				.add(WebMvcLinkBuilder.linkTo(field.getAnnotation(LinkedResource.class).controllerClass()).slash(val)
+						.withRel(sanitizeName(field.getName()))));
+	}
+
+	private boolean shouldAddLink(EntityModel<T> resource, Field field) {
+		return !(field.getType().isArray() || Collection.class.isAssignableFrom(field.getType()) || resource.hasLink(sanitizeName(field.getName())));
+	}
+
+	private List<Field> getFields(Class<? extends Annotation> annotationClass) {
+		var fields = Optional.ofNullable(ANNOTATED_FIELDS_BY_ANNOTATION.get(getEntity().getClass()))
+				.map(fieldsByAnnotation -> fieldsByAnnotation.get(annotationClass))
+				.orElseGet(Collections::emptyList);
+
+		if (CollectionUtils.isEmpty(fields)) {
+			fields = FieldUtils.getFieldsListWithAnnotation(getEntity().getClass(), annotationClass);
+
+			updateFields(annotationClass, fields);
+		}
+		return fields;
+	}
+
+	private void updateFields(Class<? extends Annotation> annotationClass, List<Field> fields) {
+		var annotationMap = Optional.ofNullable(ANNOTATED_FIELDS_BY_ANNOTATION.get(getEntity().getClass())).orElseGet(HashMap::new);
+		annotationMap.put(annotationClass, fields);
+
+		ANNOTATED_FIELDS_BY_ANNOTATION.put(annotationClass, annotationMap);
+	}
+
+	private String sanitizeName(String fieldName) {
+		if (fieldName.endsWith("Id")) {
+			return fieldName.substring(0, fieldName.indexOf("Id"));
+		}
+		return fieldName;
+	}
+
+	private Optional<Object> getEntityFieldValue(Field field) {
+		try {
+			field.setAccessible(true);
+			Optional<Object> value = Optional.ofNullable(field.get(getEntity()));
+			field.setAccessible(false);
+			return value;
+		} catch (IllegalArgumentException | IllegalAccessException e) {
+			LOG.warn("Cannot access field value of LinkedResource field.", e);
+		}
+		return Optional.empty();
+	}
+
+	private T getEntity() {
+		return Optional.ofNullable(entity == null ? model.getContent() : entity)
+				.orElseThrow(() -> new IllegalStateException("Entity must not null for ModelBuilding"));
+	}
+
+	@RequiredArgsConstructor
+	public class ConditionalLinkAdder {
+
+		public final boolean conditionFulfilled;
+
+		public ModelBuilder<T> addLink(Supplier<Link> linkSupplier) {
+			if (conditionFulfilled) {
+				addLink(linkSupplier.get());
+			}
+			return ModelBuilder.this;
+		}
+
+		public ModelBuilder<T> addLinkIfPresent(Supplier<Optional<Link>> linkSupplier) {
+			if (conditionFulfilled) {
+				addLink(linkSupplier.get());
+			}
+			return ModelBuilder.this;
+		}
+
+		public ModelBuilder<T> addLink(Function<T, Link> linkBuilder) {
+			if (conditionFulfilled) {
+				addLink(linkBuilder.apply(getEntity()));
+			}
+			return ModelBuilder.this;
+		}
+
+		public ModelBuilder<T> addLink(Link link) {
+			if (conditionFulfilled) {
+				links.add(link);
+			}
+			return ModelBuilder.this;
+		}
+
+		public ModelBuilder<T> addLink(Optional<Link> link) {
+			if (conditionFulfilled) {
+				link.ifPresent(links::add);
+			}
+			return ModelBuilder.this;
+		}
+
+		public ModelBuilder<T> addLinks(Link... links) {
+			if (conditionFulfilled) {
+				ModelBuilder.this.links.addAll(Arrays.asList(links));
+			}
+			return ModelBuilder.this;
+		}
+
+		@SafeVarargs
+		public final ModelBuilder<T> addLinks(Supplier<Link>... linkSuppliers) {
+			if (conditionFulfilled) {
+				for (int i = 0; i < linkSuppliers.length; i++) {
+					ModelBuilder.this.links.add(linkSuppliers[i].get());
+				}
+			}
+			return ModelBuilder.this;
+		}
+
+		public final ModelBuilder<T> addLinks(Supplier<Collection<Link>> linksSupplier) {
+			if (conditionFulfilled) {
+				linksSupplier.get().forEach(ModelBuilder.this.links::add);
+			}
+
+			return ModelBuilder.this;
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/common/ObjectBuilder.java b/src/main/java/de/ozgcloud/admin/common/ObjectBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ea93551abebf8d4f17d6f57a56da9c5164555e6
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/ObjectBuilder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+
+public interface ObjectBuilder<T> {
+
+	T build(Object id);
+
+	ObjectBuilder<T> constructContextAware(BeanProperty property);
+}
diff --git a/src/main/java/de/ozgcloud/admin/common/ToStringExtractor.java b/src/main/java/de/ozgcloud/admin/common/ToStringExtractor.java
new file mode 100644
index 0000000000000000000000000000000000000000..4330fe6aa0e036b5dd128072d478c9232ed1141f
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/common/ToStringExtractor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+class ToStringExtractor implements IdExtractor<Object> {
+
+	@Override
+	public String extractId(Object object) {
+		return object.toString();
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
index 03f5a50c605abcb5c1fe0acbe17c05861042a8e3..de0bca1a4ba026f84939faa1dae4f2b2dd90f6f9 100644
--- a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
+++ b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java
@@ -44,7 +44,7 @@ abstract class GroupMapper {
 			return null;
 		}
 		if (values.size() > 1 && values.stream().distinct().count() > 1) {
-			log.warn("Group contains multiple values for {}. The first one is taken.", keycloakApiProperties.getOrganisationsEinheitIdKey());
+			LOG.warn("Group contains multiple values for {}. The first one is taken.", keycloakApiProperties.getOrganisationsEinheitIdKey());
 		}
 		return values.getFirst();
 	}
diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java
index 84e860cb2cbdee0312df576f903dd285e89e1bd9..c46364338fef285376784272d2f2275743a92f79 100644
--- a/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java
+++ b/src/main/java/de/ozgcloud/admin/migration/MongockFailedEventListener.java
@@ -34,6 +34,6 @@ public class MongockFailedEventListener implements ApplicationListener<SpringMig
 
 	@Override
 	public void onApplicationEvent(SpringMigrationFailureEvent event) {
-		log.error("Mongock migration failed", event.getMigrationResult());
+		LOG.error("Mongock migration failed", event.getMigrationResult());
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java
index ad1558351ae353658dbe653bfe2630e627373489..e66855af555eb96ad054bf3ae9601d0c432a9fbb 100644
--- a/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java
+++ b/src/main/java/de/ozgcloud/admin/migration/MongockStartEventListener.java
@@ -34,6 +34,6 @@ public class MongockStartEventListener implements ApplicationListener<SpringMigr
 
 	@Override
 	public void onApplicationEvent(SpringMigrationStartedEvent event) {
-		log.info("Mongock start migration...");
+		LOG.info("Mongock start migration...");
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java b/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java
index 95a7f76ee988dc8f1e72b8db6341da77514e5b54..176bc14fdfbbac69e00b16a2e649cf8b5db1050d 100644
--- a/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java
+++ b/src/main/java/de/ozgcloud/admin/migration/MongockSuccessEventListener.java
@@ -34,6 +34,6 @@ public class MongockSuccessEventListener implements ApplicationListener<SpringMi
 
 	@Override
 	public void onApplicationEvent(SpringMigrationSuccessEvent event) {
-		log.info("Mongock migration successfull", event.getMigrationResult());
+		LOG.info("Mongock migration successfull", event.getMigrationResult());
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
index 55998463878e0a5a87a02dc84b9fec48b5c006c6..be5e37b3e0c48034d0b934455d41e4f7dd577640 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java
@@ -13,10 +13,12 @@ import lombok.extern.jackson.Jacksonized;
 @Getter
 @Builder(toBuilder = true)
 @Jacksonized
-@Document(language = "german")
+@Document(language = "german", collection = OrganisationsEinheit.COLLECTION_NAME)
 @TypeAlias("OrganisationsEinheit")
 public class OrganisationsEinheit {
 
+	static final String COLLECTION_NAME = "organisationsEinheit";
+
 	@Id
 	private String id;
 	private String name;
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitController.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitController.java
index 5197ad6c6a17efc068db1987a0a73893b2c23829..c1d8df5c9f5e370e50a3b29b6b5b746705a01fb8 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitController.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitController.java
@@ -2,6 +2,8 @@ package de.ozgcloud.admin.organisationseinheit;
 
 import org.springframework.hateoas.CollectionModel;
 import org.springframework.hateoas.EntityModel;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -10,11 +12,22 @@ import lombok.RequiredArgsConstructor;
 @RestController
 @RequestMapping(OrganisationsEinheitController.PATH)
 @RequiredArgsConstructor
-class OrganisationsEinheitController {
+public class OrganisationsEinheitController {
 
 	static final String PATH = "/api/organisationseinheits"; // NOSONAR
 
-	public CollectionModel<EntityModel<OrganisationsEinheit>> getAll(){
+	private final OrganisationsEinheitService organisationsEinheitService;
+
+	private final OrganisationsEinheitModelAssembler assembler;
+
+	@GetMapping
+	public CollectionModel<EntityModel<OrganisationsEinheit>> getAll() {
+		var organisationsEinheiten = organisationsEinheitService.getAllOrganisationsEinheiten();
+		return assembler.toCollectionModel(organisationsEinheiten);
+	}
+
+	@GetMapping("/{id}")
+	public EntityModel<OrganisationsEinheit> getById(@PathVariable String id) {
 		throw new UnsupportedOperationException("Not implemented yet");
 	}
 }
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssembler.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssembler.java
new file mode 100644
index 0000000000000000000000000000000000000000..8378d8f7dba7b06fc3e8605cccdf9301fcb7cfa0
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssembler.java
@@ -0,0 +1,32 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
+
+import java.util.stream.StreamSupport;
+
+import org.springframework.hateoas.CollectionModel;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.hateoas.server.RepresentationModelAssembler;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.admin.common.CollectionModelBuilder;
+import de.ozgcloud.admin.common.ModelBuilder;
+
+@Component
+class OrganisationsEinheitModelAssembler implements RepresentationModelAssembler<OrganisationsEinheit, EntityModel<OrganisationsEinheit>> {
+
+	@Override
+	public EntityModel<OrganisationsEinheit> toModel(OrganisationsEinheit organisationsEinheit) {
+		return ModelBuilder.fromEntity(organisationsEinheit)
+				.addLink(linkTo(methodOn(OrganisationsEinheitController.class).getById(organisationsEinheit.getId())).withSelfRel())
+				.buildModel();
+	}
+
+	@Override
+	public CollectionModel<EntityModel<OrganisationsEinheit>> toCollectionModel(Iterable<? extends OrganisationsEinheit> organisationsEinheiten) {
+		var models = StreamSupport.stream(organisationsEinheiten.spliterator(), false).map(this::toModel);
+		return CollectionModelBuilder.fromEntities(models)
+				.addLink(linkTo(methodOn(OrganisationsEinheitController.class).getAll()).withSelfRel())
+				.buildModel();
+	}
+}
diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitService.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitService.java
index e4f0dee20887cad830a95666be154a6c204a13c3..afed94e7e4691d89ec5e84faeec8bc4f22304219 100644
--- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitService.java
+++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitService.java
@@ -1,5 +1,8 @@
 package de.ozgcloud.admin.organisationseinheit;
 
+import java.util.List;
+
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;
 import org.springframework.stereotype.Service;
 
 import lombok.RequiredArgsConstructor;
@@ -8,10 +11,18 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 class OrganisationsEinheitService {
 
-	private final OrganisationsEinheitRepository organisationsEinheitRepository;
+	private final OrganisationsEinheitRepository repository;
 
 	public OrganisationsEinheit saveOrganisationsEinheit(OrganisationsEinheit organisationsEinheit) {
-		return organisationsEinheitRepository.save(organisationsEinheit);
+		return repository.save(organisationsEinheit);
+	}
+
+	public List<OrganisationsEinheit> getAllOrganisationsEinheiten() {
+		return repository.findAll();
+	}
+
+	public OrganisationsEinheit getOrganisationsEinheitById(String id) {
+		return repository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Organisationseinheit with id " + id + " not found"));
 	}
 
 }
diff --git a/src/test/java/de/ozgcloud/admin/common/CollectionModelBuilderTest.java b/src/test/java/de/ozgcloud/admin/common/CollectionModelBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc4dd74e3f2b4121bf7fc681b8ab5de5cdc42fde
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/CollectionModelBuilderTest.java
@@ -0,0 +1,92 @@
+package de.ozgcloud.admin.common;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.hateoas.Link;
+
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheit;
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheitTestFactory;
+
+class CollectionModelBuilderTest {
+
+	private final String HREF = "http://test";
+	private final String REL = "rel";
+
+	@Nested
+	class TestBuildModel {
+
+		@Test
+		void shouldBuildModel() {
+			var vorgang = OrganisationsEinheitTestFactory.create();
+
+			var model = CollectionModelBuilder.fromEntities(List.of(vorgang)).buildModel();
+
+			assertThat(model.getContent()).hasSize(1).first().usingRecursiveComparison().isEqualTo(vorgang);
+		}
+	}
+
+	@Nested
+	class TestAddLink {
+
+		@Test
+		void shouldAddLink() {
+			var model = CollectionModelBuilder.fromEntities(List.of()).addLink(Link.of(HREF, REL)).buildModel();
+
+			assertThat(model.getLinks()).hasSize(1).first().extracting(Link::getHref, link -> link.getRel().value()).containsExactly(HREF, REL);
+		}
+	}
+
+	@Nested
+	class TestIfMatch {
+
+		@Nested
+		class TestWithBooleanSupplier {
+
+			@Test
+			void shouldAddLink() {
+				var model = CollectionModelBuilder.fromEntities(List.of()).ifMatch(() -> true).addLink(Link.of(HREF, REL)).buildModel();
+
+				assertThat(model.getLinks()).hasSize(1).first().extracting(Link::getHref, link -> link.getRel().value()).containsExactly(HREF, REL);
+			}
+
+			@Test
+			void shouldNotAddLink() {
+				var model = CollectionModelBuilder.fromEntities(List.of()).ifMatch(() -> false).addLink(Link.of(HREF, REL)).buildModel();
+
+				assertThat(model.getLinks()).isEmpty();
+			}
+		}
+
+		@Nested
+		class TestWithPredicate {
+
+			private final Stream<OrganisationsEinheit> wiedervorlageStream = Stream.of(OrganisationsEinheitTestFactory.create());
+
+			@Test
+			void shouldAddLink() {
+				var model = CollectionModelBuilder.fromEntities(wiedervorlageStream)
+						.ifMatch(wiedervorlagen -> true)
+						.addLink(Link.of(HREF, REL))
+						.buildModel();
+
+				assertThat(model.getLinks()).hasSize(1).first().extracting(Link::getHref, link -> link.getRel().value()).containsExactly(HREF, REL);
+			}
+
+			@Test
+			void shouldNotAddLink() {
+				var model = CollectionModelBuilder.fromEntities(wiedervorlageStream)
+						.ifMatch(wiedervorlagen -> false)
+						.addLink(Link.of(HREF, REL))
+						.buildModel();
+
+				assertThat(model.getLinks()).isEmpty();
+			}
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/admin/common/EntityModelTestFactory.java b/src/test/java/de/ozgcloud/admin/common/EntityModelTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..99617d582151e26fa46c12e4ef40e585b18fa0eb
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/EntityModelTestFactory.java
@@ -0,0 +1,20 @@
+package de.ozgcloud.admin.common;
+
+import org.springframework.hateoas.EntityModel;
+
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheit;
+import lombok.NoArgsConstructor;
+
+public class EntityModelTestFactory {
+
+	public static final NullableEntityModel NULLABLE = createNullable();
+
+	private static NullableEntityModel createNullable() {
+		return new NullableEntityModel();
+	}
+
+	@NoArgsConstructor
+	private static class NullableEntityModel extends EntityModel<OrganisationsEinheit> {
+
+	}
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/IdBuilderTest.java b/src/test/java/de/ozgcloud/admin/common/IdBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a3d3a08d5b55434bc96d58632846d2da3936eab
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/IdBuilderTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.databind.BeanProperty;
+
+class IdBuilderTest {
+
+	@DisplayName("Test building ID when deserializing linked resources")
+	@Nested
+	class TestBuilingId {
+		private static final String ID = "id";
+
+		@Test
+		void shouldBuildId() {
+			IdBuilder idBuilder = new IdBuilder();
+
+			var idObject = idBuilder.build(ID);
+
+			assertThat(idObject).isInstanceOf(Object.class).asString().isEqualTo(ID);
+		}
+
+		@Test
+		void shouldCreateObjectBuilder() {
+			BeanProperty property = mock(BeanProperty.class);
+			ObjectBuilder<Object> idBuilder = new IdBuilder().constructContextAware(property);
+
+			assertThat(idBuilder).isNotNull();
+		}
+	}
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/KeycloakInitializer.java b/src/test/java/de/ozgcloud/admin/common/KeycloakInitializer.java
index 3cf919b51996d6d932b5fc51c0ba4079cbb9d563..7fec947e3c250ecaa53b158bfa266c05e57acf9e 100644
--- a/src/test/java/de/ozgcloud/admin/common/KeycloakInitializer.java
+++ b/src/test/java/de/ozgcloud/admin/common/KeycloakInitializer.java
@@ -26,20 +26,20 @@ public class KeycloakInitializer implements ApplicationContextInitializer<Config
 	@SuppressWarnings("resource")
 	private void initContainer() {
 		if (keycloakContainer == null) {
-			log.info("Creating Keycloak-container...");
+			LOG.info("Creating Keycloak-container...");
 			keycloakContainer = new KeycloakContainer().withRealmImportFile("keycloak/realm-export.json").withVerboseOutput();
 		}
 		if (!keycloakContainer.isRunning()) {
-			log.info("Starting Keycloak-container...");
+			LOG.info("Starting Keycloak-container...");
 			keycloakContainer.setWaitStrategy(
 					Wait.forLogMessage(".*message\":\"started.*", 1).withStartupTimeout(Duration.ofMinutes(3)));
 			keycloakContainer.start();
-			log.info("Keycloak-container started");
+			LOG.info("Keycloak-container started");
 		}
 	}
 
 	private void setProperties(ConfigurableApplicationContext applicationContext) {
-		log.info("Keycloak URL: {}", keycloakContainer.getAuthServerUrl());
+		LOG.info("Keycloak URL: {}", keycloakContainer.getAuthServerUrl());
 
 		TestPropertyValues.of(AUTH_SERVER_URL + "=" + keycloakContainer.getAuthServerUrl()).applyTo(applicationContext);
 
diff --git a/src/test/java/de/ozgcloud/admin/common/LinkedResourceDeserializerTest.java b/src/test/java/de/ozgcloud/admin/common/LinkedResourceDeserializerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..85c2cffe20da1dfc5195087a66dc8ef069080f55
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/LinkedResourceDeserializerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.exc.StreamReadException;
+import com.fasterxml.jackson.databind.DatabindException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.ozgcloud.admin.common.user.TestId;
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheitTestFactory;
+
+class LinkedResourceDeserializerTest {
+	private static final String TEST_JSON = "{\"id\":\"/api/vorgangs/" + OrganisationsEinheitTestFactory.ID + "\"}";
+
+	@DisplayName("Test the deserilization of linked resource json")
+	@Nested
+	class TestDeserialization {
+		@Test
+		void shouldDeserialize() throws IOException {
+			LinkedResourceTestObject res = new ObjectMapper().readValue(TEST_JSON.getBytes(), LinkedResourceTestObject.class);
+
+			assertThat(res).hasFieldOrPropertyWithValue("id", TestId.from(OrganisationsEinheitTestFactory.ID));
+		}
+
+	}
+
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/LinkedResourceSerializerTest.java b/src/test/java/de/ozgcloud/admin/common/LinkedResourceSerializerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..dacf8bcedacb365629ea84c8e5366ed8f540b994
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/LinkedResourceSerializerTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.ozgcloud.admin.common.user.TestId;
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheitTestFactory;
+
+class LinkedResourceSerializerTest {
+
+	@DisplayName("Test the json serialization of linked resource annotations")
+	@Nested
+	class TestSerialization {
+		@Test
+		void shouldSerialize() throws JsonProcessingException {
+			var testObj = new LinkedResourceTestObject(TestId.from(OrganisationsEinheitTestFactory.ID));
+
+			String serialized = new ObjectMapper().writeValueAsString(testObj);
+
+			assertThat(serialized).isEqualTo("{\"id\":\"/api/organisationseinheits/" + OrganisationsEinheitTestFactory.ID + "\"}");
+		}
+
+	}
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/LinkedResourceTestObject.java b/src/test/java/de/ozgcloud/admin/common/LinkedResourceTestObject.java
new file mode 100644
index 0000000000000000000000000000000000000000..f387e57475d5355f758eb1d2941d77fc51f4a74c
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/LinkedResourceTestObject.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import de.ozgcloud.admin.common.user.TestId;
+import de.ozgcloud.admin.organisationseinheit.OrganisationsEinheitController;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+class LinkedResourceTestObject {
+	@LinkedResource(controllerClass = OrganisationsEinheitController.class)
+	private TestId id;
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/ModelBuilderTest.java b/src/test/java/de/ozgcloud/admin/common/ModelBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..600e54392d19e7bf6b107ae6741f5b80488c926b
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/ModelBuilderTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.UUID;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.mockito.Mock;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import lombok.Builder;
+
+class ModelBuilderTest {
+
+	@DisplayName("Add link by annotation if missing")
+	@Nested
+	class TestAddLinkByAnnotationIfMissing {
+
+		private static final String USER_MANAGER_URL = "http://localhost";
+		private static final String USER_MANAGER_PROFILE_TEMPLATE = "/api/profile/%s";
+
+		@Mock
+		private ApplicationContext context;
+
+		private TestEntity entity = TestEntityTestFactory.create();
+
+		@Test
+		void shouldHaveAddLinkByLinkedResource() {
+			var model = ModelBuilder.fromEntity(entity).buildModel();
+
+			assertThat(model.getLink(TestController.FILE_REL).get().getHref()).isEqualTo(TestController.PATH + "/" + TestEntityTestFactory.FILE);
+		}
+
+		@ParameterizedTest
+		@NullAndEmptySource
+		void shouldNotAddLinkByLinkedRessourceIfFieldValueIsNotSet(String fileId) {
+			var model = ModelBuilder.fromEntity(TestEntityTestFactory.createBuilder().file(fileId).build()).buildModel();
+
+			assertThat(model.getLink(TestController.FILE_REL)).isEmpty();
+		}
+	}
+}
+
+@Builder
+class TestEntity {
+
+	@LinkedResource(controllerClass = TestController.class)
+	private String file;
+}
+
+@RequestMapping(TestController.PATH)
+class TestController {
+
+	static final String PATH = "/api/test";
+
+	static final String USER_REL = "user";
+	static final String FILE_REL = "file";
+
+}
+
+class TestEntityTestFactory {
+
+	static final String USER = UUID.randomUUID().toString();
+	static final String FILE = UUID.randomUUID().toString();
+
+	public static TestEntity create() {
+		return createBuilder().build();
+	}
+
+	public static TestEntity.TestEntityBuilder createBuilder() {
+		return TestEntity.builder()
+				.file(FILE);
+	}
+}
diff --git a/src/test/java/de/ozgcloud/admin/common/user/TestId.java b/src/test/java/de/ozgcloud/admin/common/user/TestId.java
new file mode 100644
index 0000000000000000000000000000000000000000..062ac78d9fed39e852260dec5f4ed938f3209346
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/common/user/TestId.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.admin.common.user;
+
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+
+import de.ozgcloud.common.datatype.StringBasedValue;
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PACKAGE)
+@EqualsAndHashCode(callSuper = true)
+public class TestId extends StringBasedValue {
+
+	private static final long serialVersionUID = 1L;
+
+	TestId(String userId) {
+		super(userId);
+	}
+
+	public static TestId from(UUID userId) {
+		return TestId.from(userId.toString());
+	}
+
+	public static TestId from(String userId) {
+		return new TestId(userId);
+	}
+
+	public static TestId empty() {
+		return new TestId(StringUtils.EMPTY);
+	}
+
+}
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d21366aa7d9b424af8033d3ab7484f1c13a5ad2
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitControllerTest.java
@@ -0,0 +1,87 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.hateoas.CollectionModel;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import lombok.SneakyThrows;
+
+class OrganisationsEinheitControllerTest {
+
+	@InjectMocks
+	private OrganisationsEinheitController controller;
+
+	@Mock
+	private OrganisationsEinheitService organisationsEinheitService;
+
+	@Mock
+	private OrganisationsEinheitModelAssembler assembler;
+
+	private MockMvc mockMvc;
+
+	@BeforeEach
+	void setUp() {
+		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+	}
+
+	@Nested
+	class TestGetAll {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+		private final List<OrganisationsEinheit> organisationsEinheiten = List.of(organisationsEinheit);
+		private final CollectionModel<EntityModel<OrganisationsEinheit>> collectionModel = CollectionModel.of(
+				List.of(EntityModel.of(organisationsEinheit)));
+
+		@BeforeEach
+		void setUp() {
+			when(organisationsEinheitService.getAllOrganisationsEinheiten()).thenReturn(organisationsEinheiten);
+			when(assembler.toCollectionModel(organisationsEinheiten)).thenReturn(collectionModel);
+		}
+
+		@Test
+		void shouldCallService() {
+			doRequest();
+
+			verify(organisationsEinheitService).getAllOrganisationsEinheiten();
+		}
+
+		@Test
+		void shouldCallAssembler() {
+			doRequest();
+
+			verify(assembler).toCollectionModel(organisationsEinheiten);
+		}
+
+		@Test
+		void shouldReturnCollectionModel() {
+			var response = controller.getAll();
+
+			assertThat(response).isEqualTo(collectionModel);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldReturnHttpOk() {
+			doRequest().andExpect(status().isOk());
+		}
+
+		@SneakyThrows
+		private ResultActions doRequest() {
+			return mockMvc.perform(get(OrganisationsEinheitController.PATH));
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d69013443509cd1ae2328fed6842d98eae379141
--- /dev/null
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitModelAssemblerTest.java
@@ -0,0 +1,84 @@
+package de.ozgcloud.admin.organisationseinheit;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.hateoas.IanaLinkRelations;
+import org.springframework.hateoas.Link;
+import org.springframework.web.util.UriTemplate;
+
+class OrganisationsEinheitModelAssemblerTest {
+
+	@Spy
+	@InjectMocks
+	private OrganisationsEinheitModelAssembler assembler;
+
+	@Nested
+	class TestToModel {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+
+		@Test
+		void shouldAddSelfLink() {
+			var model = assembler.toModel(organisationsEinheit);
+
+			assertThat(model.getLink(IanaLinkRelations.SELF))
+					.isNotEmpty()
+					.get()
+					.extracting(Link::getHref)
+					.isEqualTo(new UriTemplate(OrganisationsEinheitController.PATH + "/{id}").expand(OrganisationsEinheitTestFactory.ID).toString());
+		}
+
+		@Test
+		void shouldReturnModel() {
+			var model = assembler.toModel(organisationsEinheit);
+
+			assertThat(model.getContent()).isEqualTo(organisationsEinheit);
+		}
+	}
+
+	@Nested
+	class TestToCollectionModel {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+
+		@BeforeEach
+		void setUp() {
+			doReturn(EntityModel.of(organisationsEinheit)).when(assembler).toModel(organisationsEinheit);
+		}
+
+		@Test
+		void shouldAddSelfLink() {
+			var collectionModel = assembler.toCollectionModel(List.of(organisationsEinheit));
+
+			assertThat(collectionModel.getLink(IanaLinkRelations.SELF))
+					.isNotEmpty()
+					.get()
+					.extracting(Link::getHref)
+					.isEqualTo(OrganisationsEinheitController.PATH);
+		}
+
+		@Test
+		void shouldBuildModels() {
+			assembler.toCollectionModel(List.of(organisationsEinheit));
+
+			verify(assembler).toModel(organisationsEinheit);
+		}
+
+		@Test
+		void shouldHaveModels() {
+			var collectionModel = assembler.toCollectionModel(List.of(organisationsEinheit));
+
+			assertThat(collectionModel.getContent()).extracting(EntityModel::getContent).containsExactly(organisationsEinheit);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
index 345b190daa67a011ac5ee4d417d88fada7374138..a545a28ac74d8fc8cc41b78d50542f3e691e16af 100644
--- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
+++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitServiceTest.java
@@ -3,11 +3,15 @@ package de.ozgcloud.admin.organisationseinheit;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
+import java.util.Optional;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;
 
 class OrganisationsEinheitServiceTest {
 
@@ -15,7 +19,7 @@ class OrganisationsEinheitServiceTest {
 	private OrganisationsEinheitService service;
 
 	@Mock
-	private OrganisationsEinheitRepository organisationsEinheitRepository;
+	private OrganisationsEinheitRepository repository;
 
 	@Nested
 	class TestSaveOrganisationsEinheit {
@@ -24,14 +28,14 @@ class OrganisationsEinheitServiceTest {
 
 		@BeforeEach
 		void setUp() {
-			when(organisationsEinheitRepository.save(organisationsEinheit)).thenReturn(organisationsEinheit);
+			when(repository.save(organisationsEinheit)).thenReturn(organisationsEinheit);
 		}
 
 		@Test
 		void shouldCallRepository() {
 			service.saveOrganisationsEinheit(organisationsEinheit);
 
-			verify(organisationsEinheitRepository).save(organisationsEinheit);
+			verify(repository).save(organisationsEinheit);
 		}
 
 		@Test
@@ -42,4 +46,63 @@ class OrganisationsEinheitServiceTest {
 		}
 	}
 
+	@Nested
+	class TestGetAllOrganisationsEinheiten {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+		private final List<OrganisationsEinheit> organisationsEinheiten = List.of(organisationsEinheit);
+
+		@BeforeEach
+		void setUp() {
+			when(repository.findAll()).thenReturn(organisationsEinheiten);
+		}
+
+		@Test
+		void shouldCallRepository() {
+			service.getAllOrganisationsEinheiten();
+
+			verify(repository).findAll();
+		}
+
+		@Test
+		void shouldReturnAll() {
+			var gotOrganisationsEinheiten = service.getAllOrganisationsEinheiten();
+
+			assertThat(gotOrganisationsEinheiten).containsExactly(organisationsEinheit);
+		}
+	}
+
+	@Nested
+	class TestGetOrganisationsEinheitById {
+
+		private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create();
+
+		@Test
+		void shouldCallRepository() {
+			when(repository.findById(OrganisationsEinheitTestFactory.ID)).thenReturn(Optional.of(organisationsEinheit));
+
+			service.getOrganisationsEinheitById(OrganisationsEinheitTestFactory.ID);
+
+			verify(repository).findById(OrganisationsEinheitTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnOrganisationsEinheit() {
+			when(repository.findById(OrganisationsEinheitTestFactory.ID)).thenReturn(Optional.of(organisationsEinheit));
+
+			var gotOrganisationsEinheit = service.getOrganisationsEinheitById(OrganisationsEinheitTestFactory.ID);
+
+			assertThat(gotOrganisationsEinheit).isEqualTo(organisationsEinheit);
+		}
+
+		@Test
+		void shouldThrowResourceNotFoundException() {
+			when(repository.findById("not_exists")).thenReturn(Optional.empty());
+
+			assertThatThrownBy(() -> service.getOrganisationsEinheitById("not_exists"))
+					.isInstanceOf(ResourceNotFoundException.class)
+					.hasMessage("Organisationseinheit with id not_exists not found");
+		}
+	}
+
 }
\ No newline at end of file