diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/Experiment.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/Experiment.java
index c40e3996f469121effc449e0a67708478be48aa2..2606c9f8c1909bb30a4e0ff679b0f4875e1de699 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/Experiment.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/Experiment.java
@@ -145,6 +145,10 @@ public class Experiment implements Serializable, IAttachmentsHolder, ICodeHolder
     @JsonProperty
     private List<Attachment> attachments;
 
+    @JsonProperty
+    private Map<String, String> metaData;
+
+
     // Method automatically generated with DtoGenerator
     @JsonIgnore
     public ExperimentFetchOptions getFetchOptions()
@@ -848,6 +852,18 @@ public class Experiment implements Serializable, IAttachmentsHolder, ICodeHolder
         setProperty(propertyName, propertyValue);
     }
 
+    @JsonIgnore
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
+
     // Method automatically generated with DtoGenerator
     @Override
     public String toString()
diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/ExperimentType.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/ExperimentType.java
index eed4b0fbe7d6467fa3b351104f3fa7558aad854d..8e05cf142cde3c0a643fb599728bc6cf4209457a 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/ExperimentType.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/ExperimentType.java
@@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /*
  * Class automatically generated with DtoGenerator
@@ -62,6 +63,10 @@ public class ExperimentType implements Serializable, ICodeHolder, IDescriptionHo
     @JsonProperty
     private Plugin validationPlugin;
 
+    @JsonProperty
+    private Map<String, String> metaData;
+
+
     // Method automatically generated with DtoGenerator
     @JsonIgnore
     public ExperimentTypeFetchOptions getFetchOptions()
@@ -170,6 +175,18 @@ public class ExperimentType implements Serializable, ICodeHolder, IDescriptionHo
         this.validationPlugin = validationPlugin;
     }
 
+    @JsonIgnore
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
+
     // Method automatically generated with DtoGenerator
     @Override
     public String toString()
diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentCreation.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentCreation.java
index 6097d4802ad6dadfb530d53a1f4b97f3a6cea792..f32fe52a0607a7e4cfec84aa863f9ab29de352cc 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentCreation.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentCreation.java
@@ -54,6 +54,8 @@ public class ExperimentCreation implements ICreation, IObjectCreation, ICreation
 
     private CreationId creationId;
 
+    private Map<String, String> metaData;
+
     public void setTypeId(IEntityTypeId typeId)
     {
         this.typeId = typeId;
@@ -94,6 +96,16 @@ public class ExperimentCreation implements ICreation, IObjectCreation, ICreation
         this.tagIds = tagIds;
     }
 
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
     @Override
     public void setProperty(String propertyName, String propertyValue)
     {
diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentTypeCreation.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentTypeCreation.java
index 1eb1ac1ea860deec41da79817bc6aa930ffb5170..f42a67bb43fd61e722c1f7cb47c142156e66abb2 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentTypeCreation.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/create/ExperimentTypeCreation.java
@@ -16,6 +16,7 @@
 package ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.create;
 
 import java.util.List;
+import java.util.Map;
 
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.ObjectToString;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.create.IEntityTypeCreation;
@@ -40,6 +41,8 @@ public class ExperimentTypeCreation implements IEntityTypeCreation
 
     private List<PropertyAssignmentCreation> propertyAssignments;
 
+    private Map<String, String> metaData;
+
     @Override
     public String getCode()
     {
@@ -88,6 +91,16 @@ public class ExperimentTypeCreation implements IEntityTypeCreation
         this.propertyAssignments = propertyAssignments;
     }
 
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
     @Override
     public String toString()
     {
diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentTypeUpdate.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentTypeUpdate.java
index f85fec055b4232c64d8fbbd88c38cecf97cae2dc..926f86f5e833feeed59ec451cc9d7babed20efbd 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentTypeUpdate.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentTypeUpdate.java
@@ -17,6 +17,7 @@ package ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.update;
 
 import java.util.List;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.ListUpdateMapValues;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -49,6 +50,9 @@ public class ExperimentTypeUpdate implements IEntityTypeUpdate
     @JsonProperty
     private PropertyAssignmentListUpdateValue propertyAssignments = new PropertyAssignmentListUpdateValue();
 
+    @JsonProperty
+    private ListUpdateMapValues metaData = new ListUpdateMapValues();
+
     @Override
     @JsonIgnore
     public IEntityTypeId getObjectId()
@@ -112,6 +116,19 @@ public class ExperimentTypeUpdate implements IEntityTypeUpdate
         propertyAssignments.setActions(actions);
     }
 
+    @JsonIgnore
+    public ListUpdateMapValues getMetaData()
+    {
+        return metaData;
+    }
+
+    @JsonIgnore
+    public void setMetaDataActions(List<ListUpdateAction<Object>> actions)
+    {
+        metaData.setActions(actions);
+    }
+
+
     @Override
     public String toString()
     {
diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentUpdate.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentUpdate.java
index c577701b7abad353bf982cae9da78ca3c637dfcc..65dfee91b4d817dbba59b9d4b8ba3f98df91670a 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentUpdate.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/experiment/update/ExperimentUpdate.java
@@ -19,6 +19,7 @@ import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.*;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id.SamplePermId;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -26,10 +27,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.attachment.update.AttachmentListUpdateValue;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.ObjectToString;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IPropertiesHolder;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.FieldUpdateValue;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.IObjectUpdate;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.IUpdate;
-import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.IdListUpdateValue;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.ListUpdateValue.ListUpdateAction;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.IExperimentId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.id.IProjectId;
@@ -69,6 +66,9 @@ public class ExperimentUpdate implements IUpdate, IObjectUpdate<IExperimentId>,
     @JsonProperty
     private AttachmentListUpdateValue attachments = new AttachmentListUpdateValue();
 
+    @JsonProperty
+    private ListUpdateMapValues metaData = new ListUpdateMapValues();
+
     @Override
     @JsonIgnore
     public IExperimentId getObjectId()
@@ -378,6 +378,19 @@ public class ExperimentUpdate implements IUpdate, IObjectUpdate<IExperimentId>,
         setProperty(propertyName, propertyValue);
     }
 
+    @JsonIgnore
+    public ListUpdateMapValues getMetaData()
+    {
+        return metaData;
+    }
+
+    @JsonIgnore
+    public void setMetaDataActions(List<ListUpdateAction<Object>> actions)
+    {
+        metaData.setActions(actions);
+    }
+
+
     @Override
     public String toString()
     {
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/Experiment.js b/api-openbis-javascript/src/v3/as/dto/experiment/Experiment.js
index 92eddf528fd4bd83caf3942fa7ecdd85dfdb6938..3cf538a60db05587609913df8be46b70d5aae16e 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/Experiment.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/Experiment.js
@@ -34,6 +34,7 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) {
 		prototype.registrator = null;
 		prototype.modifier = null;
 		prototype.attachments = null;
+		prototype.metaData = null;
 		prototype.getFetchOptions = function() {
 			return this.fetchOptions;
 		};
@@ -374,6 +375,12 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) {
 		prototype.setAttachments = function(attachments) {
 			this.attachments = attachments;
 		};
+		prototype.getMetaData = function() {
+            return this.metaData;
+        };
+        prototype.setMetaData = function(metaData) {
+            this.metaData = metaData;
+        };
 		prototype.toString = function() {
 			return "Experiment " + this.permId;
 		};
@@ -438,7 +445,11 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) {
 		attachments : {
 			name : "List",
 			arguments : [ "Attachment" ]
-		}
+		},
+        metaData: {
+             name: "Map",
+             arguments: ["String", "String"]
+         }
 	});
 	return Experiment;
 })
\ No newline at end of file
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/ExperimentType.js b/api-openbis-javascript/src/v3/as/dto/experiment/ExperimentType.js
index cb12eca75ea3348a2d4068fb01c68b2c9c671714..565fa375b0de8aedf4939d45bd00a9b57a3c7b68 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/ExperimentType.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/ExperimentType.js
@@ -18,6 +18,7 @@ define(['stjs'], function (stjs) {
       prototype.modificationDate = null
       prototype.propertyAssignments = null
       prototype.validationPlugin = null
+      prototype.metaData = null;
       prototype.getPropertyAssignments = function () {
         if (
           this.getFetchOptions() &&
@@ -78,6 +79,12 @@ define(['stjs'], function (stjs) {
       prototype.setModificationDate = function (modificationDate) {
         this.modificationDate = modificationDate
       }
+      prototype.getMetaData = function() {
+        return this.metaData;
+      };
+      prototype.setMetaData = function(metaData) {
+        this.metaData = metaData;
+      };
       prototype.toString = function () {
         return this.getCode()
       }
@@ -90,7 +97,11 @@ define(['stjs'], function (stjs) {
         name: 'List',
         arguments: ['PropertyAssignment']
       },
-      validationPlugin: 'Plugin'
+      validationPlugin: 'Plugin',
+      metaData: {
+        name: "Map",
+        arguments: ["String", "String"]
+      }
     }
   )
   return ExperimentType
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentCreation.js b/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentCreation.js
index d5af878a2912a65750180b85ee917aaa33aa157c..dc536cb1a81bd8e9f4e8b30f30f241ad30c30169 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentCreation.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentCreation.js
@@ -15,7 +15,7 @@ define([ "stjs" ], function(stjs) {
 		prototype.properties = null;
 		prototype.attachments = null;
 		prototype.creationId = null;
-
+        prototype.metaData = null;
 		prototype.setTypeId = function(typeId) {
 			this.typeId = typeId;
 		};
@@ -154,6 +154,12 @@ define([ "stjs" ], function(stjs) {
 		prototype.setCreationId = function(creationId) {
 			this.creationId = creationId;
 		};
+		prototype.getMetaData = function() {
+            return this.metaData;
+        };
+        prototype.setMetaData = function(metaData) {
+            this.metaData = metaData;
+        };
 	}, {
 		typeId : "IEntityTypeId",
 		projectId : "IProjectId",
@@ -169,7 +175,11 @@ define([ "stjs" ], function(stjs) {
 			name : "List",
 			arguments : [ "AttachmentCreation" ]
 		},
-		creationId : "CreationId"
+        creationId : "CreationId",
+        metaData: {
+             name: "Map",
+             arguments: ["String", "String"]
+        }
 	});
 	return ExperimentCreation;
 })
\ No newline at end of file
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentTypeCreation.js b/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentTypeCreation.js
index 56d473bf6916dd6e64e736b8687ff07e5ffbd062..7dabdb028089bf2302476961ce610c5c9556a942 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentTypeCreation.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/create/ExperimentTypeCreation.js
@@ -11,6 +11,7 @@ define([ "stjs" ], function(stjs) {
 		prototype.description = null;
 		prototype.validationPluginId = null;
 		prototype.propertyAssignments = null;
+        prototype.metaData = null;
 
 		prototype.getCode = function() {
 			return this.code;
@@ -36,13 +37,23 @@ define([ "stjs" ], function(stjs) {
 		prototype.setPropertyAssignments = function(propertyAssignments) {
 			this.propertyAssignments = propertyAssignments;
 		};
+        prototype.getMetaData = function() {
+            return this.metaData;
+        };
+        prototype.setMetaData = function(metaData) {
+            this.metaData = metaData;
+        };
 
 	}, {
 		validationPluginId : "IPluginId",
 		propertyAssignments : {
 			name : "List",
 			arguments : [ "PropertyAssignmentCreation" ]
-		}
+		},
+        metaData: {
+             name: "Map",
+             arguments: ["String", "String"]
+         }
 	});
 	return ExperimentTypeCreation;
 })
\ No newline at end of file
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentTypeUpdate.js b/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentTypeUpdate.js
index df2b587b1953c73414d0abf7cea5bde03a2b2da4..076b9c98378b46ca085a50318e7b0c8e7ac6adb0 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentTypeUpdate.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentTypeUpdate.js
@@ -1,9 +1,11 @@
-define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/entitytype/update/PropertyAssignmentListUpdateValue" ], function(stjs, FieldUpdateValue, 
-		PropertyAssignmentListUpdateValue) {
+define([ "stjs", "as/dto/common/update/FieldUpdateValue",
+    "as/dto/entitytype/update/PropertyAssignmentListUpdateValue", "as/dto/common/update/ListUpdateMapValues"],
+     function(stjs, FieldUpdateValue, PropertyAssignmentListUpdateValue, ListUpdateMapValues) {
 	var ExperimentTypeUpdate = function() {
 		this.description = new FieldUpdateValue();
 		this.validationPluginId = new FieldUpdateValue();
 		this.propertyAssignments = new PropertyAssignmentListUpdateValue();
+		this.metaData = new ListUpdateMapValues();
 	};
 	stjs.extend(ExperimentTypeUpdate, null, [], function(constructor, prototype) {
 		prototype['@type'] = 'as.dto.experiment.update.ExperimentTypeUpdate';
@@ -12,6 +14,7 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/entitytype/upd
 		prototype.description = null;
 		prototype.validationPluginId = null;
 		prototype.propertyAssignments = null;
+		prototype.metaData = null;
 
 		prototype.getObjectId = function() {
 			return this.getTypeId();
@@ -40,6 +43,12 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/entitytype/upd
 		prototype.setPropertyAssignmentActions = function(actions) {
 			this.propertyAssignments.setActions(actions);
 		};
+		prototype.getMetaData = function() {
+            return this.metaData;
+        };
+        prototype.setMetaDataActions = function(actions) {
+            this.metaData.setActions(actions);
+        };
 	}, {
 		typeId : "IEntityTypeId",
 		description : {
@@ -50,7 +59,8 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/entitytype/upd
 			name : "FieldUpdateValue",
 			arguments : [ "IPluginId" ]
 		},
-		propertyAssignments : "PropertyAssignmentListUpdateValue"
+		propertyAssignments : "PropertyAssignmentListUpdateValue",
+		metaData : "ListUpdateMapValues"
 	});
 	return ExperimentTypeUpdate;
 })
\ No newline at end of file
diff --git a/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentUpdate.js b/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentUpdate.js
index b34d7714a3a1f8cbbcb39fb63e1aa1753846a690..0deae9fc13fd1b1983c462f5227d2825b3c4212d 100644
--- a/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentUpdate.js
+++ b/api-openbis-javascript/src/v3/as/dto/experiment/update/ExperimentUpdate.js
@@ -1,13 +1,16 @@
 /**
  * @author pkupczyk
  */
