diff --git a/src/main/java/org/caosdb/server/entity/Message.java b/src/main/java/org/caosdb/server/entity/Message.java
index 63cf8210becc916447ac9e64cebcf094e179f865..e8c1a63080eca37451eebf8b1a39e5457b8c3732 100644
--- a/src/main/java/org/caosdb/server/entity/Message.java
+++ b/src/main/java/org/caosdb/server/entity/Message.java
@@ -67,7 +67,7 @@ public class Message extends Exception implements Comparable<Message>, ToElement
   public String toString() {
     return this.type.toString()
         + " ("
-        + (this.code != null ? this.code.toString() : "")
+        + (this.code != null ? this.code.toString() : "0")
         + ") - "
         + (this.description != null ? this.description : "");
   }
diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa6a260dfb52b5e36520d130219632d26095b0d1
--- /dev/null
+++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
@@ -0,0 +1,441 @@
+package org.caosdb.server.grpc;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.api.entity.v1.AtomicDataType;
+import org.caosdb.api.entity.v1.CollectionValues;
+import org.caosdb.api.entity.v1.DataType;
+import org.caosdb.api.entity.v1.Entity;
+import org.caosdb.api.entity.v1.Entity.Builder;
+import org.caosdb.api.entity.v1.EntityResponse;
+import org.caosdb.api.entity.v1.EntityRole;
+import org.caosdb.api.entity.v1.Importance;
+import org.caosdb.api.entity.v1.ListDataType;
+import org.caosdb.api.entity.v1.MessageCode;
+import org.caosdb.api.entity.v1.Parent;
+import org.caosdb.api.entity.v1.ReferenceDataType;
+import org.caosdb.api.entity.v1.ScalarValue;
+import org.caosdb.api.entity.v1.SpecialValue;
+import org.caosdb.api.entity.v1.Version;
+import org.caosdb.datetime.DateTimeInterface;
+import org.caosdb.server.datatype.AbstractCollectionDatatype;
+import org.caosdb.server.datatype.AbstractDatatype;
+import org.caosdb.server.datatype.BooleanDatatype;
+import org.caosdb.server.datatype.BooleanValue;
+import org.caosdb.server.datatype.CollectionValue;
+import org.caosdb.server.datatype.DateTimeDatatype;
+import org.caosdb.server.datatype.DoubleDatatype;
+import org.caosdb.server.datatype.FileDatatype;
+import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.IndexedSingleValue;
+import org.caosdb.server.datatype.IntegerDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype2;
+import org.caosdb.server.datatype.ReferenceValue;
+import org.caosdb.server.datatype.TextDatatype;
+import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.MagicTypes;
+import org.caosdb.server.entity.Message;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.container.ParentContainer;
+import org.caosdb.server.entity.container.PropertyContainer;
+import org.caosdb.server.entity.wrapper.Property;
+
+public class CaosDBToGrpcConverters {
+
+  /** Get the unit as string. */
+  public String getStringUnit(final EntityInterface entity) {
+    final Iterator<Property> iterator = entity.getProperties().iterator();
+    while (iterator.hasNext()) {
+      final Property p = iterator.next();
+      if (MagicTypes.UNIT.getId() == p.getId()) {
+        iterator.remove();
+        return p.getValue().toString();
+      }
+    }
+    return null;
+  }
+
+  public EntityResponse.Builder convert(final EntityInterface from) {
+
+    final Builder entityBuilder = Entity.newBuilder();
+
+    if (from.hasId()) {
+      entityBuilder.setId(Integer.toString(from.getId()));
+    }
+    if (from.getRole() != null) {
+      entityBuilder.setRole(convert(from.getRole()));
+    }
+    if (from.hasName()) {
+      entityBuilder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      entityBuilder.setDescription(from.getDescription());
+    }
+    if (from.hasDatatype()) {
+      entityBuilder.setDataType(convert(from.getDatatype()));
+    }
+    if (from.hasValue()) {
+      try {
+        from.parseValue();
+      } catch (final Message e) {
+        // ignore. This problem should be handled elsewhere because this is
+        // only for the serialization of the data and not for the validation.
+        // In any case, the string representation can be used.
+      }
+      entityBuilder.setValue(convert(from.getValue()));
+    }
+    final String unit = getStringUnit(from);
+    if (unit != null) {
+      entityBuilder.setUnit(unit);
+    }
+    if (from.hasProperties()) {
+      entityBuilder.addAllProperties(convert(from.getProperties()));
+    }
+    if (from.hasParents()) {
+      entityBuilder.addAllParents(convert(from.getParents()));
+    }
+
+    final EntityResponse.Builder responseBuilder = EntityResponse.newBuilder();
+    responseBuilder.setEntity(entityBuilder);
+
+    appendMessages(from, responseBuilder);
+
+    return responseBuilder;
+  }
+
+  private EntityRole convert(final Role role) {
+    switch (role) {
+      case RecordType:
+        return EntityRole.ENTITY_ROLE_RECORD_TYPE;
+      case Record:
+        return EntityRole.ENTITY_ROLE_RECORD;
+      case Property:
+        return EntityRole.ENTITY_ROLE_PROPERTY;
+      case File:
+        return EntityRole.ENTITY_ROLE_FILE;
+      default:
+        return EntityRole.ENTITY_ROLE_UNSPECIFIED;
+    }
+  }
+
+  public Iterable<? extends org.caosdb.api.entity.v1.Message> convert(
+      final List<Message> messages) {
+    final List<org.caosdb.api.entity.v1.Message> result = new LinkedList<>();
+    for (final Message m : messages) {
+      result.add(convert(m));
+    }
+    return result;
+  }
+
+  public org.caosdb.api.entity.v1.Message convert(final Message m) {
+    final org.caosdb.api.entity.v1.Message.Builder builder =
+        org.caosdb.api.entity.v1.Message.newBuilder();
+    final MessageCode code = getMessageCode(m);
+    builder.setCode(code.getNumber());
+    builder.setDescription(m.getDescription());
+    return builder.build();
+  }
+
+  public static MessageCode getMessageCode(final Message m) {
+    return m.getCode();
+  }
+
+  public Version convert(final org.caosdb.server.entity.Version from) {
+    final org.caosdb.api.entity.v1.Version.Builder builder = Version.newBuilder();
+
+    builder.setId(from.getId());
+    return builder.build();
+  }
+
+  public Parent convert(final org.caosdb.server.entity.wrapper.Parent from) {
+    final org.caosdb.api.entity.v1.Parent.Builder builder = Parent.newBuilder();
+    if (from.hasId()) {
+      builder.setId(from.getId().toString());
+    }
+    if (from.hasName()) {
+      builder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      builder.setDescription(from.getDescription());
+    }
+
+    return builder.build();
+  }
+
+  public org.caosdb.api.entity.v1.Property convert(final Property from) {
+    final org.caosdb.api.entity.v1.Property.Builder builder =
+        org.caosdb.api.entity.v1.Property.newBuilder();
+
+    if (from.hasId()) {
+      builder.setId(from.getId().toString());
+    }
+    if (from.hasName()) {
+      builder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      builder.setDescription(from.getDescription());
+    }
+    if (from.hasDatatype()) {
+      builder.setDataType(convert(from.getDatatype()));
+    }
+    final String unit = getStringUnit(from);
+    if (unit != null) {
+      builder.setUnit(unit);
+    }
+    if (from.hasValue()) {
+      try {
+        from.parseValue();
+      } catch (final Message e) {
+        // ignore. This problem should be handled elsewhere because this is
+        // only for the serialization of the data and not for the validation.
+        // In any case, the string representation can be used.
+      }
+      builder.setValue(convert(from.getValue()));
+    }
+    builder.setImportance(convert(from.getStatementStatus()));
+    return builder.build();
+  }
+
+  private org.caosdb.api.entity.v1.Value.Builder convert(final Value value) {
+    if (value instanceof CollectionValue) {
+      return convertCollectionValue((CollectionValue) value);
+    }
+    final org.caosdb.api.entity.v1.Value.Builder builder =
+        org.caosdb.api.entity.v1.Value.newBuilder();
+    builder.setScalarValue(convertScalarValue(value));
+    return builder;
+  }
+
+  private ScalarValue.Builder convertScalarValue(final Value value) {
+
+    if (value instanceof BooleanValue) {
+      return convertBooleanValue((BooleanValue) value);
+
+    } else if (value instanceof ReferenceValue) {
+      return convertReferenceValue((ReferenceValue) value);
+
+    } else if (value instanceof DateTimeInterface) {
+      return convertDateTimeInterface((DateTimeInterface) value);
+
+    } else if (value instanceof GenericValue) {
+      return convertGenericValue((GenericValue) value);
+    }
+    return null;
+  }
+
+  private ScalarValue.Builder convertGenericValue(final GenericValue value) {
+    final Object wrappedValue = value.getValue();
+    if (wrappedValue instanceof Double) {
+      return ScalarValue.newBuilder().setDoubleValue((Double) wrappedValue);
+    } else if (wrappedValue instanceof Integer) {
+      return ScalarValue.newBuilder().setIntegerValue((Integer) wrappedValue);
+    } else {
+      return convertStringValue(value);
+    }
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertStringValue(final Value value) {
+    if (value.toString().isEmpty()) {
+      return ScalarValue.newBuilder().setSpecialValue(SpecialValue.SPECIAL_VALUE_EMPTY_STRING);
+    }
+    return ScalarValue.newBuilder().setStringValue(value.toString());
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertDateTimeInterface(
+      final DateTimeInterface value) {
+    return convertStringValue(value);
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertBooleanValue(
+      final BooleanValue value) {
+    return ScalarValue.newBuilder().setBooleanValue(value.getValue());
+  }
+
+  private ScalarValue.Builder convertReferenceValue(final ReferenceValue value) {
+    return convertStringValue(value);
+  }
+
+  private org.caosdb.api.entity.v1.Value.Builder convertCollectionValue(
+      final CollectionValue value) {
+
+    final org.caosdb.api.entity.v1.Value.Builder builder =
+        org.caosdb.api.entity.v1.Value.newBuilder();
+    final List<ScalarValue> values = new LinkedList<>();
+    value.forEach(
+        (v) -> {
+          values.add(convertScalarValue(v));
+        });
+    builder.setListValues(CollectionValues.newBuilder().addAllValues(values));
+    return builder;
+  }
+
+  private ScalarValue convertScalarValue(final IndexedSingleValue v) {
+    return convertScalarValue(v.getWrapped()).build();
+  }
+
+  private Importance convert(final StatementStatus statementStatus) {
+    switch (statementStatus) {
+      case FIX:
+        return Importance.IMPORTANCE_FIX;
+      case OBLIGATORY:
+        return Importance.IMPORTANCE_OBLIGATORY;
+      case RECOMMENDED:
+        return Importance.IMPORTANCE_RECOMMENDED;
+      case SUGGESTED:
+        return Importance.IMPORTANCE_SUGGESTED;
+      default:
+        return null;
+    }
+  }
+
+  private org.caosdb.api.entity.v1.DataType.Builder convert(final AbstractDatatype datatype) {
+    if (datatype instanceof ReferenceDatatype2) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype2) datatype));
+    } else if (datatype instanceof FileDatatype) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((FileDatatype) datatype));
+    } else if (datatype instanceof ReferenceDatatype) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
+    } else if (datatype instanceof AbstractCollectionDatatype) {
+      return DataType.newBuilder()
+          .setListDataType(
+              convertAbstractCollectionDatatype((AbstractCollectionDatatype) datatype));
+    } else if (datatype instanceof BooleanDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
+
+    } else if (datatype instanceof DateTimeDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
+
+    } else if (datatype instanceof DoubleDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
+
+    } else if (datatype instanceof IntegerDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
+
+    } else if (datatype instanceof TextDatatype) {
+      return DataType.newBuilder().setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
+    }
+    return null;
+  }
+
+  private AtomicDataType convertTextDatatype(final TextDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_TEXT;
+  }
+
+  private AtomicDataType convertIntegerDatatype(final IntegerDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_INTEGER;
+  }
+
+  private AtomicDataType convertDoubleDatatype(final DoubleDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_DOUBLE;
+  }
+
+  private AtomicDataType convertDateTimeDatatype(final DateTimeDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_DATETIME;
+  }
+
+  private AtomicDataType convertBooleanDatatype(final BooleanDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_BOOLEAN;
+  }
+
+  private org.caosdb.api.entity.v1.ListDataType.Builder convertAbstractCollectionDatatype(
+      final AbstractCollectionDatatype collectionDatatype) {
+
+    final org.caosdb.api.entity.v1.ListDataType.Builder listBuilder = ListDataType.newBuilder();
+    final AbstractDatatype datatype = collectionDatatype.getDatatype();
+    if (datatype instanceof ReferenceDatatype) {
+      listBuilder.setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
+    } else if (datatype instanceof BooleanDatatype) {
+      return listBuilder.setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
+
+    } else if (datatype instanceof DateTimeDatatype) {
+      return listBuilder.setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
+
+    } else if (datatype instanceof DoubleDatatype) {
+      return listBuilder.setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
+
+    } else if (datatype instanceof IntegerDatatype) {
+      return listBuilder.setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
+
+    } else if (datatype instanceof TextDatatype) {
+      return listBuilder.setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
+    }
+    return listBuilder;
+  }
+
+  private org.caosdb.api.entity.v1.ReferenceDataType.Builder convertReferenceDatatype(
+      final ReferenceDatatype datatype) {
+    return ReferenceDataType.newBuilder().setName(datatype.getName());
+  }
+
+  public Iterable<? extends org.caosdb.api.entity.v1.Property> convert(
+      final PropertyContainer from) {
+    final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = from.iterator();
+    return () ->
+        new Iterator<>() {
+
+          @Override
+          public boolean hasNext() {
+            return iterator.hasNext();
+          }
+
+          @Override
+          public org.caosdb.api.entity.v1.Property next() {
+            return convert(iterator.next());
+          }
+        };
+  }
+
+  public Iterable<? extends Parent> convert(final ParentContainer from) {
+    final Iterator<org.caosdb.server.entity.wrapper.Parent> iterator = from.iterator();
+    return () ->
+        new Iterator<>() {
+
+          @Override
+          public boolean hasNext() {
+            return iterator.hasNext();
+          }
+
+          @Override
+          public Parent next() {
+            return convert(iterator.next());
+          }
+        };
+  }
+
+  public void appendMessages(
+      final EntityInterface from, final org.caosdb.api.entity.v1.EntityResponse.Builder builder) {
+    if (from.hasMessage(Message.MessageType.Error.toString())) {
+      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Warning.toString())) {
+      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Info.toString())) {
+      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
+    }
+  }
+
+  public void appendMessages(
+      final EntityInterface from, final org.caosdb.api.entity.v1.IdResponse.Builder builder) {
+    if (from.hasMessage(Message.MessageType.Error.toString())) {
+      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Warning.toString())) {
+      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Info.toString())) {
+      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
+    }
+  }
+}
diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
index eeba659aa5ab0bd2b7271a8bd1fa9987268197fc..4608bd49034d4957a4a19dcf6e03913d99201274 100644
--- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
@@ -1,460 +1,48 @@
 package org.caosdb.server.grpc;
 
 import io.grpc.stub.StreamObserver;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.UUID;
 import org.apache.shiro.SecurityUtils;