-define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/IdListUpdateValue", "as/dto/attachment/update/AttachmentListUpdateValue" ], function(stjs, FieldUpdateValue, IdListUpdateValue,
-		AttachmentListUpdateValue) {
+define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/IdListUpdateValue",
+    "as/dto/attachment/update/AttachmentListUpdateValue", "as/dto/common/update/ListUpdateMapValues" ],
+    function(stjs, FieldUpdateValue, IdListUpdateValue,
+		AttachmentListUpdateValue, ListUpdateMapValues) {
 	var ExperimentUpdate = function() {
 		this.properties = {};
 		this.projectId = new FieldUpdateValue();
 		this.tagIds = new IdListUpdateValue();
 		this.attachments = new AttachmentListUpdateValue();
+		this.metaData = new ListUpdateMapValues();
 	};
 	stjs.extend(ExperimentUpdate, null, [], function(constructor, prototype) {
 		prototype['@type'] = 'as.dto.experiment.update.ExperimentUpdate';
@@ -20,6 +23,7 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/
 		prototype.projectId = null;
 		prototype.tagIds = null;
 		prototype.attachments = null;
+		prototype.metaData = null;
 
 		prototype.getObjectId = function() {
 			return this.getExperimentId();
@@ -167,6 +171,12 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/
 		prototype.setAttachmentsActions = function(actions) {
 			this.attachments.setActions(actions);
 		};
+		prototype.getMetaData = function() {
+            return this.metaData;
+        };
+        prototype.setMetaDataActions = function(actions) {
+            this.metaData.setActions(actions);
+        };
 	}, {
 		experimentId : "IExperimentId",
 		properties : {
@@ -181,7 +191,8 @@ define([ "stjs", "as/dto/common/update/FieldUpdateValue", "as/dto/common/update/
 			name : "IdListUpdateValue",
 			arguments : [ "ITagId" ]
 		},
-		attachments : "AttachmentListUpdateValue"
+		attachments : "AttachmentListUpdateValue",
+        metaData : "ListUpdateMapValues"
 	});
 	return ExperimentUpdate;
 })
\ No newline at end of file
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentExecutor.java
index bbb97b4d0b7fa4079956c6aecb85f68c91e073b1..06b78045911ea09a440222884585b2a324769bd6 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentExecutor.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentExecutor.java
@@ -101,6 +101,7 @@ public class CreateExperimentExecutor extends AbstractCreateEntityExecutor<Exper
                     experiment.setPermId(createdPermId);
                     experiment.setRegistrator(person);
                     RelationshipUtils.updateModificationDateAndModifier(experiment, person, timeStamp);
+                    experiment.setMetaData(object.getMetaData());
                     experiments.add(experiment);
                 }
 
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentTypesExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentTypesExecutor.java
index edf5470e5489821fd85f7857eb3f2183062ff411..a451eef136b2835b5fe5767ad313f0b91fb7503a 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentTypesExecutor.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/CreateExperimentTypesExecutor.java
@@ -64,7 +64,7 @@ public class CreateExperimentTypesExecutor extends AbstractCreateEntityTypeExecu
     @Override
     protected void fillTypeSpecificFields(ExperimentType type, ExperimentTypeCreation creation)
     {
-        // nothing to do
+        type.setMetaData(creation.getMetaData());
     }
 
     @Override
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentExecutor.java
index 6958cc946609160fe9d3c26ac0b8695d8df4a888..af3397f4c99e829072871d20d14ac2d0aaca4931 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentExecutor.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentExecutor.java
@@ -15,13 +15,11 @@
  */
 package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.experiment;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.ListUpdateValue;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataAccessException;
 import org.springframework.stereotype.Component;
@@ -114,6 +112,7 @@ public class UpdateExperimentExecutor extends AbstractUpdateEntityExecutor<Exper
         updateExperimentPropertyExecutor.update(context, batch);
         updateTags(context, batch);
         updateAttachments(context, batch);
+        updateMetaData(context, batch);
 
         PersonPE person = context.getSession().tryGetPerson();
         Date timeStamp = daoFactory.getTransactionTimestamp();
@@ -156,6 +155,69 @@ public class UpdateExperimentExecutor extends AbstractUpdateEntityExecutor<Exper
         }
     }
 
+    private void updateMetaData(final IOperationContext context, final MapBatch<ExperimentUpdate, ExperimentPE> batch)
+    {
+        new MapBatchProcessor<ExperimentUpdate, ExperimentPE>(context, batch)
+        {
+            @Override
+            public void process(ExperimentUpdate update, ExperimentPE entity)
+            {
+                Map<String, String> metaData = new HashMap<>();
+                if(entity.getMetaData() != null) {
+                    metaData.putAll(entity.getMetaData());
+                }
+                ListUpdateValue.ListUpdateActionSet<?> lastSetAction = null;
+                AtomicBoolean metaDataChanged = new AtomicBoolean(false);
+                for (ListUpdateValue.ListUpdateAction<Object> action : update.getMetaData().getActions())
+                {
+                    if (action instanceof ListUpdateValue.ListUpdateActionAdd<?>)
+                    {
+                        addTo(metaData, action, metaDataChanged);
+                    } else if (action instanceof ListUpdateValue.ListUpdateActionRemove<?>)
+                    {
+                        for (String key : (Collection<String>) action.getItems())
+                        {
+                            metaDataChanged.set(true);
+                            metaData.remove(key);
+                        }
+                    } else if (action instanceof ListUpdateValue.ListUpdateActionSet<?>)
+                    {
+                        lastSetAction = (ListUpdateValue.ListUpdateActionSet<?>) action;
+                    }
+                }
+                if (lastSetAction != null)
+                {
+                    metaData.clear();
+                    addTo(metaData, lastSetAction, metaDataChanged);
+                }
+                if (metaDataChanged.get())
+                {
+                    entity.setMetaData(metaData.isEmpty() ? null : metaData);
+                }
+            }
+
+            @Override
+            public IProgress createProgress(ExperimentUpdate update, ExperimentPE entity, int objectIndex, int totalObjectCount)
+            {
+                return new UpdateRelationProgress(update, entity, "experiment-tag", objectIndex, totalObjectCount);
+            }
+
+            @SuppressWarnings("unchecked")
+            private void addTo(Map<String, String> metaData, ListUpdateValue.ListUpdateAction<?> lastSetAction, AtomicBoolean metaDataChanged)
+            {
+                Collection<Map<String, String>> maps = (Collection<Map<String, String>>) lastSetAction.getItems();
+                for (Map<String, String> map : maps)
+                {
+                    if (!map.isEmpty())
+                    {
+                        metaDataChanged.set(true);
+                        metaData.putAll(map);
+                    }
+                }
+            }
+        };
+    }
+
     private void updateTags(final IOperationContext context, final MapBatch<ExperimentUpdate, ExperimentPE> batch)
     {
         new MapBatchProcessor<ExperimentUpdate, ExperimentPE>(context, batch)
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentTypeExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentTypeExecutor.java
index 7943c226ac0fca9d694b783c8ae1ac53e59f4621..1f3df9a824de3e5002af6bf8aec44e39ecbb9e58 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentTypeExecutor.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/experiment/UpdateExperimentTypeExecutor.java
@@ -15,6 +15,7 @@
  */
 package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.experiment;
 
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update.ListUpdateValue;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -26,6 +27,11 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.IUpdateEntity
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * @author Franz-Josef Elmer
  */
@@ -51,6 +57,12 @@ public class UpdateExperimentTypeExecutor
     {
     }
 
+    @Override
+    protected void updateSpecific(ExperimentTypePE type, ExperimentTypeUpdate update)
+    {
+        updateMetaData(type, update);
+    }
+
     @Override
     protected IUpdateEntityTypePropertyTypesExecutor<ExperimentTypeUpdate, ExperimentTypePE> getUpdateEntityTypePropertyTypeExecutor()
     {
@@ -63,4 +75,53 @@ public class UpdateExperimentTypeExecutor
         authorizationExecutor.canUpdate(context);
     }
 
+    private void updateMetaData(ExperimentTypePE type, ExperimentTypeUpdate update)
+    {
+        Map<String, String> metaData = new HashMap<>();
+        if(type.getMetaData() != null) {
+            metaData.putAll(type.getMetaData());
+        }
+        ListUpdateValue.ListUpdateActionSet<?> lastSetAction = null;
+        AtomicBoolean metaDataChanged = new AtomicBoolean(false);
+        for (ListUpdateValue.ListUpdateAction<Object> action : update.getMetaData().getActions())
+        {
+            if (action instanceof ListUpdateValue.ListUpdateActionAdd<?>)
+            {
+                addTo(metaData, action, metaDataChanged);
+            } else if (action instanceof ListUpdateValue.ListUpdateActionRemove<?>)
+            {
+                for (String key : (Collection<String>) action.getItems())
+                {
+                    metaDataChanged.set(true);
+                    metaData.remove(key);
+                }
+            } else if (action instanceof ListUpdateValue.ListUpdateActionSet<?>)
+            {
+                lastSetAction = (ListUpdateValue.ListUpdateActionSet<?>) action;
+            }
+        }
+        if (lastSetAction != null)
+        {
+            metaData.clear();
+            addTo(metaData, lastSetAction, metaDataChanged);
+        }
+        if (metaDataChanged.get())
+        {
+            type.setMetaData(metaData.isEmpty() ? null : metaData);
+        }
+    }
+
+    private void addTo(Map<String, String> metaData, ListUpdateValue.ListUpdateAction<?> lastSetAction, AtomicBoolean metaDataChanged)
+    {
+        Collection<Map<String, String>> maps = (Collection<Map<String, String>>) lastSetAction.getItems();
+        for (Map<String, String> map : maps)
+        {
+            if (!map.isEmpty())
+            {
+                metaDataChanged.set(true);
+                metaData.putAll(map);
+            }
+        }
+    }
+
 }
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/generators/Generator.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/generators/Generator.java
index 1dadf4b81bd614d52e95a3f35194fe22e741489b..ba929dd1517b4205c178545aa0df67a6ebfb59bf 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/generators/Generator.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/generators/Generator.java
@@ -341,6 +341,7 @@ public class Generator extends AbstractGenerator
         addRegistrator(gen);
         addModifier(gen);
         addAttachments(gen);