-import org.caosdb.api.entity.v1.AtomicDataType;
-import org.caosdb.api.entity.v1.CollectionValues;
-import org.caosdb.api.entity.v1.DataType;
 import org.caosdb.api.entity.v1.DeleteRequest;
 import org.caosdb.api.entity.v1.DeleteResponse;
 import org.caosdb.api.entity.v1.Entity;
-import org.caosdb.api.entity.v1.Entity.Builder;
 import org.caosdb.api.entity.v1.EntityRequest;
 import org.caosdb.api.entity.v1.EntityResponse;
-import org.caosdb.api.entity.v1.EntityRole;
 import org.caosdb.api.entity.v1.EntityTransactionServiceGrpc.EntityTransactionServiceImplBase;
-import org.caosdb.api.entity.v1.FileDescriptor;
 import org.caosdb.api.entity.v1.IdResponse;
-import org.caosdb.api.entity.v1.Importance;
 import org.caosdb.api.entity.v1.InsertRequest;
 import org.caosdb.api.entity.v1.InsertResponse;
-import org.caosdb.api.entity.v1.ListDataType;
-import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.api.entity.v1.MultiTransactionRequest;
 import org.caosdb.api.entity.v1.MultiTransactionResponse;
-import org.caosdb.api.entity.v1.Parent;
-import org.caosdb.api.entity.v1.ReferenceDataType;
 import org.caosdb.api.entity.v1.RetrieveResponse;
-import org.caosdb.api.entity.v1.ScalarValue;
-import org.caosdb.api.entity.v1.SpecialValue;
 import org.caosdb.api.entity.v1.TransactionRequest;
 import org.caosdb.api.entity.v1.TransactionRequest.WrappedRequestsCase;
 import org.caosdb.api.entity.v1.TransactionResponse;
 import org.caosdb.api.entity.v1.UpdateRequest;
 import org.caosdb.api.entity.v1.UpdateResponse;
-import org.caosdb.api.entity.v1.Version;
-import org.caosdb.datetime.DateTimeInterface;
 import org.caosdb.server.CaosDBException;
-import org.caosdb.server.datatype.AbstractCollectionDatatype;
-import org.caosdb.server.datatype.AbstractDatatype;
-import org.caosdb.server.datatype.BooleanDatatype;
-import org.caosdb.server.datatype.BooleanValue;
-import org.caosdb.server.datatype.CollectionValue;
-import org.caosdb.server.datatype.DateTimeDatatype;
-import org.caosdb.server.datatype.DoubleDatatype;
-import org.caosdb.server.datatype.FileDatatype;
-import org.caosdb.server.datatype.GenericValue;
-import org.caosdb.server.datatype.IndexedSingleValue;
-import org.caosdb.server.datatype.IntegerDatatype;
-import org.caosdb.server.datatype.ListDatatype;
-import org.caosdb.server.datatype.ReferenceDatatype;
-import org.caosdb.server.datatype.ReferenceDatatype2;
-import org.caosdb.server.datatype.ReferenceValue;
-import org.caosdb.server.datatype.TextDatatype;
-import org.caosdb.server.datatype.Value;
 import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
-import org.caosdb.server.entity.MagicTypes;
-import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.RetrieveEntity;
-import org.caosdb.server.entity.Role;
-import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.UpdateEntity;
-import org.caosdb.server.entity.container.ParentContainer;
-import org.caosdb.server.entity.container.PropertyContainer;
 import org.caosdb.server.entity.container.RetrieveContainer;
 import org.caosdb.server.entity.container.WritableContainer;
-import org.caosdb.server.entity.wrapper.Property;
 import org.caosdb.server.transaction.Retrieve;
 import org.caosdb.server.transaction.WriteTransaction;