+        addMetaData(gen);
 
         gen.setToStringMethod("\"Experiment \" + permId");
 
@@ -356,6 +357,7 @@ public class Generator extends AbstractGenerator
         addCode(gen);
         addDescription(gen);
         addModificationDate(gen);
+        addMetaData(gen);
 
         gen.setToStringMethod("\"ExperimentType \" + code");
         addPropertyAssignments(gen);
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentBaseRecord.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentBaseRecord.java
index f8d441c51beeba4b466466db6feaa4f905df5d85..c4fe53eb5920de7d6140f174f5afbd0dffbfb194 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentBaseRecord.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentBaseRecord.java
@@ -43,4 +43,6 @@ public class ExperimentBaseRecord extends ObjectBaseRecord
 
     public Date modificationDate;
 
+    public String metaData;
+
 }
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentQuery.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentQuery.java
index c13492e00598feb27de5d52cea977050b34b5a9b..1a8be90db0c1de5476c5539e607e956b97ba8c02 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentQuery.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentQuery.java
@@ -38,7 +38,8 @@ public interface ExperimentQuery extends ObjectQuery
 
     @Select(sql = "select e.id, e.code, e.perm_id as permId, p.code as projectCode, sp.code as spaceCode, "
             + "e.registration_timestamp as registrationDate, e.modification_timestamp as modificationDate, "
-            + "e.frozen as frozen, e.frozen_for_data as frozenForDataSets, e.frozen_for_samp as frozenForSamples "
+            + "e.frozen as frozen, e.frozen_for_data as frozenForDataSets, e.frozen_for_samp as frozenForSamples, "
+            + "e.meta_data as metaData "
             + "from experiments e join projects p on e.proj_id = p.id "
             + "join spaces sp on p.space_id = sp.id "
             + "where e.id = any(?{1})", parameterBindings = { LongSetMapper.class }, fetchSize = FETCH_SIZE)
@@ -48,7 +49,7 @@ public interface ExperimentQuery extends ObjectQuery
             LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public List<ObjectRelationRecord> getTypeIds(LongSet experimentIds);
 
-    @Select(sql = "select et.id, et.code, et.description, et.modification_timestamp as modificationDate "
+    @Select(sql = "select et.id, et.code, et.description, et.modification_timestamp as modificationDate, et.meta_data as metaData "
             + "from experiment_types et where et.id = any(?{1})", parameterBindings = { LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public List<ExperimentTypeBaseRecord> getTypes(LongSet experimentTypeIds);
 
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTranslator.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTranslator.java
index 7edefd0ad6c477a8ea08191a5da408d795b2b5ef..f74e934c10c71e4346849933c175f0af8c35b5b5 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTranslator.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTranslator.java
@@ -19,6 +19,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.common.CommonUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -234,6 +235,7 @@ public class ExperimentTranslator extends AbstractCachingTranslator<Long, Experi
         result.setFrozenForSamples(baseRecord.frozenForSamples);
         result.setRegistrationDate(baseRecord.registrationDate);
         result.setModificationDate(baseRecord.modificationDate);
+        result.setMetaData(CommonUtils.asMap(baseRecord.metaData));
 
         if (fetchOptions.hasType())
         {
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeBaseRecord.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeBaseRecord.java
index 8d0d441b6515ab4aba7cfd16102b3042c86e7186..45fb11f3e67cdd19e58b8b360376a86e0fa192ce 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeBaseRecord.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeBaseRecord.java
@@ -31,4 +31,6 @@ public class ExperimentTypeBaseRecord extends ObjectBaseRecord
 
     public Date modificationDate;
 
+    public String metaData;
+
 }
diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeTranslator.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeTranslator.java
index dd98602196d89f10b9f7a78aa53ccb349dd2bbed..f7ff3c1e9c246eddb46ff8a54cbc4155976a7927 100644
--- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeTranslator.java
+++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/experiment/ExperimentTypeTranslator.java
@@ -18,6 +18,7 @@ package ch.ethz.sis.openbis.generic.server.asapi.v3.translator.experiment;
 import java.util.Collection;
 import java.util.List;
 
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.common.CommonUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -86,6 +87,7 @@ public class ExperimentTypeTranslator extends AbstractCachingTranslator<Long, Ex
         result.setCode(baseRecord.code);
         result.setDescription(baseRecord.description);
         result.setModificationDate(baseRecord.modificationDate);
+        result.setMetaData(CommonUtils.asMap(baseRecord.metaData));
 
         if (fetchOptions.hasPropertyAssignments())
         {
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java
index 7be474770d5d90d2ae86eb1715f9e0cdc476c0ae..329f6ce13272d7492acfa6797b7d21ed4880bbaf 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java
@@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.IAttachmentHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithProperties;
@@ -61,6 +62,8 @@ public class Experiment extends CodeWithRegistrationAndModificationDate<Experime
 
     private Collection<Metaproject> metaprojects;
 
+    private Map<String, String> metaData;
+
     public Experiment()
     {
         this(false);
@@ -237,4 +240,15 @@ public class Experiment extends CodeWithRegistrationAndModificationDate<Experime
     {
         this.metaprojects = metaprojects;
     }
+
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ExperimentType.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ExperimentType.java
index ce346505c320d0191468af98abe56c572e520e6d..a1099b1212e2bc3a7b382d5a234dbacc7fd6d74b 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ExperimentType.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ExperimentType.java
@@ -16,6 +16,7 @@
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * The <i>GWT</i> equivalent to ExperimentTypePE.
@@ -28,6 +29,8 @@ public class ExperimentType extends EntityType
 
     private List<ExperimentTypePropertyType> experimentTypePropertyTypes;
 
+    private Map<String, String> metaData;
+
     @Override
     public List<ExperimentTypePropertyType> getAssignedPropertyTypes()
     {
@@ -51,4 +54,14 @@ public class ExperimentType extends EntityType
     {
         return EntityKind.EXPERIMENT;
     }
+
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
index 6c5142f3dd5545f5b80982749b792acd1a786873..e64c51d641d89e049f6cf7ca69b207b520984f55 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
@@ -16,11 +16,7 @@
 package ch.systemsx.cisd.openbis.generic.shared.dto;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -43,17 +39,11 @@ import javax.validation.constraints.Pattern;
 import ch.systemsx.cisd.openbis.generic.server.CommonServiceProvider;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.JsonMapUserType;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.hibernate.annotations.BatchSize;
-import org.hibernate.annotations.Cache;
-import org.hibernate.annotations.CacheConcurrencyStrategy;
-import org.hibernate.annotations.Fetch;
-import org.hibernate.annotations.FetchMode;
-import org.hibernate.annotations.Generated;
-import org.hibernate.annotations.GenerationTime;
-import org.hibernate.annotations.OptimisticLock;
+import org.hibernate.annotations.*;
 import org.hibernate.validator.constraints.Length;
 
 import ch.rinn.restrictions.Friend;
@@ -79,6 +69,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 @Table(name = TableNames.EXPERIMENTS_VIEW, uniqueConstraints = {
         @UniqueConstraint(columnNames = { ColumnNames.CODE_COLUMN, ColumnNames.PROJECT_COLUMN }) })
 @Friend(toClasses = { AttachmentPE.class, ProjectPE.class })
+@TypeDefs({ @TypeDef(name = "JsonMap", typeClass = JsonMapUserType.class) })
 public class ExperimentPE extends AttachmentHolderPE implements
         IEntityInformationWithPropertiesHolder, IIdAndCodeHolder, Comparable<ExperimentPE>,
         IModifierAndModificationDateBean, IMatchingEntity, IDeletablePE, IEntityWithMetaprojects, IIdentityHolder,
@@ -153,6 +144,8 @@ public class ExperimentPE extends AttachmentHolderPE implements
 
     private String permId;
 
+    private Map<String, String> metaData;
+
     @Column(name = ColumnNames.REGISTRATION_TIMESTAMP_COLUMN, nullable = false, insertable = false, updatable = false)
     @Generated(GenerationTime.INSERT)
     public Date getRegistrationDate()
@@ -709,4 +702,16 @@ public class ExperimentPE extends AttachmentHolderPE implements
     {
         setSamples(samples);
     }
+
+    @Column(name = "meta_data")
+    @Type(type = "JsonMap")
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
index e9615b5bad5761aa4566149ccbe826b2010b2535..3fd5eac42632c3c7624c5c2d02612d4a8f467dbf 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
@@ -17,22 +17,18 @@ package ch.systemsx.cisd.openbis.generic.shared.dto;
 
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
+import javax.persistence.*;
 import javax.persistence.Id;
-import javax.persistence.OneToMany;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.Table;
-import javax.persistence.Transient;
-import javax.persistence.UniqueConstraint;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.JsonMapUserType;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
 
 /**
  * Persistence entity representing type of experiment.
@@ -42,6 +38,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
  */
 @Entity
 @Table(name = TableNames.EXPERIMENT_TYPES_TABLE, uniqueConstraints = { @UniqueConstraint(columnNames = { ColumnNames.CODE_COLUMN }) })
+@TypeDefs({ @TypeDef(name = "JsonMap", typeClass = JsonMapUserType.class) })
 public final class ExperimentTypePE extends EntityTypePE
 {
     private static final long serialVersionUID = IServer.VERSION;
@@ -49,6 +46,8 @@ public final class ExperimentTypePE extends EntityTypePE
     private Set<ExperimentTypePropertyTypePE> exerimentTypePropertyTypes =
             new HashSet<ExperimentTypePropertyTypePE>();
 
+    private Map<String, String> metaData;
+
     @Override
     @SequenceGenerator(name = SequenceNames.EXPERIMENT_TYPE_SEQUENCE, sequenceName = SequenceNames.EXPERIMENT_TYPE_SEQUENCE, allocationSize = 1)
     @Id
@@ -113,4 +112,16 @@ public final class ExperimentTypePE extends EntityTypePE
         return getExperimentTypePropertyTypes();
     }
 
+    @Column(name = "meta_data")
+    @Type(type = "JsonMap")
+    public Map<String, String> getMetaData()
+    {
+        return metaData;
+    }
+
+    public void setMetaData(Map<String, String> metaData)
+    {
+        this.metaData = metaData;
+    }
+
 }
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTranslator.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTranslator.java
index f321a8218eb5f77f2f1dabd35df0a4c4038764c7..feeeaa8efd297c0274aa36d2f9a682b4d03762f6 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTranslator.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTranslator.java
@@ -144,6 +144,7 @@ public final class ExperimentTranslator
         result.setModifier(PersonTranslator.translate(experiment.getModifier()));
         result.setDeletion(DeletionTranslator.translate(experiment.getDeletion()));
         result.setVersion(experiment.getVersion());
+        result.setMetaData(experiment.getMetaData());
         for (final LoadableFields field : withFields)
         {
             switch (field)
diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTypeTranslator.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTypeTranslator.java
index e3fcfd28cfecd0809e0d4a7a8ec856b5299356f1..2e1fd0670de19d6e9f9d081d84537890be4224dc 100644
--- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTypeTranslator.java
+++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/ExperimentTypeTranslator.java
@@ -47,6 +47,7 @@ public class ExperimentTypeTranslator
         result.setModificationDate(experimentTypePE.getModificationDate());
         result.setValidationScript(ScriptTranslator.translate(experimentTypePE
                 .getValidationScript()));
+        result.setMetaData(experimentTypePE.getMetaData());
         return result;
     }
 
diff --git a/server-application-server/source/sql/generic/192/schema-192.sql b/server-application-server/source/sql/generic/192/schema-192.sql
index 0b7f7daca45152ebc8931217f4217c67d7151068..a36235c47cf8fd5c3e03bec2193a5f60e944dac7 100644
--- a/server-application-server/source/sql/generic/192/schema-192.sql
+++ b/server-application-server/source/sql/generic/192/schema-192.sql
@@ -10,12 +10,12 @@ CREATE TABLE DATA_STORE_SERVICE_DATA_SET_TYPES (DATA_STORE_SERVICE_ID TECH_ID NO
 CREATE TABLE DATA_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000 NOT NULL);
 CREATE TABLE EVENTS (ID TECH_ID NOT NULL,EVENT_TYPE EVENT_TYPE NOT NULL,DESCRIPTION TEXT_VALUE,REASON DESCRIPTION_2000,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, entity_type VARCHAR(80) NOT NULL, identifiers TEXT_VALUE NOT NULL, CONTENT TEXT_VALUE, EXAC_ID TECH_ID);
 CREATE TABLE EVENTS_SEARCH (ID TECH_ID NOT NULL, EVENT_TYPE EVENT_TYPE NOT NULL, ENTITY_TYPE TEXT_VALUE NOT NULL, ENTITY_SPACE TEXT_VALUE, ENTITY_SPACE_PERM_ID TEXT_VALUE, ENTITY_PROJECT TEXT_VALUE, ENTITY_PROJECT_PERM_ID TEXT_VALUE, ENTITY_REGISTERER TEXT_VALUE, ENTITY_REGISTRATION_TIMESTAMP TIME_STAMP, IDENTIFIER TEXT_VALUE NOT NULL, DESCRIPTION TEXT_VALUE, REASON TEXT_VALUE, CONTENT TEXT_VALUE, EXAC_ID TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP NOT NULL);
-CREATE TABLE EXPERIMENTS_ALL (ID TECH_ID NOT NULL,PERM_ID CODE NOT NULL,CODE CODE NOT NULL,EXTY_ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PROJ_ID TECH_ID NOT NULL,DEL_ID TECH_ID, ORIG_DEL TECH_ID, IS_PUBLIC BOOLEAN_CHAR NOT NULL DEFAULT 'F', PERS_ID_MODIFIER TECH_ID, VERSION INTEGER DEFAULT 0, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_SAMP BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_DATA BOOLEAN_CHAR NOT NULL DEFAULT 'F', PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL);
+CREATE TABLE EXPERIMENTS_ALL (ID TECH_ID NOT NULL,PERM_ID CODE NOT NULL,CODE CODE NOT NULL,EXTY_ID TECH_ID NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, PROJ_ID TECH_ID NOT NULL,DEL_ID TECH_ID, ORIG_DEL TECH_ID, IS_PUBLIC BOOLEAN_CHAR NOT NULL DEFAULT 'F', PERS_ID_MODIFIER TECH_ID, VERSION INTEGER DEFAULT 0, FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_SAMP BOOLEAN_CHAR NOT NULL DEFAULT 'F', FROZEN_FOR_DATA BOOLEAN_CHAR NOT NULL DEFAULT 'F', PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL, META_DATA JSONB);
 CREATE TABLE ATTACHMENTS (ID TECH_ID NOT NULL,EXPE_ID TECH_ID,SAMP_ID TECH_ID,PROJ_ID TECH_ID,EXAC_ID TECH_ID NOT NULL,FILE_NAME FILE_NAME NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP,VERSION INTEGER NOT NULL,PERS_ID_REGISTERER TECH_ID NOT NULL, title TITLE_100, description DESCRIPTION_2000, PROJ_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', SAMP_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F');
 CREATE TABLE ATTACHMENT_CONTENTS (ID TECH_ID NOT NULL,VALUE FILE NOT NULL);
 CREATE TABLE EXPERIMENT_PROPERTIES (ID TECH_ID NOT NULL,EXPE_ID TECH_ID NOT NULL,ETPT_ID TECH_ID NOT NULL,VALUE TEXT_VALUE, CVTE_ID TECH_ID, MATE_PROP_ID TECH_ID, SAMP_PROP_ID TECH_ID, PERS_ID_REGISTERER TECH_ID NOT NULL, REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, PERS_ID_AUTHOR TECH_ID NOT NULL, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, EXPE_FROZEN BOOLEAN_CHAR NOT NULL DEFAULT 'F', TSVECTOR_DOCUMENT TSVECTOR NOT NULL, IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
 CREATE TABLE EXPERIMENT_PROPERTIES_HISTORY (ID TECH_ID NOT NULL, EXPE_ID TECH_ID NOT NULL, ETPT_ID TECH_ID NOT NULL, VALUE TEXT_VALUE, VOCABULARY_TERM IDENTIFIER, MATERIAL IDENTIFIER, SAMPLE IDENTIFIER, PERS_ID_AUTHOR TECH_ID NOT NULL, VALID_FROM_TIMESTAMP TIME_STAMP NOT NULL, VALID_UNTIL_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, INTEGER_ARRAY_VALUE LONG_VALUE[], REAL_ARRAY_VALUE DOUBLE_VALUE[], STRING_ARRAY_VALUE TEXT_VALUE[], TIMESTAMP_ARRAY_VALUE TIME_STAMP[], JSON_VALUE JSONB);
-CREATE TABLE EXPERIMENT_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, VALIDATION_SCRIPT_ID TECH_ID);
+CREATE TABLE EXPERIMENT_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000, MODIFICATION_TIMESTAMP TIME_STAMP DEFAULT CURRENT_TIMESTAMP, VALIDATION_SCRIPT_ID TECH_ID, META_DATA JSONB);
 CREATE TABLE EXPERIMENT_TYPE_PROPERTY_TYPES (ID TECH_ID NOT NULL,EXTY_ID TECH_ID NOT NULL,PRTY_ID TECH_ID NOT NULL,IS_MANDATORY BOOLEAN_CHAR NOT NULL DEFAULT 'F',IS_MANAGED_INTERNALLY BOOLEAN_CHAR NOT NULL DEFAULT 'F',PERS_ID_REGISTERER TECH_ID NOT NULL,REGISTRATION_TIMESTAMP TIME_STAMP_DFL NOT NULL DEFAULT CURRENT_TIMESTAMP, ORDINAL ORDINAL_INT NOT NULL, SECTION DESCRIPTION_2000,SCRIPT_ID TECH_ID,IS_SHOWN_EDIT BOOLEAN_CHAR NOT NULL DEFAULT 'T',SHOW_RAW_VALUE BOOLEAN_CHAR NOT NULL DEFAULT 'F', IS_UNIQUE BOOLEAN_CHAR NOT NULL DEFAULT 'F');
 CREATE TABLE EXTERNAL_DATA (ID TECH_ID NOT NULL,SHARE_ID CODE,SIZE ORDINAL_INT,LOCATION VARCHAR(1024) NOT NULL,FFTY_ID TECH_ID NOT NULL,LOTY_ID TECH_ID NOT NULL,CVTE_ID_STOR_FMT TECH_ID NOT NULL,IS_COMPLETE BOOLEAN_CHAR_OR_UNKNOWN NOT NULL DEFAULT 'U',CVTE_ID_STORE TECH_ID, STATUS ARCHIVING_STATUS NOT NULL DEFAULT 'AVAILABLE', PRESENT_IN_ARCHIVE BOOLEAN_CHAR DEFAULT 'F', SPEED_HINT INTEGER NOT NULL DEFAULT -50, STORAGE_CONFIRMATION BOOLEAN_CHAR NOT NULL DEFAULT 'F', H5_FOLDERS BOOLEAN_CHAR NOT NULL, H5AR_FOLDERS BOOLEAN_CHAR NOT NULL, ARCHIVING_REQUESTED BOOLEAN_CHAR NOT NULL DEFAULT 'F');
 CREATE TABLE FILE_FORMAT_TYPES (ID TECH_ID NOT NULL,CODE CODE NOT NULL,DESCRIPTION DESCRIPTION_2000);
@@ -142,7 +142,7 @@ CREATE VIEW data_deleted AS
 
 CREATE VIEW experiments AS
      SELECT id, perm_id, code, exty_id, pers_id_registerer, pers_id_modifier, registration_timestamp, modification_timestamp, 
-            proj_id, proj_frozen, del_id, orig_del, is_public, version, frozen, frozen_for_samp, frozen_for_data, tsvector_document
+            proj_id, proj_frozen, del_id, orig_del, is_public, version, frozen, frozen_for_samp, frozen_for_data, tsvector_document, meta_data
        FROM experiments_all 
       WHERE del_id IS NULL;
 
diff --git a/server-application-server/source/sql/postgresql/192/function-192.sql b/server-application-server/source/sql/postgresql/192/function-192.sql
index 1839d904dbb232be4284f6668a2409431848f554..4245d2128177b4bcc83de68ca78d562873cb5dd5 100644
--- a/server-application-server/source/sql/postgresql/192/function-192.sql
+++ b/server-application-server/source/sql/postgresql/192/function-192.sql
@@ -713,7 +713,8 @@ CREATE OR REPLACE RULE experiment_insert AS
        proj_id,
        proj_frozen,
        registration_timestamp,
-       version
+       version,
+       meta_data
      ) VALUES (
        NEW.id,
        NEW.frozen,
@@ -731,7 +732,8 @@ CREATE OR REPLACE RULE experiment_insert AS
        NEW.proj_id,
        NEW.proj_frozen,
        NEW.registration_timestamp,
-       NEW.version
+       NEW.version,
+       NEW.meta_data
      );
 
 CREATE OR REPLACE RULE experiment_update AS
@@ -752,7 +754,8 @@ CREATE OR REPLACE RULE experiment_update AS
               proj_id = NEW.proj_id,
               proj_frozen = NEW.proj_frozen,
               registration_timestamp = NEW.registration_timestamp,
-              version = NEW.version
+              version = NEW.version,
+              meta_data = NEW.meta_data
           WHERE id = NEW.id;
 
 CREATE OR REPLACE RULE experiment_delete AS
diff --git a/server-application-server/source/sql/postgresql/migration/migration-191-192.sql b/server-application-server/source/sql/postgresql/migration/migration-191-192.sql
index 6f74d1ec943c2cf269c315b3bbf4d5b1a006585b..e3d5e405e95a7d1ef35b705f39d21dfdb4055983 100644
--- a/server-application-server/source/sql/postgresql/migration/migration-191-192.sql
+++ b/server-application-server/source/sql/postgresql/migration/migration-191-192.sql
@@ -16,6 +16,19 @@ CREATE OR REPLACE VIEW samples AS
      WHERE del_id IS NULL;
 
 
+ALTER TABLE IF EXISTS EXPERIMENTS_ALL
+    ADD COLUMN META_DATA jsonb;
+
+ALTER TABLE IF EXISTS EXPERIMENT_TYPES
+    ADD COLUMN META_DATA jsonb;
+
+CREATE OR REPLACE VIEW experiments AS
+     SELECT id, perm_id, code, exty_id, pers_id_registerer, pers_id_modifier, registration_timestamp, modification_timestamp,
+            proj_id, proj_frozen, del_id, orig_del, is_public, version, frozen, frozen_for_samp, frozen_for_data, tsvector_document, meta_data
+       FROM experiments_all
+      WHERE del_id IS NULL;
+
+
 -- function
 
 CREATE OR REPLACE RULE sample_insert AS
@@ -102,3 +115,68 @@ CREATE OR REPLACE RULE sample_update AS
               version = NEW.version,
               meta_data = NEW.meta_data
           WHERE id = NEW.id;
+
+
+CREATE OR REPLACE RULE experiment_insert AS
+  ON INSERT TO experiments DO INSTEAD
+     INSERT INTO experiments_all (
+       id,
+       frozen,
+       frozen_for_samp,
+       frozen_for_data,
+       code,
+       del_id,
+       orig_del,
+       exty_id,
+       is_public,
+       modification_timestamp,
+       perm_id,
+       pers_id_registerer,
+       pers_id_modifier,
+       proj_id,
+       proj_frozen,
+       registration_timestamp,
+       version,
+       meta_data
+     ) VALUES (
+       NEW.id,
+       NEW.frozen,
+       NEW.frozen_for_samp,
+       NEW.frozen_for_data,
+       NEW.code,
+       NEW.del_id,
+       NEW.orig_del,
+       NEW.exty_id,
+       NEW.is_public,
+       NEW.modification_timestamp,
+       NEW.perm_id,
+       NEW.pers_id_registerer,
+       NEW.pers_id_modifier,
+       NEW.proj_id,
+       NEW.proj_frozen,
+       NEW.registration_timestamp,
+       NEW.version,
+       NEW.meta_data
+     );
+
+CREATE OR REPLACE RULE experiment_update AS
+    ON UPDATE TO experiments DO INSTEAD
+       UPDATE experiments_all
+          SET code = NEW.code,
+              frozen = NEW.frozen,
+              frozen_for_samp = NEW.frozen_for_samp,
+              frozen_for_data = NEW.frozen_for_data,
+              del_id = NEW.del_id,
+              orig_del = NEW.orig_del,
+              exty_id = NEW.exty_id,
+              is_public = NEW.is_public,
+              modification_timestamp = NEW.modification_timestamp,
+              perm_id = NEW.perm_id,
+              pers_id_registerer = NEW.pers_id_registerer,
+              pers_id_modifier = NEW.pers_id_modifier,
+              proj_id = NEW.proj_id,
+              proj_frozen = NEW.proj_frozen,
+              registration_timestamp = NEW.registration_timestamp,
+              version = NEW.version,
+              meta_data = NEW.meta_data
+          WHERE id = NEW.id;