-import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
 public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBase {
 
-  public EntityTransactionServiceImpl(final FileTransmissionServiceImpl fileTransmissionService) {
-    this.fileTransmissionService = fileTransmissionService;
-  }
-
+  /// MOVE END
+  private final CaosDBToGrpcConverters caosdbToGrpc = new CaosDBToGrpcConverters();
+  private final GrpcToCaosDBConverters grpcToCaosdb = new GrpcToCaosDBConverters();
   private final FileTransmissionServiceImpl fileTransmissionService;
 
-  /** Get the unit as string. */
-  public String getStringUnit(final EntityInterface entity) {
-    final Iterator<Property> iterator = entity.getProperties().iterator();
-    while (iterator.hasNext()) {
-      final Property p = iterator.next();
-      if (MagicTypes.UNIT.getId() == p.getId()) {
-        iterator.remove();
-        return p.getValue().toString();
-      }
-    }
-    return null;
-  }
-
-  public EntityResponse.Builder convert(final EntityInterface from) {
-
-    final Builder entityBuilder = Entity.newBuilder();
-
-    if (from.hasId()) {
-      entityBuilder.setId(Integer.toString(from.getId()));
-    }
-    if (from.getRole() != null) {
-      entityBuilder.setRole(convert(from.getRole()));
-    }
-    if (from.hasName()) {
-      entityBuilder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      entityBuilder.setDescription(from.getDescription());
-    }
-    if (from.hasDatatype()) {
-      entityBuilder.setDataType(convert(from.getDatatype()));
-    }
-    if (from.hasValue()) {
-      try {
-        from.parseValue();
-      } catch (final Message e) {
-        // ignore. This problem should be handled elsewhere because this is
-        // only for the serialization of the data and not for the validation.
-        // In any case, the string representation can be used.
-      }
-      entityBuilder.setValue(convert(from.getValue()));
-    }
-    final String unit = getStringUnit(from);
-    if (unit != null) {
-      entityBuilder.setUnit(unit);
-    }
-    if (from.hasProperties()) {
-      entityBuilder.addAllProperties(convert(from.getProperties()));
-    }
-    if (from.hasParents()) {
-      entityBuilder.addAllParents(convert(from.getParents()));
-    }
-
-    final EntityResponse.Builder responseBuilder = EntityResponse.newBuilder();
-    responseBuilder.setEntity(entityBuilder);
-
-    appendMessages(from, responseBuilder);
-
-    return responseBuilder;
-  }
-
-  private EntityRole convert(final Role role) {
-    switch (role) {
-      case RecordType:
-        return EntityRole.ENTITY_ROLE_RECORD_TYPE;
-      case Record:
-        return EntityRole.ENTITY_ROLE_RECORD;
-      case Property:
-        return EntityRole.ENTITY_ROLE_PROPERTY;
-      case File:
-        return EntityRole.ENTITY_ROLE_FILE;
-      default:
-        return EntityRole.ENTITY_ROLE_UNSPECIFIED;
-    }
-  }
-
-  public static Iterable<? extends org.caosdb.api.entity.v1.Message> convert(
-      final List<Message> messages) {
-    final List<org.caosdb.api.entity.v1.Message> result = new LinkedList<>();
-    for (final Message m : messages) {
-      result.add(convert(m));
-    }
-    return result;
-  }
-
-  public static org.caosdb.api.entity.v1.Message convert(final Message m) {
-    final org.caosdb.api.entity.v1.Message.Builder builder =
-        org.caosdb.api.entity.v1.Message.newBuilder();
-    final MessageCode code = getMessageCode(m);
-    builder.setCode(code.getNumber());
-    builder.setDescription(m.getDescription());
-    return builder.build();
-  }
-
-  public static MessageCode getMessageCode(final Message m) {
-    return m.getCode();
-  }
-
-  public Version convert(final org.caosdb.server.entity.Version from) {
-    final org.caosdb.api.entity.v1.Version.Builder builder = Version.newBuilder();
-
-    builder.setId(from.getId());
-    return builder.build();
-  }
-
-  public Parent convert(final org.caosdb.server.entity.wrapper.Parent from) {
-    final org.caosdb.api.entity.v1.Parent.Builder builder = Parent.newBuilder();
-    if (from.hasId()) {
-      builder.setId(from.getId().toString());
-    }
-    if (from.hasName()) {
-      builder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      builder.setDescription(from.getDescription());
-    }
-
-    return builder.build();
-  }
-
-  public org.caosdb.api.entity.v1.Property convert(final Property from) {
-    final org.caosdb.api.entity.v1.Property.Builder builder =
-        org.caosdb.api.entity.v1.Property.newBuilder();
-
-    if (from.hasId()) {
-      builder.setId(from.getId().toString());
-    }
-    if (from.hasName()) {
-      builder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      builder.setDescription(from.getDescription());
-    }
-    if (from.hasDatatype()) {
-      builder.setDataType(convert(from.getDatatype()));
-    }
-    final String unit = getStringUnit(from);
-    if (unit != null) {
-      builder.setUnit(unit);
-    }
-    if (from.hasValue()) {
-      try {
-        from.parseValue();
-      } catch (final Message e) {
-        // ignore. This problem should be handled elsewhere because this is
-        // only for the serialization of the data and not for the validation.
-        // In any case, the string representation can be used.
-      }
-      builder.setValue(convert(from.getValue()));
-    }
-    builder.setImportance(convert(from.getStatementStatus()));
-    return builder.build();
-  }
-
-  private org.caosdb.api.entity.v1.Value.Builder convert(final Value value) {
-    if (value instanceof CollectionValue) {
-      return convertCollectionValue((CollectionValue) value);
-    }
-    final org.caosdb.api.entity.v1.Value.Builder builder =
-        org.caosdb.api.entity.v1.Value.newBuilder();
-    builder.setScalarValue(convertScalarValue(value));
-    return builder;
-  }
-
-  private ScalarValue.Builder convertScalarValue(final Value value) {
-
-    if (value instanceof BooleanValue) {
-      return convertBooleanValue((BooleanValue) value);
-
-    } else if (value instanceof ReferenceValue) {
-      return convertReferenceValue((ReferenceValue) value);
-
-    } else if (value instanceof DateTimeInterface) {
-      return convertDateTimeInterface((DateTimeInterface) value);
-
-    } else if (value instanceof GenericValue) {
-      return convertGenericValue((GenericValue) value);
-    }
-    return null;
-  }
-
-  private ScalarValue.Builder convertGenericValue(final GenericValue value) {
-    final Object wrappedValue = value.getValue();
-    if (wrappedValue instanceof Double) {
-      return ScalarValue.newBuilder().setDoubleValue((Double) wrappedValue);
-    } else if (wrappedValue instanceof Integer) {
-      return ScalarValue.newBuilder().setIntegerValue((Integer) wrappedValue);
-    } else {
-      return convertStringValue(value);
-    }
-  }
-
-  private org.caosdb.api.entity.v1.ScalarValue.Builder convertStringValue(final Value value) {
-    if (value.toString().isEmpty()) {
-      return ScalarValue.newBuilder().setSpecialValue(SpecialValue.SPECIAL_VALUE_EMPTY_STRING);
-    }
-    return ScalarValue.newBuilder().setStringValue(value.toString());
-  }
-
-  private org.caosdb.api.entity.v1.ScalarValue.Builder convertDateTimeInterface(
-      final DateTimeInterface value) {
-    return convertStringValue(value);
-  }
-
-  private org.caosdb.api.entity.v1.ScalarValue.Builder convertBooleanValue(
-      final BooleanValue value) {
-    return ScalarValue.newBuilder().setBooleanValue(value.getValue());
-  }
-
-  private ScalarValue.Builder convertReferenceValue(final ReferenceValue value) {
-    return convertStringValue(value);
-  }
-
-  private org.caosdb.api.entity.v1.Value.Builder convertCollectionValue(
-      final CollectionValue value) {
-
-    final org.caosdb.api.entity.v1.Value.Builder builder =
-        org.caosdb.api.entity.v1.Value.newBuilder();
-    final List<ScalarValue> values = new LinkedList<>();
-    value.forEach(
-        (v) -> {
-          values.add(convertScalarValue(v));
-        });
-    builder.setListValues(CollectionValues.newBuilder().addAllValues(values));
-    return builder;
-  }
-
-  private ScalarValue convertScalarValue(final IndexedSingleValue v) {
-    return convertScalarValue(v.getWrapped()).build();
-  }
-
-  private Importance convert(final StatementStatus statementStatus) {
-    switch (statementStatus) {
-      case FIX:
-        return Importance.IMPORTANCE_FIX;
-      case OBLIGATORY:
-        return Importance.IMPORTANCE_OBLIGATORY;
-      case RECOMMENDED:
-        return Importance.IMPORTANCE_RECOMMENDED;
-      case SUGGESTED:
-        return Importance.IMPORTANCE_SUGGESTED;
-      default:
-        return null;
-    }
-  }
-
-  private org.caosdb.api.entity.v1.DataType.Builder convert(final AbstractDatatype datatype) {
-    if (datatype instanceof ReferenceDatatype2) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype2) datatype));
-    } else if (datatype instanceof FileDatatype) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((FileDatatype) datatype));
-    } else if (datatype instanceof ReferenceDatatype) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
-    } else if (datatype instanceof AbstractCollectionDatatype) {
-      return DataType.newBuilder()
-          .setListDataType(
-              convertAbstractCollectionDatatype((AbstractCollectionDatatype) datatype));
-    } else if (datatype instanceof BooleanDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
-
-    } else if (datatype instanceof DateTimeDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
-
-    } else if (datatype instanceof DoubleDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
-
-    } else if (datatype instanceof IntegerDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
-
-    } else if (datatype instanceof TextDatatype) {
-      return DataType.newBuilder().setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
-    }
-    return null;
-  }
-
-  private AtomicDataType convertTextDatatype(final TextDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_TEXT;
-  }
-
-  private AtomicDataType convertIntegerDatatype(final IntegerDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_INTEGER;
-  }
-
-  private AtomicDataType convertDoubleDatatype(final DoubleDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_DOUBLE;
-  }
-
-  private AtomicDataType convertDateTimeDatatype(final DateTimeDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_DATETIME;
-  }
-
-  private AtomicDataType convertBooleanDatatype(final BooleanDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_BOOLEAN;
-  }
-
-  private org.caosdb.api.entity.v1.ListDataType.Builder convertAbstractCollectionDatatype(
-      final AbstractCollectionDatatype collectionDatatype) {
-
-    final org.caosdb.api.entity.v1.ListDataType.Builder listBuilder = ListDataType.newBuilder();
-    final AbstractDatatype datatype = collectionDatatype.getDatatype();
-    if (datatype instanceof ReferenceDatatype) {
-      listBuilder.setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
-    } else if (datatype instanceof BooleanDatatype) {
-      return listBuilder.setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
-
-    } else if (datatype instanceof DateTimeDatatype) {
-      return listBuilder.setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
-
-    } else if (datatype instanceof DoubleDatatype) {
-      return listBuilder.setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
-
-    } else if (datatype instanceof IntegerDatatype) {
-      return listBuilder.setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
-
-    } else if (datatype instanceof TextDatatype) {
-      return listBuilder.setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
-    }
-    return listBuilder;
-  }
-
-  private org.caosdb.api.entity.v1.ReferenceDataType.Builder convertReferenceDatatype(
-      final ReferenceDatatype datatype) {
-    return ReferenceDataType.newBuilder().setName(datatype.getName());
-  }
-
-  public Iterable<? extends org.caosdb.api.entity.v1.Property> convert(
-      final PropertyContainer from) {
-    final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = from.iterator();
-    return () ->
-        new Iterator<>() {
-
-          @Override
-          public boolean hasNext() {
-            return iterator.hasNext();
-          }
-
-          @Override
-          public org.caosdb.api.entity.v1.Property next() {
-            return convert(iterator.next());
-          }
-        };
-  }
-
-  public Iterable<? extends Parent> convert(final ParentContainer from) {
-    final Iterator<org.caosdb.server.entity.wrapper.Parent> iterator = from.iterator();
-    return () ->
-        new Iterator<>() {
-
-          @Override
-          public boolean hasNext() {
-            return iterator.hasNext();
-          }
-
-          @Override
-          public Parent next() {
-            return convert(iterator.next());
-          }
-        };
-  }
-
-  public Integer getId(final String id) {
-    return Integer.parseInt(id);
+  public EntityTransactionServiceImpl(final FileTransmissionServiceImpl fileTransmissionService) {
+    this.fileTransmissionService = fileTransmissionService;
   }
 
   /**
@@ -490,7 +78,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         final String id = sub_request.getRetrieveRequest().getId();
         if (!id.isBlank()) {
           try {
-            final RetrieveEntity entity = new RetrieveEntity(getId(id));
+            final RetrieveEntity entity = new RetrieveEntity(grpcToCaosdb.getId(id));
             if (fileDownload) {
               entity.setFlag("download_files", "true");
             }
@@ -512,7 +100,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     } else {
       final boolean download_files_container = container.getFlags().containsKey("download_files");
       for (final EntityInterface entity : container) {
-        final EntityResponse.Builder entityResponse = convert(entity);
+        final EntityResponse.Builder entityResponse = caosdbToGrpc.convert(entity);
         if ((download_files_container || entity.getFlags().containsKey("download_files"))
             && entity.hasFileProperties()) {
           if (file_download == null) {
@@ -534,7 +122,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
       final String id = sub_request.getRetrieveRequest().getId();
       if (!id.isBlank()) {
         try {
-          getId(id);
+          grpcToCaosdb.getId(id);
         } catch (final NumberFormatException e) {
           // ID wasn't an integer - the server doesn't support string id's yet, so that entity
           // cannot
@@ -551,7 +139,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
   private EntityResponse entityDoesNotExist(final String id) {
     return EntityResponse.newBuilder()
-        .addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST))
+        .addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST))
         .setEntity(Entity.newBuilder().setId(id))
         .build();
   }
@@ -619,8 +207,8 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
             final InsertEntity entity =
                 new InsertEntity(
                     insertEntity.getName().isEmpty() ? null : insertEntity.getName(),
-                    convert(insertEntity.getRole()));
-            convert(insertEntity, entity);
+                    grpcToCaosdb.convert(insertEntity.getRole()));
+            grpcToCaosdb.convert(insertEntity, entity);
             addFileUpload(container, entity, insertRequest.getEntityRequest());
             container.add(entity);
           }
@@ -631,9 +219,11 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
           try {
             final UpdateEntity entity =
-                new UpdateEntity(getId(updateEntity.getId()), convert(updateEntity.getRole()));
+                new UpdateEntity(
+                    grpcToCaosdb.getId(updateEntity.getId()),
+                    grpcToCaosdb.convert(updateEntity.getRole()));
             entity.setName(updateEntity.getName().isEmpty() ? null : updateEntity.getName());
-            convert(updateEntity, entity);
+            grpcToCaosdb.convert(updateEntity, entity);
             addFileUpload(container, entity, updateRequest.getEntityRequest());
             container.add(entity);
           } catch (final NumberFormatException e) {
@@ -644,7 +234,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         case DELETE_REQUEST:
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           try {
-            final DeleteEntity entity = new DeleteEntity(getId(deleteRequest.getId()));
+            final DeleteEntity entity = new DeleteEntity(grpcToCaosdb.getId(deleteRequest.getId()));
             container.add(entity);
 
           } catch (final NumberFormatException e) {
@@ -671,7 +261,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
       if (entity.getId() != null) {
         idResponse.setId(entity.getId().toString());
       }
-      appendMessages(entity, idResponse);
+      caosdbToGrpc.appendMessages(entity, idResponse);
 
       if (entity instanceof InsertEntity) {
         builder
@@ -717,10 +307,10 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
           idResponse.setId(updateEntity.getId());
           try {
-            getId(updateEntity.getId());
+            grpcToCaosdb.getId(updateEntity.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
-            idResponse.addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
+            idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
           builder
               .addResponsesBuilder()
@@ -730,10 +320,10 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           idResponse.setId(deleteRequest.getId());
           try {
-            getId(deleteRequest.getId());
+            grpcToCaosdb.getId(deleteRequest.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
-            idResponse.addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
+            idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
           builder
               .addResponsesBuilder()
@@ -765,280 +355,6 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     }
   }
 
-  private Role convert(final EntityRole role) {
-    switch (role) {
-      case ENTITY_ROLE_FILE:
-        return Role.File;
-      case ENTITY_ROLE_PROPERTY:
-        return Role.Property;
-      case ENTITY_ROLE_RECORD:
-        return Role.Record;
-      case ENTITY_ROLE_RECORD_TYPE:
-        return Role.RecordType;
-      default:
-        return null;
-    }
-  }
-
-  private void appendMessages(
-      final EntityInterface from, final org.caosdb.api.entity.v1.EntityResponse.Builder builder) {
-    if (from.hasMessage(Message.MessageType.Error.toString())) {
-      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Warning.toString())) {
-      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Info.toString())) {
-      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
-    }
-  }
-
-  private void appendMessages(
-      final EntityInterface from, final org.caosdb.api.entity.v1.IdResponse.Builder builder) {
-    if (from.hasMessage(Message.MessageType.Error.toString())) {
-      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Warning.toString())) {
-      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Info.toString())) {
-      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
-    }
-  }
-
-  public Property getUnit(final String unitStr) {
-    final EntityInterface magicUnit = MagicTypes.UNIT.getEntity();
-    final Property unit = new Property();
-    unit.setDescription(magicUnit.getDescription());
-    unit.setName(magicUnit.getName());
-    unit.setId(magicUnit.getId());
-    unit.setDatatype(magicUnit.getDatatype());
-    unit.setStatementStatus(StatementStatus.FIX);
-    unit.setValue(new GenericValue(unitStr));
-    unit.setEntityStatus(EntityStatus.QUALIFIED);
-    return unit;
-  }
-
-  public Value getValue(final String valString) {
-    return new GenericValue(valString);
-  }
-
-  private EntityInterface convert(final Entity from, final EntityInterface entity) {
-    entity.setName(from.getName().isEmpty() ? null : from.getName());
-    entity.setDescription(from.getDescription().isBlank() ? null : from.getDescription());
-    if (!from.getUnit().isBlank()) {
-      entity.addProperty(getUnit(from.getUnit()));
-    }
-    if (from.hasDataType()) {
-      entity.setDatatype(convert(from.getDataType()));
-    }
-    if (from.hasValue()) {
-      entity.setValue(convert(from.getValue()));
-    }
-
-    if (from.getPropertiesCount() > 0) {
-      final StatementStatus defaultImportance =
-          entity.getRole() == Role.RecordType ? StatementStatus.RECOMMENDED : StatementStatus.FIX;
-      entity.getProperties().addAll(convertProperties(from.getPropertiesList(), defaultImportance));
-    }
-    if (from.getParentsCount() > 0) {
-      entity.getParents().addAll(convertParents(from.getParentsList()));
-    }
-    if (from.hasFileDescriptor()) {
-      entity.setFileProperties(convert(from.getFileDescriptor()));
-    }
-    return entity;
-  }
-
-  private Value convert(final org.caosdb.api.entity.v1.Value value) {
-    switch (value.getValueCase()) {
-      case LIST_VALUES:
-        return convertListValue(value.getListValues());
-      case SCALAR_VALUE:
-        return convertScalarValue(value.getScalarValue());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private CollectionValue convertListValue(final CollectionValues collectionValues) {
-    final CollectionValue result = new CollectionValue();
-    collectionValues
-        .getValuesList()
-        .forEach(
-            (v) -> {
-              result.add(convertScalarValue(v));
-            });
-    return result;
-  }
-
-  private Value convertScalarValue(final org.caosdb.api.entity.v1.ScalarValue value) {
-    switch (value.getScalarValueCase()) {
-      case BOOLEAN_VALUE:
-        return BooleanValue.valueOf(value.getBooleanValue());
-      case DOUBLE_VALUE:
-        return new GenericValue(value.getDoubleValue());
-      case INTEGER_VALUE:
-        return new GenericValue(Long.toString(value.getIntegerValue()));
-      case SPECIAL_VALUE:
-        return convertSpecial(value.getSpecialValue());
-      case STRING_VALUE:
-        return new GenericValue(value.getStringValue());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private Value convertSpecial(final SpecialValue specialValue) {
-    if (specialValue == SpecialValue.SPECIAL_VALUE_EMPTY_STRING) {
-      return new GenericValue("");
-    }
-    return null;
-  }
-
-  private AbstractDatatype convert(final DataType dataType) {
-    switch (dataType.getDataTypeCase()) {
-      case ATOMIC_DATA_TYPE:
-        return convertAtomicType(dataType.getAtomicDataType());
-      case LIST_DATA_TYPE:
-        return convertListDataType(dataType.getListDataType());
-      case REFERENCE_DATA_TYPE:
-        return convertReferenceDataType(dataType.getReferenceDataType());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private ReferenceDatatype convertReferenceDataType(final ReferenceDataType referenceDataType) {
-    final String name = referenceDataType.getName();
-    if (name.equalsIgnoreCase("REFERENCE")) {
-      return new ReferenceDatatype();
-    } else if (name.equalsIgnoreCase("FILE")) {
-      return new FileDatatype();
-    }
-    return new ReferenceDatatype2(name);
-  }
-
-  private AbstractDatatype convertAtomicType(final AtomicDataType dataType) {
-    switch (dataType) {
-      case ATOMIC_DATA_TYPE_BOOLEAN:
-        return AbstractDatatype.datatypeFactory("BOOLEAN");
-      case ATOMIC_DATA_TYPE_DATETIME:
-        return AbstractDatatype.datatypeFactory("DATETIME");
-      case ATOMIC_DATA_TYPE_DOUBLE:
-        return AbstractDatatype.datatypeFactory("DOUBLE");
-      case ATOMIC_DATA_TYPE_INTEGER:
-        return AbstractDatatype.datatypeFactory("INTEGER");
-      case ATOMIC_DATA_TYPE_TEXT:
-        return AbstractDatatype.datatypeFactory("TEXT");
-      default:
-        return null;
-    }
-  }
-
-  private AbstractDatatype convertListDataType(final ListDataType dataType) {
-    switch (dataType.getListDataTypeCase()) {
-      case ATOMIC_DATA_TYPE:
-        return new ListDatatype(convertAtomicType(dataType.getAtomicDataType()));
-      case REFERENCE_DATA_TYPE:
-        return new ListDatatype(convertReferenceDataType(dataType.getReferenceDataType()));
-      default:
-        return null;
-    }
-  }
-
-  private FileProperties convert(final FileDescriptor fileDescriptor) {
-    return new FileProperties(
-        null,
-        fileDescriptor.getPath(),
-        fileDescriptor.getSize() == 0 ? null : fileDescriptor.getSize());
-  }
-
-  private Collection<Property> convertProperties(
-      final List<org.caosdb.api.entity.v1.Property> propertiesList,
-      final StatementStatus defaultImportance) {
-    final Collection<Property> result = new LinkedList<>();
-    propertiesList.forEach(
-        e -> {
-          result.add(convert(e, defaultImportance));
-        });
-    return result;
-  }
-
-  private Property convert(
-      final org.caosdb.api.entity.v1.Property e, final StatementStatus defaultImportance) {
-    final Property result = new Property();
-
-    try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
-    } catch (final NumberFormatException exc) {
-      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
-    }
-    result.setName(e.getName().isBlank() ? null : e.getName());
-    result.setDescription(e.getDescription().isBlank() ? null : e.getDescription());
-    if (!e.getUnit().isBlank()) {
-      result.addProperty(getUnit(e.getUnit()));
-    }
-    if (e.hasDataType()) {
-      result.setDatatype(convert(e.getDataType()));
-    }
-    if (e.hasValue()) {
-      result.setValue(convert(e.getValue()));
-    }
-    if (e.getImportance() != Importance.IMPORTANCE_UNSPECIFIED) {
-      result.setStatementStatus(convert(e.getImportance()));
-    } else {
-      result.setStatementStatus(defaultImportance);
-    }
-    // TODO remove this hard-coded setting when the API supports flags
-    if (result.getFlag("inheritance") == null) {
-      result.setFlag("inheritance", "fix");
-    }
-
-    return result;
-  }
-
-  private StatementStatus convert(final Importance importance) {
-    switch (importance) {
-      case IMPORTANCE_FIX:
-        return StatementStatus.FIX;
-      case IMPORTANCE_OBLIGATORY:
-        return StatementStatus.OBLIGATORY;
-      case IMPORTANCE_RECOMMENDED:
-        return StatementStatus.RECOMMENDED;
-      case IMPORTANCE_SUGGESTED:
-        return StatementStatus.SUGGESTED;
-      default:
-        return null;
-    }
-  }
-
-  private Collection<org.caosdb.server.entity.wrapper.Parent> convertParents(
-      final List<Parent> parentsList) {
-    final Collection<org.caosdb.server.entity.wrapper.Parent> result = new LinkedList<>();
-    parentsList.forEach(
-        e -> {
-          result.add(convert(e));
-        });
-    return result;
-  }
-
-  private org.caosdb.server.entity.wrapper.Parent convert(final Parent e) {
-    final org.caosdb.server.entity.wrapper.Parent result =
-        new org.caosdb.server.entity.wrapper.Parent();
-
-    try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
-    } catch (final NumberFormatException exc) {
-      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
-    }
-    result.setName(e.getName().isBlank() ? null : e.getName());
-    return result;
-  }
-
   @Override
   public void multiTransaction(
       final MultiTransactionRequest request,
diff --git a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
new file mode 100644
index 0000000000000000000000000000000000000000..a79f1293f2d0f6ddc343da3b4215db9cc9ec1c94
--- /dev/null
+++ b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
@@ -0,0 +1,288 @@
+package org.caosdb.server.grpc;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.api.entity.v1.AtomicDataType;
+import org.caosdb.api.entity.v1.CollectionValues;
+import org.caosdb.api.entity.v1.DataType;
+import org.caosdb.api.entity.v1.Entity;
+import org.caosdb.api.entity.v1.EntityRole;
+import org.caosdb.api.entity.v1.FileDescriptor;
+import org.caosdb.api.entity.v1.Importance;
+import org.caosdb.api.entity.v1.ListDataType;
+import org.caosdb.api.entity.v1.Parent;
+import org.caosdb.api.entity.v1.ReferenceDataType;
+import org.caosdb.api.entity.v1.SpecialValue;
+import org.caosdb.server.datatype.AbstractDatatype;
+import org.caosdb.server.datatype.BooleanValue;
+import org.caosdb.server.datatype.CollectionValue;
+import org.caosdb.server.datatype.FileDatatype;
+import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.ListDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype2;
+import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.FileProperties;
+import org.caosdb.server.entity.MagicTypes;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.wrapper.Property;
+import org.caosdb.server.utils.EntityStatus;
+import org.caosdb.server.utils.ServerMessages;
+
+public class GrpcToCaosDBConverters {
+  /// MOVE
+  public Integer getId(final String id) {
+    return Integer.parseInt(id);
+  }
+
+  public Role convert(final EntityRole role) {
+    switch (role) {
+      case ENTITY_ROLE_FILE:
+        return Role.File;
+      case ENTITY_ROLE_PROPERTY:
+        return Role.Property;
+      case ENTITY_ROLE_RECORD:
+        return Role.Record;
+      case ENTITY_ROLE_RECORD_TYPE:
+        return Role.RecordType;
+      default:
+        return null;
+    }
+  }
+
+  public Property getUnit(final String unitStr) {
+    final EntityInterface magicUnit = MagicTypes.UNIT.getEntity();
+    final Property unit = new Property();
+    unit.setDescription(magicUnit.getDescription());
+    unit.setName(magicUnit.getName());
+    unit.setId(magicUnit.getId());
+    unit.setDatatype(magicUnit.getDatatype());
+    unit.setStatementStatus(StatementStatus.FIX);
+    unit.setValue(new GenericValue(unitStr));
+    unit.setEntityStatus(EntityStatus.QUALIFIED);
+    return unit;
+  }
+
+  public Value getValue(final String valString) {
+    return new GenericValue(valString);
+  }
+
+  public EntityInterface convert(final Entity from, final EntityInterface entity) {
+    entity.setName(from.getName().isEmpty() ? null : from.getName());
+    entity.setDescription(from.getDescription().isBlank() ? null : from.getDescription());
+    if (!from.getUnit().isBlank()) {
+      entity.addProperty(getUnit(from.getUnit()));
+    }
+    if (from.hasDataType()) {
+      entity.setDatatype(convert(from.getDataType()));
+    }
+    if (from.hasValue()) {
+      entity.setValue(convert(from.getValue()));
+    }
+
+    if (from.getPropertiesCount() > 0) {
+      final StatementStatus defaultImportance =
+          entity.getRole() == Role.RecordType ? StatementStatus.RECOMMENDED : StatementStatus.FIX;
+      entity.getProperties().addAll(convertProperties(from.getPropertiesList(), defaultImportance));
+    }
+    if (from.getParentsCount() > 0) {
+      entity.getParents().addAll(convertParents(from.getParentsList()));
+    }
+    if (from.hasFileDescriptor()) {
+      entity.setFileProperties(convert(from.getFileDescriptor()));
+    }
+    return entity;
+  }
+
+  private Value convert(final org.caosdb.api.entity.v1.Value value) {
+    switch (value.getValueCase()) {
+      case LIST_VALUES:
+        return convertListValue(value.getListValues());
+      case SCALAR_VALUE:
+        return convertScalarValue(value.getScalarValue());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private CollectionValue convertListValue(final CollectionValues collectionValues) {
+    final CollectionValue result = new CollectionValue();
+    collectionValues
+        .getValuesList()
+        .forEach(
+            (v) -> {
+              result.add(convertScalarValue(v));
+            });
+    return result;
+  }
+
+  private Value convertScalarValue(final org.caosdb.api.entity.v1.ScalarValue value) {
+    switch (value.getScalarValueCase()) {
+      case BOOLEAN_VALUE:
+        return BooleanValue.valueOf(value.getBooleanValue());
+      case DOUBLE_VALUE:
+        return new GenericValue(value.getDoubleValue());
+      case INTEGER_VALUE:
+        return new GenericValue(Long.toString(value.getIntegerValue()));
+      case SPECIAL_VALUE:
+        return convertSpecial(value.getSpecialValue());
+      case STRING_VALUE:
+        return new GenericValue(value.getStringValue());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private Value convertSpecial(final SpecialValue specialValue) {
+    if (specialValue == SpecialValue.SPECIAL_VALUE_EMPTY_STRING) {
+      return new GenericValue("");
+    }
+    return null;
+  }
+
+  private AbstractDatatype convert(final DataType dataType) {
+    switch (dataType.getDataTypeCase()) {
+      case ATOMIC_DATA_TYPE:
+        return convertAtomicType(dataType.getAtomicDataType());
+      case LIST_DATA_TYPE:
+        return convertListDataType(dataType.getListDataType());
+      case REFERENCE_DATA_TYPE:
+        return convertReferenceDataType(dataType.getReferenceDataType());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private ReferenceDatatype convertReferenceDataType(final ReferenceDataType referenceDataType) {
+    final String name = referenceDataType.getName();
+    if (name.equalsIgnoreCase("REFERENCE")) {
+      return new ReferenceDatatype();
+    } else if (name.equalsIgnoreCase("FILE")) {
+      return new FileDatatype();
+    }
+    return new ReferenceDatatype2(name);
+  }
+
+  private AbstractDatatype convertAtomicType(final AtomicDataType dataType) {
+    switch (dataType) {
+      case ATOMIC_DATA_TYPE_BOOLEAN:
+        return AbstractDatatype.datatypeFactory("BOOLEAN");
+      case ATOMIC_DATA_TYPE_DATETIME:
+        return AbstractDatatype.datatypeFactory("DATETIME");
+      case ATOMIC_DATA_TYPE_DOUBLE:
+        return AbstractDatatype.datatypeFactory("DOUBLE");
+      case ATOMIC_DATA_TYPE_INTEGER:
+        return AbstractDatatype.datatypeFactory("INTEGER");
+      case ATOMIC_DATA_TYPE_TEXT:
+        return AbstractDatatype.datatypeFactory("TEXT");
+      default:
+        return null;
+    }
+  }
+
+  private AbstractDatatype convertListDataType(final ListDataType dataType) {
+    switch (dataType.getListDataTypeCase()) {
+      case ATOMIC_DATA_TYPE:
+        return new ListDatatype(convertAtomicType(dataType.getAtomicDataType()));
+      case REFERENCE_DATA_TYPE:
+        return new ListDatatype(convertReferenceDataType(dataType.getReferenceDataType()));
+      default:
+        return null;
+    }
+  }
+
+  private FileProperties convert(final FileDescriptor fileDescriptor) {
+    return new FileProperties(
+        null,
+        fileDescriptor.getPath(),
+        fileDescriptor.getSize() == 0 ? null : fileDescriptor.getSize());
+  }
+
+  private Collection<Property> convertProperties(
+      final List<org.caosdb.api.entity.v1.Property> propertiesList,
+      final StatementStatus defaultImportance) {
+    final Collection<Property> result = new LinkedList<>();
+    propertiesList.forEach(
+        e -> {
+          result.add(convert(e, defaultImportance));
+        });
+    return result;
+  }
+
+  private Property convert(
+      final org.caosdb.api.entity.v1.Property e, final StatementStatus defaultImportance) {
+    final Property result = new Property();
+
+    try {
+      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+    } catch (final NumberFormatException exc) {
+      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
+    }
+    result.setName(e.getName().isBlank() ? null : e.getName());
+    result.setDescription(e.getDescription().isBlank() ? null : e.getDescription());
+    if (!e.getUnit().isBlank()) {
+      result.addProperty(getUnit(e.getUnit()));
+    }
+    if (e.hasDataType()) {
+      result.setDatatype(convert(e.getDataType()));
+    }
+    if (e.hasValue()) {
+      result.setValue(convert(e.getValue()));
+    }
+    if (e.getImportance() != Importance.IMPORTANCE_UNSPECIFIED) {
+      result.setStatementStatus(convert(e.getImportance()));
+    } else {
+      result.setStatementStatus(defaultImportance);
+    }
+    // TODO remove this hard-coded setting when the API supports flags
+    if (result.getFlag("inheritance") == null) {
+      result.setFlag("inheritance", "fix");
+    }
+
+    return result;
+  }
+
+  private StatementStatus convert(final Importance importance) {
+    switch (importance) {
+      case IMPORTANCE_FIX:
+        return StatementStatus.FIX;
+      case IMPORTANCE_OBLIGATORY:
+        return StatementStatus.OBLIGATORY;
+      case IMPORTANCE_RECOMMENDED:
+        return StatementStatus.RECOMMENDED;
+      case IMPORTANCE_SUGGESTED:
+        return StatementStatus.SUGGESTED;
+      default:
+        return null;
+    }
+  }
+
+  private Collection<org.caosdb.server.entity.wrapper.Parent> convertParents(
+      final List<Parent> parentsList) {
+    final Collection<org.caosdb.server.entity.wrapper.Parent> result = new LinkedList<>();
+    parentsList.forEach(
+        e -> {
+          result.add(convert(e));
+        });
+    return result;
+  }
+
+  private org.caosdb.server.entity.wrapper.Parent convert(final Parent e) {
+    final org.caosdb.server.entity.wrapper.Parent result =
+        new org.caosdb.server.entity.wrapper.Parent();
+
+    try {
+      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+    } catch (final NumberFormatException exc) {
+      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
+    }
+    result.setName(e.getName().isBlank() ? null : e.getName());
+    return result;
+  }
+}
diff --git a/src/main/java/org/caosdb/server/utils/ServerMessages.java b/src/main/java/org/caosdb/server/utils/ServerMessages.java
index 6280ca28eb0515ce395b51ea3e75fd7984385a58..759aeef837092b3d1e004cbd4ec1d2016c388b83 100644
--- a/src/main/java/org/caosdb/server/utils/ServerMessages.java
+++ b/src/main/java/org/caosdb/server/utils/ServerMessages.java
@@ -55,7 +55,7 @@ public class ServerMessages {
       new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Parsing failed.");
 
   public static final Message UNKNOWN_DATATYPE =
-      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Unknown data type.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Unknown datatype.");
 
   public static final Message UNKNOWN_IMPORTANCE =
       new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Unknown importance.");