You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2022/02/15 16:30:39 UTC

[unomi] branch UNOMI-486-json-schema-graphql created (now 9f0e07d)

This is an automated email from the ASF dual-hosted git repository.

shuber pushed a change to branch UNOMI-486-json-schema-graphql
in repository https://gitbox.apache.org/repos/asf/unomi.git.


      at 9f0e07d  JSON Schema GraphQL integration

This branch includes the following new commits:

     new 9f0e07d  JSON Schema GraphQL integration

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[unomi] 01/01: JSON Schema GraphQL integration

Posted by sh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

shuber pushed a commit to branch UNOMI-486-json-schema-graphql
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 9f0e07d2aedd48dbb0898dc4a8421c93cef19a9b
Author: Serge Huber <sh...@jahia.com>
AuthorDate: Tue Feb 15 17:30:32 2022 +0100

    JSON Schema GraphQL integration
---
 .../main/java/org/apache/unomi/api/EventType.java  |  73 ------
 .../main/java/org/apache/unomi/api/SchemaType.java |  60 -----
 .../json/JSONArrayType.java}                       |  19 +-
 .../json/JSONBooleanType.java}                     |  20 +-
 .../json/JSONEnumType.java}                        |  20 +-
 .../json/JSONIntegerType.java}                     |  20 +-
 .../json/JSONNullType.java}                        |  20 +-
 .../json/JSONNumberType.java}                      |  20 +-
 .../unomi/api/schema/json/JSONObjectType.java      |  52 ++++
 .../apache/unomi/api/schema/json/JSONSchema.java   | 107 +++++++++
 .../json/JSONStringType.java}                      |  20 +-
 .../org/apache/unomi/api/schema/json/JSONType.java | 111 +++++++++
 .../unomi/api/schema/json/JSONTypeFactory.java     |  91 +++++++
 .../apache/unomi/api/services/EventService.java    |  16 +-
 .../unomi/api/services/EventTypeRegistry.java      |  59 -----
 .../apache/unomi/api/services/SchemaRegistry.java  |  11 +-
 .../graphql/schema/GraphQLSchemaProvider.java      | 198 +++++++++++-----
 .../unomi/graphql/schema/GraphQLSchemaUpdater.java |  10 +-
 .../unomi/graphql/schema/PropertyFilterUtils.java  |  26 +-
 .../types/resolvers/CDPEventInterfaceResolver.java |  12 +-
 .../org/apache/unomi/itests/ContextServletIT.java  | 105 +++------
 .../schemas/events/float-property-type.json        |  21 ++
 .../resources/schemas/events/test-event-type.json  |  13 +
 .../unomi/rest/endpoints/EventServiceEndpoint.java |  12 -
 .../services/impl/events/EventServiceImpl.java     |  19 +-
 .../impl/events/EventTypeRegistryImpl.java         | 261 ---------------------
 .../services/impl/schemas/SchemaRegistryImpl.java  |  92 +++++---
 .../resources/META-INF/cxs/schemas/condition.json  |   2 +-
 .../META-INF/cxs/schemas/conditiontype.json        |   6 +-
 .../resources/META-INF/cxs/schemas/consent.json    |   2 +-
 .../META-INF/cxs/schemas/consentType.json          |   2 +-
 .../resources/META-INF/cxs/schemas/customitem.json |   4 +-
 .../META-INF/cxs/schemas/customitems/page.json     |  13 +-
 .../META-INF/cxs/schemas/customitems/site.json     |  11 +-
 .../main/resources/META-INF/cxs/schemas/event.json |   4 +-
 .../META-INF/cxs/schemas/events/modifyConsent.json |  22 +-
 .../META-INF/cxs/schemas/events/view.json          |  17 +-
 .../main/resources/META-INF/cxs/schemas/goal.json  |   8 +-
 .../main/resources/META-INF/cxs/schemas/item.json  |   2 +-
 .../resources/META-INF/cxs/schemas/metadata.json   |   2 +-
 .../META-INF/cxs/schemas/metadataitem.json         |   6 +-
 .../resources/META-INF/cxs/schemas/parameter.json  |   2 +-
 .../resources/META-INF/cxs/schemas/profile.json    |   4 +-
 .../resources/META-INF/cxs/schemas/session.json    |   6 +-
 .../META-INF/cxs/schemas/timestampeditem.json      |   4 +-
 .../META-INF/cxs/schemas/values/boolean.json       |   2 +-
 .../META-INF/cxs/schemas/values/date.json          |   2 +-
 .../META-INF/cxs/schemas/values/email.json         |   2 +-
 .../META-INF/cxs/schemas/values/integer.json       |   2 +-
 .../META-INF/cxs/schemas/values/long.json          |   2 +-
 .../resources/META-INF/cxs/schemas/values/set.json |   2 +-
 .../META-INF/cxs/schemas/values/string.json        |   2 +-
 .../resources/OSGI-INF/blueprint/blueprint.xml     |   7 -
 53 files changed, 792 insertions(+), 834 deletions(-)

diff --git a/api/src/main/java/org/apache/unomi/api/EventType.java b/api/src/main/java/org/apache/unomi/api/EventType.java
deleted file mode 100644
index 5ae05b8..0000000
--- a/api/src/main/java/org/apache/unomi/api/EventType.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.unomi.api;
-
-import java.util.Set;
-
-/**
- * An event type definition, used to define the structure of accepted events
- */
-public class EventType implements PluginType {
-
-    private String type;
-
-    private Set<PropertyType> propertyTypes;
-
-    private long pluginId;
-
-    public EventType() {
-    }
-
-    public EventType(String type, Set<PropertyType> propertyTypes, long pluginId) {
-        this.type = type;
-        this.propertyTypes = propertyTypes;
-        this.pluginId = pluginId;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public Set<PropertyType> getPropertyTypes() {
-        return propertyTypes;
-    }
-
-    public void setPropertyTypes(Set<PropertyType> propertyTypes) {
-        this.propertyTypes = propertyTypes;
-    }
-
-    @Override
-    public long getPluginId() {
-        return pluginId;
-    }
-
-    @Override
-    public void setPluginId(long pluginId) {
-        this.pluginId = pluginId;
-    }
-
-    public void merge(final EventType source) {
-        if (source == null || source.getPropertyTypes() == null || source.getPropertyTypes().isEmpty()) {
-            return;
-        }
-        this.propertyTypes.addAll(source.getPropertyTypes());
-    }
-}
diff --git a/api/src/main/java/org/apache/unomi/api/SchemaType.java b/api/src/main/java/org/apache/unomi/api/SchemaType.java
deleted file mode 100644
index a3bd37a..0000000
--- a/api/src/main/java/org/apache/unomi/api/SchemaType.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.unomi.api;
-
-import java.util.Map;
-
-public class SchemaType implements PluginType {
-
-    private transient long pluginId;
-    private String schemaId;
-    private String target;
-    private Map<String,Object> schemaTree;
-
-    public long getPluginId() {
-        return pluginId;
-    }
-
-    public void setPluginId(long pluginId) {
-        this.pluginId = pluginId;
-    }
-
-    public String getSchemaId() {
-        return schemaId;
-    }
-
-    public void setSchemaId(String schemaId) {
-        this.schemaId = schemaId;
-    }
-
-    public String getTarget() {
-        return target;
-    }
-
-    public void setTarget(String target) {
-        this.target = target;
-    }
-
-    public Map<String, Object> getSchemaTree() {
-        return schemaTree;
-    }
-
-    public void setSchemaTree(Map<String, Object> schemaTree) {
-        this.schemaTree = schemaTree;
-    }
-}
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java
similarity index 66%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java
index 03a234e..add106d 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java
@@ -14,19 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
-
-import org.apache.unomi.api.SchemaType;
+import org.apache.unomi.api.services.SchemaRegistry;
 
 import java.util.List;
+import java.util.Map;
 
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
+public class JSONArrayType extends JSONType {
 
-    List<SchemaType> getTargetSchemas(String target);
+    List<JSONType> items;
+    JSONType contains;
 
+    public JSONArrayType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("array");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java
similarity index 67%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java
index 03a234e..cfaa734 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONBooleanType extends JSONType {
+    public JSONBooleanType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("boolean");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java
similarity index 68%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java
index 03a234e..d2e18a0 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONEnumType extends JSONType {
+    public JSONEnumType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("enum");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java
similarity index 67%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java
index 03a234e..6aa9a32 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONIntegerType extends JSONType {
+    public JSONIntegerType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("integer");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java
similarity index 68%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java
index 03a234e..ec0adde 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONNullType extends JSONType {
+    public JSONNullType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("null");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java
similarity index 67%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java
index 03a234e..bb6bf13 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONNumberType extends JSONType {
+    public JSONNumberType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("number");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java
new file mode 100644
index 0000000..45b25e0
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.unomi.api.schema.json;
+
+import org.apache.unomi.api.services.SchemaRegistry;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JSONObjectType extends JSONType {
+
+    Map<String,List<JSONType>> properties = new HashMap<>();
+    JSONType additionalProperties;
+    Map<String,List<JSONType>> patternProperties = new HashMap<>();
+    JSONType propertyNames;
+
+    int maxProperties;
+
+    public JSONObjectType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("object");
+        Map<String,Object> propertiesTree = (Map<String,Object>) schemaTree.get("properties");
+        if (propertiesTree != null) {
+            propertiesTree.entrySet().forEach(entry -> {
+                properties.put(entry.getKey(), jsonTypeFactory.getTypes((Map<String,Object>)entry.getValue()));
+            });
+        }
+    }
+
+    public Map<String,List<JSONType>> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String,List<JSONType>> properties) {
+        this.properties = properties;
+    }
+}
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java
new file mode 100644
index 0000000..544d009
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.unomi.api.schema.json;
+
+import org.apache.unomi.api.PluginType;
+import org.apache.unomi.api.services.SchemaRegistry;
+
+import java.util.List;
+import java.util.Map;
+
+public class JSONSchema extends JSONType implements PluginType {
+
+    private transient long pluginId;
+    private String schemaId;
+    private String target;
+    private List<JSONType> rootTypes;
+
+    private String vendor;
+    private String name;
+    private String version;
+
+    public JSONSchema(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        schemaId = (String) schemaTree.get("$id");
+        if (schemaTree.containsKey("self")) {
+            Map<String,Object> self = (Map<String,Object>) schemaTree.get("self");
+            name = (String) self.get("name");
+            vendor = (String) self.get("vendor");
+            version = (String) self.get("version");
+            target = (String) self.get("target");
+        }
+    }
+
+    public String getVendor() {
+        return vendor;
+    }
+
+    public void setVendor(String vendor) {
+        this.vendor = vendor;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public long getPluginId() {
+        return pluginId;
+    }
+
+    public void setPluginId(long pluginId) {
+        this.pluginId = pluginId;
+    }
+
+    public String getSchemaId() {
+        return schemaId;
+    }
+
+    public void setSchemaId(String schemaId) {
+        this.schemaId = schemaId;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    public void setTarget(String target) {
+        this.target = target;
+    }
+
+    public List<JSONType> getRootTypes() {
+        if (rootTypes == null) {
+            buildRootTypes();
+        }
+        return rootTypes;
+    }
+
+    private void buildRootTypes() {
+        rootTypes = jsonTypeFactory.getTypes(schemaTree);
+    }
+}
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java
similarity index 67%
copy from api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
copy to api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java
index 03a234e..c1b9c10 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.unomi.api.schema.json;
 
-package org.apache.unomi.api.services;
+import org.apache.unomi.api.services.SchemaRegistry;
 
-import org.apache.unomi.api.SchemaType;
-
-import java.util.List;
-
-public interface SchemaRegistry {
-
-    boolean isValid(Object object, String schemaId);
-
-    SchemaType getSchema(String schemaId);
-
-    List<SchemaType> getTargetSchemas(String target);
+import java.util.Map;
 
+public class JSONStringType extends JSONType {
+    public JSONStringType(Map<String, Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        super(schemaTree, jsonTypeFactory, schemaRegistry);
+        setType("string");
+    }
 }
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java
new file mode 100644
index 0000000..3b60b0f
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.unomi.api.schema.json;
+
+import org.apache.unomi.api.services.SchemaRegistry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class JSONType {
+
+    String type;
+    String name;
+    List<String> required;
+    String ref;
+    List<JSONType> anyOf;
+    List<JSONType> oneOf;
+
+    Map<String,Object> customKeywords;
+
+    protected Map<String,Object> schemaTree;
+
+    protected JSONTypeFactory jsonTypeFactory;
+
+    protected SchemaRegistry schemaRegistry;
+
+    public JSONType(Map<String,Object> schemaTree, JSONTypeFactory jsonTypeFactory, SchemaRegistry schemaRegistry) {
+        this.schemaTree = schemaTree;
+        this.jsonTypeFactory = jsonTypeFactory;
+        this.schemaRegistry = schemaRegistry;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Map<String, Object> getSchemaTree() {
+        return schemaTree;
+    }
+
+    public JSONTypeFactory getJsonTypeFactory() {
+        return jsonTypeFactory;
+    }
+
+    public SchemaRegistry getSchemaRegistry() {
+        return schemaRegistry;
+    }
+
+    public String getRef() {
+        ref = (String) schemaTree.get("$ref");
+        return ref;
+    }
+
+    public List<JSONType> getAllOf() {
+        List<Map<String,Object>> allOfTree = (List<Map<String,Object>>) schemaTree.get("allOf");
+        List<JSONType> allOfTypes = new ArrayList<>();
+        if (allOfTree != null) {
+            for (Map<String,Object> allOfEntry : allOfTree) {
+                List<JSONType> entryTypes = jsonTypeFactory.getTypes(allOfEntry);
+                allOfTypes.addAll(entryTypes);
+            }
+        }
+        return allOfTypes;
+    }
+
+    public List<JSONType> getAnyOf() {
+        return anyOf;
+    }
+
+    public List<JSONType> getOneOf() {
+        return oneOf;
+    }
+
+    public Map<String, Object> getCustomKeywords() {
+        return customKeywords;
+    }
+
+    public boolean merge(JSONType anotherType) {
+        if (!anotherType.getType().equals(getType())) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java b/api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java
new file mode 100644
index 0000000..da79016
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.unomi.api.schema.json;
+
+import org.apache.unomi.api.services.SchemaRegistry;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JSONTypeFactory {
+
+    Map<String, Class<? extends JSONType>> jsonTypes = new HashMap<>();
+
+    SchemaRegistry schemaRegistry;
+
+    public JSONTypeFactory(SchemaRegistry schemaRegistry) {
+        this.schemaRegistry = schemaRegistry;
+        jsonTypes.put("object", JSONObjectType.class);
+        jsonTypes.put("string", JSONStringType.class);
+        jsonTypes.put("array", JSONArrayType.class);
+        jsonTypes.put("number", JSONNumberType.class);
+        jsonTypes.put("integer", JSONIntegerType.class);
+        jsonTypes.put("boolean", JSONBooleanType.class);
+        jsonTypes.put("null", JSONNullType.class);
+    }
+
+    List<JSONType> getTypes(Map<String,Object> schemaTree) {
+        if (schemaTree.containsKey("$ref")) {
+            String schemaId = (String) schemaTree.get("$ref");
+            JSONSchema refSchema = schemaRegistry.getSchema(schemaId);
+            if (refSchema != null) {
+                schemaTree = refSchema.getSchemaTree();
+            } else {
+                System.err.println("Couldn't find schema for ref " + schemaId);
+            }
+        }
+        if (schemaTree.containsKey("enum")) {
+            List<JSONType> result = new ArrayList<>();
+            result.add(new JSONEnumType(schemaTree, this, schemaRegistry));
+            return result;
+        }
+        Object typeObject = schemaTree.get("type");
+        if (typeObject == null) {
+            return new ArrayList<>();
+        }
+        List<String> types = null;
+        if (typeObject instanceof String) {
+            types = new ArrayList<>();
+            types.add((String) typeObject);
+        } else {
+            types = (List<String>) typeObject;
+        }
+        List<JSONType> resultJsonTypes = new ArrayList<>();
+        for (String type : types) {
+            if (type == null) {
+                continue;
+            }
+            if (!jsonTypes.containsKey(type)) {
+                continue;
+            }
+            Class<? extends JSONType> typeClass = jsonTypes.get(type);
+            Constructor<? extends JSONType> constructor = null;
+            try {
+                constructor = typeClass.getConstructor(Map.class, JSONTypeFactory.class, SchemaRegistry.class);
+                resultJsonTypes.add(constructor.newInstance(schemaTree, this, schemaRegistry));
+            } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
+                e.printStackTrace();
+            }
+        }
+        return resultJsonTypes;
+    }
+
+}
diff --git a/api/src/main/java/org/apache/unomi/api/services/EventService.java b/api/src/main/java/org/apache/unomi/api/services/EventService.java
index c6136a3..4dde0a9 100644
--- a/api/src/main/java/org/apache/unomi/api/services/EventService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/EventService.java
@@ -19,7 +19,6 @@ package org.apache.unomi.api.services;
 
 import org.apache.unomi.api.Event;
 import org.apache.unomi.api.EventProperty;
-import org.apache.unomi.api.EventType;
 import org.apache.unomi.api.PartialList;
 import org.apache.unomi.api.Session;
 import org.apache.unomi.api.actions.ActionPostExecutor;
@@ -72,7 +71,7 @@ public interface EventService {
 
 
     /**
-     * Check if event fields complies with corresponding {@link EventType} definition
+     * Check if event fields complies with corresponding event JSON schema definition
      *
      * @param event        event to test
      * @return true if the event is valid
@@ -97,19 +96,6 @@ public interface EventService {
     List<EventProperty> getEventProperties();
 
     /**
-     * Retrieves an event type
-     * @param typeName the name identifier for the event type
-     * @return the EventType object corresponding to the name, or null if not found.
-     */
-    EventType getEventType(String typeName);
-
-    /**
-     * Registers event type
-     * @param eventType event type to register
-     */
-    void registerEventType(EventType eventType);
-
-    /**
      * Retrieves the set of known event type identifiers.
      *
      * @return the set of known event type identifiers.
diff --git a/api/src/main/java/org/apache/unomi/api/services/EventTypeRegistry.java b/api/src/main/java/org/apache/unomi/api/services/EventTypeRegistry.java
deleted file mode 100644
index c81668c..0000000
--- a/api/src/main/java/org/apache/unomi/api/services/EventTypeRegistry.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.unomi.api.services;
-
-import org.apache.unomi.api.Event;
-import org.apache.unomi.api.EventType;
-
-import java.util.Collection;
-
-/**
- * An event types registry service.
- */
-public interface EventTypeRegistry {
-
-    /**
-     * Retrieve event type definition
-     *
-     * @param typeName name of the event type
-     * @return {@link EventType} definition
-     */
-    EventType get(String typeName);
-
-    /**
-     * Adds event type definition to registry
-     *
-     * @param eventType {@link EventType} definition
-     */
-    void register(EventType eventType);
-
-    /**
-     * Checks if event complies with {@link EventType} definition
-     *
-     * @param event the event to validate
-     * @return result of validation
-     */
-    boolean isValid(Event event);
-
-    /**
-     * List all known event types
-     *
-     * @return Lists all known {@link EventType}s
-     */
-    Collection<EventType> getAll();
-}
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java b/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
index 03a234e..1bdea07 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
+++ b/api/src/main/java/org/apache/unomi/api/services/SchemaRegistry.java
@@ -17,16 +17,21 @@
 
 package org.apache.unomi.api.services;
 
-import org.apache.unomi.api.SchemaType;
+import org.apache.unomi.api.schema.json.JSONSchema;
 
+import java.io.InputStream;
 import java.util.List;
 
 public interface SchemaRegistry {
 
     boolean isValid(Object object, String schemaId);
 
-    SchemaType getSchema(String schemaId);
+    JSONSchema getSchema(String schemaId);
 
-    List<SchemaType> getTargetSchemas(String target);
+    List<JSONSchema> getTargetSchemas(String target);
+
+    String registerSchema(String target, InputStream jsonSchemaInputStream);
+
+    boolean unregisterSchema(String target, String schemaId);
 
 }
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
index 1f2d9bb..38358d0 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
@@ -33,10 +33,12 @@ import graphql.schema.GraphQLOutputType;
 import graphql.schema.GraphQLSchema;
 import graphql.schema.GraphQLType;
 import graphql.schema.visibility.GraphqlFieldVisibility;
-import org.apache.unomi.api.EventType;
 import org.apache.unomi.api.PropertyType;
-import org.apache.unomi.api.services.EventTypeRegistry;
+import org.apache.unomi.api.schema.json.JSONObjectType;
+import org.apache.unomi.api.schema.json.JSONSchema;
+import org.apache.unomi.api.schema.json.JSONType;
 import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.api.services.SchemaRegistry;
 import org.apache.unomi.graphql.CDPGraphQLConstants;
 import org.apache.unomi.graphql.converters.UnomiToGraphQLConverter;
 import org.apache.unomi.graphql.fetchers.CustomEventOrSetPropertyDataFetcher;
@@ -72,13 +74,7 @@ import org.apache.unomi.graphql.utils.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static graphql.schema.FieldCoordinates.coordinates;
@@ -92,7 +88,7 @@ public class GraphQLSchemaProvider {
 
     private final ProfileService profileService;
 
-    private final EventTypeRegistry eventTypeRegistry;
+    private final SchemaRegistry schemaRegistry;
 
     private final List<GraphQLTypeFunctionProvider> typeFunctionProviders;
 
@@ -116,9 +112,83 @@ public class GraphQLSchemaProvider {
 
     private Set<Class<?>> additionalTypes = new HashSet<>();
 
+    public interface DefinitionType {
+        String getTypeId();
+        String getName();
+        boolean hasSubTypes();
+        List<DefinitionType> getSubTypes();
+    }
+
+    public class PropertyTypeDefinitionType implements DefinitionType {
+
+        private PropertyType propertyType;
+
+        public PropertyTypeDefinitionType(PropertyType propertyType) {
+            this.propertyType = propertyType;
+        }
+
+        @Override
+        public String getTypeId() {
+            return propertyType.getValueTypeId();
+        }
+
+        @Override
+        public String getName() {
+            return propertyType.getItemId();
+        }
+
+        @Override
+        public boolean hasSubTypes() {
+            return "set".equals(propertyType.getValueTypeId());
+        }
+
+        @Override
+        public List<DefinitionType> getSubTypes() {
+            return propertyType.getChildPropertyTypes().stream().map(PropertyTypeDefinitionType::new).collect(Collectors.toList());
+        }
+    }
+
+    public class JSONTypeDefinitionType implements DefinitionType {
+        private List<JSONType> jsonTypes;
+        private JSONType firstNonNullType;
+        private String name;
+
+        public JSONTypeDefinitionType(String name, List<JSONType> jsonTypes) {
+            this.name = name;
+            this.jsonTypes = jsonTypes;
+            Optional<JSONType> firstNonNullType = jsonTypes.stream().filter(jsonType -> !"null".equals(jsonType.getType())).findFirst();
+            if (firstNonNullType.isPresent()) {
+                this.firstNonNullType = firstNonNullType.get();
+            }
+        }
+
+        @Override
+        public String getTypeId() {
+            return firstNonNullType.getType();
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public boolean hasSubTypes() {
+            return firstNonNullType instanceof JSONObjectType && ((JSONObjectType) firstNonNullType).getProperties() != null;
+        }
+
+        @Override
+        public List<DefinitionType> getSubTypes() {
+            if (!hasSubTypes()) {
+                return new ArrayList<>();
+            }
+            return ((JSONObjectType) firstNonNullType).getProperties().entrySet().stream().map(entry -> new JSONTypeDefinitionType(entry.getKey(), entry.getValue())).collect(Collectors.toList());
+        }
+    }
+
     private GraphQLSchemaProvider(final Builder builder) {
         this.profileService = builder.profileService;
-        this.eventTypeRegistry = builder.eventTypeRegistry;
+        this.schemaRegistry = builder.schemaRegistry;
         this.eventPublisher = builder.eventPublisher;
         this.typeFunctionProviders = builder.typeFunctionProviders;
         this.extensionsProviders = builder.extensionsProviders;
@@ -238,20 +308,21 @@ public class GraphQLSchemaProvider {
             }
         }
 
-        final Collection<PropertyType> propertyTypes = profileService.getTargetPropertyTypes("profiles");
+        final Collection<PropertyType> profilePropertyTypes = profileService.getTargetPropertyTypes("profiles");
+        final Collection<DefinitionType> profileDefinitionTypes = profilePropertyTypes.stream().map(PropertyTypeDefinitionType::new).collect(Collectors.toList());
 
         // Profile
-        registerDynamicInputFilterFields(CDPProfilePropertiesFilterInput.TYPE_NAME, CDPProfilePropertiesFilterInput.class, propertyTypes);
-        registerDynamicInputFilterFields(CDPProfileUpdateEventFilterInput.TYPE_NAME, CDPProfileUpdateEventFilterInput.class, propertyTypes);
-        registerDynamicInputFields(CDPProfileUpdateEventInput.TYPE_NAME, CDPProfileUpdateEventInput.class, propertyTypes);
+        registerDynamicInputFilterFields(CDPProfilePropertiesFilterInput.TYPE_NAME, CDPProfilePropertiesFilterInput.class, profileDefinitionTypes);
+        registerDynamicInputFilterFields(CDPProfileUpdateEventFilterInput.TYPE_NAME, CDPProfileUpdateEventFilterInput.class, profileDefinitionTypes);
+        registerDynamicInputFields(CDPProfileUpdateEventInput.TYPE_NAME, CDPProfileUpdateEventInput.class, profileDefinitionTypes);
         registerDynamicEventFilterInputFields();
 
         // Profile
-        registerDynamicOutputFields(CDPProfile.TYPE_NAME, CDPProfile.class, CustomerPropertyDataFetcher.class, propertyTypes);
+        registerDynamicOutputFields(CDPProfile.TYPE_NAME, CDPProfile.class, CustomerPropertyDataFetcher.class, profileDefinitionTypes);
 
         // Persona
-        registerDynamicInputFields(CDPPersonaInput.TYPE_NAME, CDPPersonaInput.class, propertyTypes);
-        registerDynamicOutputFields(CDPPersona.TYPE_NAME, CDPPersona.class, CustomerPropertyDataFetcher.class, propertyTypes);
+        registerDynamicInputFields(CDPPersonaInput.TYPE_NAME, CDPPersonaInput.class, profileDefinitionTypes);
+        registerDynamicOutputFields(CDPPersona.TYPE_NAME, CDPPersona.class, CustomerPropertyDataFetcher.class, profileDefinitionTypes);
 
         // Events
         registerDynamicUnomiInputEvents(schemaBuilder);
@@ -260,18 +331,18 @@ public class GraphQLSchemaProvider {
     }
 
     private void registerDynamicUnomiInputEvents(GraphQLSchema.Builder schemaBuilder) {
-        final Collection<EventType> unomiEventTypes = eventTypeRegistry.getAll();
+        final List<JSONSchema> unomiEventTypes = schemaRegistry.getTargetSchemas("events");
 
         if (!unomiEventTypes.isEmpty()) {
-            for (EventType unomiEventType : unomiEventTypes) {
-                final String typeName = UnomiToGraphQLConverter.convertEventType(unomiEventType.getType()) + "Input";
+            for (JSONSchema unomiEventType : unomiEventTypes) {
+                final String typeName = UnomiToGraphQLConverter.convertEventType(unomiEventType.getName()) + "Input";
 
                 final GraphQLInputObjectType objectType;
                 if (!graphQLAnnotations.getContainer().getTypeRegistry().containsKey(typeName)) {
-                    objectType = createDynamicEventInputType(unomiEventType);
+                    objectType = createDynamicEventInputType(new JSONTypeDefinitionType(unomiEventType.getName(), unomiEventType.getRootTypes()));
                 } else {
                     objectType = (GraphQLInputObjectType) getFromTypeRegistry(typeName);
-                    registerDynamicInputFields(typeName, objectType, unomiEventType.getPropertyTypes());
+                    registerDynamicInputFields(typeName, objectType, new JSONTypeDefinitionType(unomiEventType.getName(), unomiEventType.getRootTypes()).getSubTypes());
                 }
 
                 if (objectType != null) {
@@ -282,20 +353,20 @@ public class GraphQLSchemaProvider {
     }
 
     private void registerDynamicUnomiOutputEvents(GraphQLSchema.Builder schemaBuilder) {
-        final Collection<EventType> unomiEventTypes = eventTypeRegistry.getAll();
+        final List<JSONSchema> unomiEventTypes = schemaRegistry.getTargetSchemas("events");
 
         if (!unomiEventTypes.isEmpty()) {
             final GraphQLCodeRegistry.Builder codeRegisterBuilder = graphQLAnnotations.getContainer().getCodeRegistryBuilder();
 
-            for (EventType unomiEventType : unomiEventTypes) {
-                final String typeName = UnomiToGraphQLConverter.convertEventType(unomiEventType.getType());
+            for (JSONSchema unomiEventType : unomiEventTypes) {
+                final String typeName = UnomiToGraphQLConverter.convertEventType(unomiEventType.getSchemaId());
 
                 final GraphQLObjectType objectType;
                 if (!graphQLAnnotations.getContainer().getTypeRegistry().containsKey(typeName)) {
-                    objectType = createDynamicEventOutputType(unomiEventType, codeRegisterBuilder);
+                    objectType = createDynamicEventOutputType(new JSONTypeDefinitionType(unomiEventType.getName(), unomiEventType.getRootTypes()), codeRegisterBuilder);
                 } else {
                     objectType = (GraphQLObjectType) getFromTypeRegistry(typeName);
-                    registerDynamicOutputFields(typeName, objectType, CustomerPropertyDataFetcher.class, unomiEventType.getPropertyTypes());
+                    registerDynamicOutputFields(typeName, objectType, CustomerPropertyDataFetcher.class, new JSONTypeDefinitionType(unomiEventType.getName(), unomiEventType.getRootTypes()).getSubTypes());
                 }
 
                 if (objectType != null) {
@@ -307,7 +378,7 @@ public class GraphQLSchemaProvider {
 
     private void registerDynamicInputFilterFields(final String typeName,
                                                   final Class<?> annotatedClass,
-                                                  final Collection<PropertyType> propertyTypes) {
+                                                  final Collection<DefinitionType> propertyTypes) {
         final GraphQLInputObjectType originalObject = getInputObjectType(annotatedClass);
 
         final List<GraphQLInputObjectField> inputObjectFields =
@@ -322,7 +393,7 @@ public class GraphQLSchemaProvider {
     private void registerDynamicOutputFields(final String graphQLTypeName,
                                              final Class<?> annotatedClass,
                                              final Class<? extends DynamicFieldDataFetcher> fetcherClass,
-                                             final Collection<PropertyType> propertyTypes) {
+                                             final Collection<DefinitionType> propertyTypes) {
         final GraphQLObjectType objectType = graphQLAnnotations.object(annotatedClass);
         registerDynamicOutputFields(graphQLTypeName, objectType, fetcherClass, propertyTypes);
     }
@@ -330,15 +401,15 @@ public class GraphQLSchemaProvider {
     private void registerDynamicOutputFields(final String graphQLTypeName,
                                              final GraphQLObjectType graphQLObjectType,
                                              final Class<? extends DynamicFieldDataFetcher> fetcherClass,
-                                             final Collection<PropertyType> propertyTypes) {
+                                             final Collection<DefinitionType> propertyTypes) {
         final GraphQLCodeRegistry.Builder codeRegisterBuilder = graphQLAnnotations.getContainer().getCodeRegistryBuilder();
 
         final List<GraphQLFieldDefinition> fieldDefinitions = new ArrayList<>();
 
         propertyTypes.forEach(propertyType -> {
-            final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getItemId());
+            final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getName());
 
-            if ("set".equals(propertyType.getValueTypeId())) {
+            if (propertyType.hasSubTypes()) {
                 final String typeName = StringUtils.capitalize(propertyName);
 
                 if (!graphQLAnnotations.getContainer().getTypeRegistry().containsKey(typeName)) {
@@ -355,12 +426,12 @@ public class GraphQLSchemaProvider {
                 }
             } else {
                 fieldDefinitions.add(GraphQLFieldDefinition.newFieldDefinition()
-                        .type((GraphQLOutputType) UnomiToGraphQLConverter.convertPropertyType(propertyType.getValueTypeId()))
+                        .type((GraphQLOutputType) UnomiToGraphQLConverter.convertPropertyType(propertyType.getTypeId()))
                         .name(propertyName).build());
             }
 
             try {
-                final DataFetcher dataFetcher = fetcherClass.getConstructor(String.class, String.class).newInstance(propertyName, propertyType.getValueTypeId());
+                final DataFetcher dataFetcher = fetcherClass.getConstructor(String.class, String.class).newInstance(propertyName, propertyType.getTypeId());
                 codeRegisterBuilder.dataFetcher(FieldCoordinates.coordinates(graphQLTypeName, propertyName), dataFetcher);
             } catch (Exception e) {
                 throw new RuntimeException(String.format("Error creating a data fetcher with class %s for field %s", fetcherClass.getName(), propertyName), e);
@@ -375,20 +446,20 @@ public class GraphQLSchemaProvider {
     }
 
     private GraphQLObjectType createDynamicSetOutputType(
-            final PropertyType propertyType, final GraphQLCodeRegistry.Builder codeRegisterBuilder, final String parentName) {
+            final DefinitionType propertyType, final GraphQLCodeRegistry.Builder codeRegisterBuilder, final String parentName) {
 
-        return createDynamicOutputType(parentName != null ? parentName : propertyType.getItemId(), propertyType.getChildPropertyTypes(), null, codeRegisterBuilder);
+        return createDynamicOutputType(parentName != null ? parentName : propertyType.getName(), propertyType.getSubTypes(), null, codeRegisterBuilder);
     }
 
     private GraphQLObjectType createDynamicEventOutputType(
-            final EventType eventType, final GraphQLCodeRegistry.Builder codeRegisterBuilder) {
+            final DefinitionType eventType, final GraphQLCodeRegistry.Builder codeRegisterBuilder) {
 
         final Set<Class> interfaces = new HashSet<>();
         interfaces.add(CDPEventInterface.class);
-        return createDynamicOutputType(UnomiToGraphQLConverter.convertEventType(eventType.getType()), eventType.getPropertyTypes(), interfaces, codeRegisterBuilder);
+        return createDynamicOutputType(UnomiToGraphQLConverter.convertEventType(eventType.getName()), eventType.getSubTypes(), interfaces, codeRegisterBuilder);
     }
 
-    private GraphQLObjectType createDynamicOutputType(final String name, final Set<PropertyType> propertyTypes, final Set<Class> interfaces, final GraphQLCodeRegistry.Builder codeRegisterBuilder) {
+    private GraphQLObjectType createDynamicOutputType(final String name, final List<DefinitionType> propertyTypes, final Set<Class> interfaces, final GraphQLCodeRegistry.Builder codeRegisterBuilder) {
         final String typeName = StringUtils.capitalize(PropertyNameTranslator.translateFromUnomiToGraphQL(name));
 
         final GraphQLObjectType.Builder dynamicTypeBuilder = GraphQLObjectType.newObject()
@@ -413,15 +484,16 @@ public class GraphQLSchemaProvider {
         }
 
         if (propertyTypes != null && !propertyTypes.isEmpty()) {
+            //
             propertyTypes.forEach(childPropertyType -> {
-                final boolean isSet = "set".equals(childPropertyType.getValueTypeId());
-                String childPropertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(childPropertyType.getItemId());
+                final boolean isSet = childPropertyType.hasSubTypes();
+                String childPropertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(childPropertyType.getName());
 
                 GraphQLOutputType objectType = null;
                 if (isSet) {
                     objectType = createDynamicSetOutputType(childPropertyType, codeRegisterBuilder, typeName + "_" + childPropertyName);
                 } else {
-                    objectType = (GraphQLOutputType) UnomiToGraphQLConverter.convertPropertyType(childPropertyType.getValueTypeId());
+                    objectType = (GraphQLOutputType) UnomiToGraphQLConverter.convertPropertyType(childPropertyType.getTypeId());
                 }
 
                 if (objectType != null) {
@@ -446,15 +518,15 @@ public class GraphQLSchemaProvider {
         return null;
     }
 
-    private GraphQLInputObjectType createDynamicEventInputType(final EventType eventType) {
-        return createDynamicInputType(UnomiToGraphQLConverter.convertEventType(eventType.getType()), eventType.getPropertyTypes(), true);
+    private GraphQLInputObjectType createDynamicEventInputType(final DefinitionType eventType) {
+        return createDynamicInputType(UnomiToGraphQLConverter.convertEventType(eventType.getName()), eventType.getSubTypes(), true);
     }
 
-    private GraphQLInputObjectType createDynamicSetInputType(final PropertyType propertyType, final String parentName) {
-        return createDynamicInputType(parentName != null ? parentName : propertyType.getItemId(), propertyType.getChildPropertyTypes(), false);
+    private GraphQLInputObjectType createDynamicSetInputType(final DefinitionType propertyType, final String parentName) {
+        return createDynamicInputType(parentName != null ? parentName : propertyType.getName(), propertyType.getSubTypes(), false);
     }
 
-    private GraphQLInputObjectType createDynamicInputType(final String name, final Set<PropertyType> propertyTypes, final boolean isEvent) {
+    private GraphQLInputObjectType createDynamicInputType(final String name, final List<DefinitionType> propertyTypes, final boolean isEvent) {
         final String typeName = StringUtils.capitalize(PropertyNameTranslator.translateFromUnomiToGraphQL(name)) + "Input";
 
         final GraphQLInputObjectType.Builder dynamicTypeBuilder = GraphQLInputObjectType.newInputObject()
@@ -470,14 +542,14 @@ public class GraphQLSchemaProvider {
 
         if (propertyTypes != null && !propertyTypes.isEmpty()) {
             propertyTypes.forEach(childPropertyType -> {
-                final boolean isSet = "set".equals(childPropertyType.getValueTypeId());
-                String childPropertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(childPropertyType.getItemId());
+                final boolean isSet = childPropertyType.hasSubTypes();
+                String childPropertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(childPropertyType.getName());
 
                 GraphQLInputType objectType;
                 if (isSet) {
                     objectType = createDynamicSetInputType(childPropertyType, typeName + "_" + childPropertyName);
                 } else {
-                    objectType = (GraphQLInputType) UnomiToGraphQLConverter.convertPropertyType(childPropertyType.getValueTypeId());
+                    objectType = (GraphQLInputType) UnomiToGraphQLConverter.convertPropertyType(childPropertyType.getTypeId());
                 }
 
                 if (objectType != null) {
@@ -501,20 +573,20 @@ public class GraphQLSchemaProvider {
 
     private void registerDynamicInputFields(final String graphQLTypeName,
                                             final Class<?> clazz,
-                                            final Collection<PropertyType> propertyTypes) {
+                                            final Collection<DefinitionType> propertyTypes) {
         final GraphQLInputObjectType inputObjectType = getInputObjectType(clazz);
         registerDynamicInputFields(graphQLTypeName, inputObjectType, propertyTypes);
     }
 
     private void registerDynamicInputFields(final String graphQLTypeName,
                                             final GraphQLInputObjectType graphQLInputObjectType,
-                                            final Collection<PropertyType> propertyTypes) {
+                                            final Collection<DefinitionType> propertyTypes) {
         final List<GraphQLInputObjectField> fieldDefinitions = new ArrayList<>();
 
         propertyTypes.forEach(propertyType -> {
-            final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getItemId());
+            final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getName());
 
-            if ("set".equals(propertyType.getValueTypeId())) {
+            if (propertyType.hasSubTypes()) {
                 final String typeName = StringUtils.capitalize(propertyName) + "Input";
 
                 if (!graphQLAnnotations.getContainer().getTypeRegistry().containsKey(typeName)) {
@@ -533,7 +605,7 @@ public class GraphQLSchemaProvider {
                 }
             } else {
                 fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
-                        .type((GraphQLInputType) UnomiToGraphQLConverter.convertPropertyType(propertyType.getValueTypeId()))
+                        .type((GraphQLInputType) UnomiToGraphQLConverter.convertPropertyType(propertyType.getTypeId()))
                         .name(propertyName)
                         .build());
             }
@@ -578,9 +650,9 @@ public class GraphQLSchemaProvider {
         }
 
         // now add all unomi defined event types
-        final Collection<EventType> unomiEventTypes = eventTypeRegistry.getAll();
+        final List<JSONSchema> unomiEventTypes = schemaRegistry.getTargetSchemas("events");
         unomiEventTypes.forEach(eventType -> {
-            final String typeName = UnomiToGraphQLConverter.convertEventType(eventType.getType());
+            final String typeName = UnomiToGraphQLConverter.convertEventType(eventType.getSchemaId());
             final GraphQLInputType eventInputType = (GraphQLInputType) getFromTypeRegistry(typeName + "Input");
             if (eventInputType == null) {
                 logger.warn("Couldn't find event input type {}", typeName + "Input, will not add it as a field.");
@@ -740,15 +812,15 @@ public class GraphQLSchemaProvider {
                 .getGraphQLType(annotatedClass, graphQLAnnotations.getContainer(), false);
     }
 
-    public static Builder create(final ProfileService profileService, final EventTypeRegistry eventTypeRegistry) {
-        return new Builder(profileService, eventTypeRegistry);
+    public static Builder create(final ProfileService profileService, final SchemaRegistry schemaRegistry) {
+        return new Builder(profileService, schemaRegistry);
     }
 
     static class Builder {
 
         final ProfileService profileService;
 
-        final EventTypeRegistry eventTypeRegistry;
+        final SchemaRegistry schemaRegistry;
 
         List<GraphQLTypeFunctionProvider> typeFunctionProviders;
 
@@ -768,9 +840,9 @@ public class GraphQLSchemaProvider {
 
         UnomiEventPublisher eventPublisher;
 
-        private Builder(final ProfileService profileService, final EventTypeRegistry eventTypeRegistry) {
+        private Builder(final ProfileService profileService, final SchemaRegistry schemaRegistry) {
             this.profileService = profileService;
-            this.eventTypeRegistry = eventTypeRegistry;
+            this.schemaRegistry = schemaRegistry;
         }
 
         public Builder typeFunctionProviders(List<GraphQLTypeFunctionProvider> typeFunctionProviders) {
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
index af5d992..24fb973 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
@@ -20,8 +20,8 @@ import graphql.GraphQL;
 import graphql.execution.SubscriptionExecutionStrategy;
 import graphql.schema.GraphQLCodeRegistry;
 import graphql.schema.GraphQLSchema;
-import org.apache.unomi.api.services.EventTypeRegistry;
 import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.api.services.SchemaRegistry;
 import org.apache.unomi.graphql.fetchers.event.UnomiEventPublisher;
 import org.apache.unomi.graphql.providers.GraphQLAdditionalTypesProvider;
 import org.apache.unomi.graphql.providers.GraphQLCodeRegistryProvider;
@@ -83,7 +83,7 @@ public class GraphQLSchemaUpdater {
 
     private ProfileService profileService;
 
-    private EventTypeRegistry eventTypeRegistry;
+    private SchemaRegistry schemaRegistry;
 
     private CDPEventInterfaceRegister eventInterfaceRegister;
 
@@ -131,8 +131,8 @@ public class GraphQLSchemaUpdater {
     }
 
     @Reference
-    public void setEventTypeRegistry(EventTypeRegistry eventTypeRegistry) {
-        this.eventTypeRegistry = eventTypeRegistry;
+    public void setSchemaRegistry(SchemaRegistry schemaRegistry) {
+        this.schemaRegistry = schemaRegistry;
     }
 
     @Reference
@@ -330,7 +330,7 @@ public class GraphQLSchemaUpdater {
 
     @SuppressWarnings("unchecked")
     private GraphQLSchema createGraphQLSchema() {
-        final GraphQLSchemaProvider schemaProvider = GraphQLSchemaProvider.create(profileService, eventTypeRegistry)
+        final GraphQLSchemaProvider schemaProvider = GraphQLSchemaProvider.create(profileService, schemaRegistry)
                 .typeFunctionProviders(typeFunctionProviders)
                 .extensionsProviders(extensionsProviders)
                 .additionalTypesProviders(additionalTypesProviders)
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/PropertyFilterUtils.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/PropertyFilterUtils.java
index 436193a..49e0741 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/PropertyFilterUtils.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/PropertyFilterUtils.java
@@ -35,7 +35,7 @@ import java.util.List;
 
 public class PropertyFilterUtils {
 
-    public static List<GraphQLInputObjectField> buildInputPropertyFilters(final Collection<PropertyType> propertyTypes, final GraphQLAnnotations graphQLAnnotations) {
+    public static List<GraphQLInputObjectField> buildInputPropertyFilters(final Collection<GraphQLSchemaProvider.DefinitionType> propertyTypes, final GraphQLAnnotations graphQLAnnotations) {
         if (propertyTypes == null || propertyTypes.isEmpty()) {
             return Collections.emptyList();
         }
@@ -47,10 +47,10 @@ public class PropertyFilterUtils {
         return fieldDefinitions;
     }
 
-    private static void addFilters(final List<GraphQLInputObjectField> fieldDefinitions, final PropertyType propertyType, final GraphQLAnnotations graphQLAnnotations) {
-        final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getItemId());
+    private static void addFilters(final List<GraphQLInputObjectField> fieldDefinitions, final GraphQLSchemaProvider.DefinitionType propertyType, final GraphQLAnnotations graphQLAnnotations) {
+        final String propertyName = PropertyNameTranslator.translateFromUnomiToGraphQL(propertyType.getName());
 
-        if ("integer".equals(propertyType.getValueTypeId())) {
+        if ("integer".equals(propertyType.getTypeId())) {
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
                     .type(Scalars.GraphQLInt)
@@ -71,7 +71,7 @@ public class PropertyFilterUtils {
                     .name(propertyName + "_gte")
                     .type(Scalars.GraphQLInt)
                     .build());
-        } else if ("long".equals(propertyType.getValueTypeId())) {
+        } else if ("long".equals(propertyType.getTypeId())) {
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
                     .type(Scalars.GraphQLLong)
@@ -92,7 +92,7 @@ public class PropertyFilterUtils {
                     .name(propertyName + "_gte")
                     .type(Scalars.GraphQLLong)
                     .build());
-        } else if ("float".equals(propertyType.getValueTypeId())) {
+        } else if ("float".equals(propertyType.getTypeId())) {
 
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
@@ -114,7 +114,7 @@ public class PropertyFilterUtils {
                     .name(propertyName + "_gte")
                     .type(Scalars.GraphQLFloat)
                     .build());
-        } else if ("date".equals(propertyType.getValueTypeId())) {
+        } else if ("date".equals(propertyType.getTypeId())) {
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
                     .type(DateTimeFunction.DATE_TIME_SCALAR)
@@ -135,18 +135,18 @@ public class PropertyFilterUtils {
                     .name(propertyName + "_gte")
                     .type(DateTimeFunction.DATE_TIME_SCALAR)
                     .build());
-        } else if ("boolean".equals(propertyType.getValueTypeId())) {
+        } else if ("boolean".equals(propertyType.getTypeId())) {
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
                     .type(Scalars.GraphQLBoolean)
                     .build());
-        } else if ("id".equals(propertyType.getValueTypeId())) {
+        } else if ("id".equals(propertyType.getTypeId())) {
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
                     .type(Scalars.GraphQLString)
                     .build());
-        } else if ("set".equals(propertyType.getValueTypeId())) {
-            if (propertyType.getChildPropertyTypes() != null && !propertyType.getChildPropertyTypes().isEmpty()) {
+        } else if ("set".equals(propertyType.getTypeId())) {
+            if (propertyType.hasSubTypes()) {
                 final String typeName = StringUtils.capitalize(propertyName) + "FilterInput";
 
                 GraphQLInputObjectType inputObjectType;
@@ -156,7 +156,7 @@ public class PropertyFilterUtils {
 
                     final List<GraphQLInputObjectField> setFieldDefinitions = new ArrayList<>();
 
-                    propertyType.getChildPropertyTypes().forEach(childPropertyType ->
+                    propertyType.getSubTypes().forEach(childPropertyType ->
                             addFilters(setFieldDefinitions, childPropertyType, graphQLAnnotations));
 
                     dynamicTypeBuilder.fields(setFieldDefinitions);
@@ -173,7 +173,7 @@ public class PropertyFilterUtils {
                         .type(inputObjectType)
                         .build());
             }
-        } else if ("geopoint".equals(propertyType.getValueTypeId())) {
+        } else if ("geopoint".equals(propertyType.getTypeId())) {
 
             fieldDefinitions.add(GraphQLInputObjectField.newInputObjectField()
                     .name(propertyName + "_equals")
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java
index f766175..fc15ed4 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/types/resolvers/CDPEventInterfaceResolver.java
@@ -18,8 +18,8 @@ package org.apache.unomi.graphql.types.resolvers;
 
 import graphql.TypeResolutionEnvironment;
 import graphql.schema.GraphQLObjectType;
-import org.apache.unomi.api.EventType;
-import org.apache.unomi.api.services.EventTypeRegistry;
+import org.apache.unomi.api.schema.json.JSONSchema;
+import org.apache.unomi.api.services.SchemaRegistry;
 import org.apache.unomi.graphql.converters.UnomiToGraphQLConverter;
 import org.apache.unomi.graphql.services.ServiceManager;
 import org.apache.unomi.graphql.types.output.CDPEventInterface;
@@ -29,12 +29,12 @@ public class CDPEventInterfaceResolver extends BaseTypeResolver {
     @Override
     public GraphQLObjectType getType(TypeResolutionEnvironment env) {
         final ServiceManager serviceManager = env.getContext();
-        final EventTypeRegistry eventTypeRegistry = serviceManager.getService(EventTypeRegistry.class);
+        SchemaRegistry schemaRegistry = serviceManager.getService(SchemaRegistry.class);
 
         final CDPEventInterface eventInterface = env.getObject();
-        final EventType eventType = eventTypeRegistry.get(eventInterface.getEvent().getEventType());
-        if (eventType != null) {
-            final String typeName = UnomiToGraphQLConverter.convertEventType(eventType.getType());
+        final JSONSchema eventSchema = schemaRegistry.getSchema("https://unomi.apache.org/schemas/json/events/" + eventInterface.getEvent().getEventType() + "/1-0-0");
+        if (eventSchema != null) {
+            final String typeName = UnomiToGraphQLConverter.convertEventType(eventSchema.getSchemaId());
             return env.getSchema().getObjectType(typeName);
         } else {
             return super.getType(env);
diff --git a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
index 2df03c5..469464c 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
@@ -25,10 +25,7 @@ import org.apache.unomi.api.*;
 import org.apache.unomi.api.conditions.Condition;
 import org.apache.unomi.api.segments.Scoring;
 import org.apache.unomi.api.segments.Segment;
-import org.apache.unomi.api.services.DefinitionsService;
-import org.apache.unomi.api.services.EventService;
-import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.SegmentService;
+import org.apache.unomi.api.services.*;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.apache.unomi.persistence.spi.PersistenceService;
 import org.junit.After;
@@ -43,6 +40,7 @@ import org.ops4j.pax.exam.util.Filter;
 import javax.inject.Inject;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URI;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -62,7 +60,10 @@ import static org.junit.Assert.*;
 public class ContextServletIT extends BaseIT {
     private final static String CONTEXT_URL = "/cxs/context.json";
     private final static String THIRD_PARTY_HEADER_NAME = "X-Unomi-Peer";
-    private final static String SEGMENT_EVENT_TYPE = "test-event-type";
+    private final static String TEST_EVENT_TYPE = "test-event-type";
+    private final static String TEST_EVENT_TYPE_SCHEMA = "test-event-type.json";
+    private final static String FLOAT_PROPERTY_EVENT_TYPE = "float-property-type";
+    private final static String FLOAT_PROPERTY_EVENT_TYPE_SCHEMA = "float-property-type.json";
     private final static String SEGMENT_ID = "test-segment-id";
     private final static int SEGMENT_NUMBER_OF_DAYS = 30;
 
@@ -88,11 +89,16 @@ public class ContextServletIT extends BaseIT {
     @Filter(timeout = 600000)
     protected SegmentService segmentService;
 
+    @Inject
+    @Filter(timeout = 600000)
+    protected SchemaRegistry schemaRegistry;
+
     private Profile profile;
 
     @Before
     public void setUp() throws InterruptedException {
-        this.registerEventType(SEGMENT_EVENT_TYPE);
+        this.registerEventType(TEST_EVENT_TYPE_SCHEMA);
+        this.registerEventType(FLOAT_PROPERTY_EVENT_TYPE_SCHEMA);
 
         //Create a past-event segment
         Metadata segmentMetadata = new Metadata(SEGMENT_ID);
@@ -101,7 +107,7 @@ public class ContextServletIT extends BaseIT {
         segmentCondition.setParameter("minimumEventCount", 2);
         segmentCondition.setParameter("numberOfDays", SEGMENT_NUMBER_OF_DAYS);
         Condition pastEventEventCondition = new Condition(definitionsService.getConditionType("eventTypeCondition"));
-        pastEventEventCondition.setParameter("eventTypeId", SEGMENT_EVENT_TYPE);
+        pastEventEventCondition.setParameter("eventTypeId", TEST_EVENT_TYPE);
         segmentCondition.setParameter("eventCondition", pastEventEventCondition);
         segment.setCondition(segmentCondition);
         segmentService.setSegmentDefinition(segment);
@@ -120,38 +126,14 @@ public class ContextServletIT extends BaseIT {
         TestUtils.removeAllProfiles(definitionsService, persistenceService);
         profileService.delete(profile.getItemId(), false);
         segmentService.removeSegmentDefinition(SEGMENT_ID, false);
-    }
 
-    private void registerEventType(final String type) {
-        final Set<PropertyType> props = new HashSet<>();
-        registerEventType(type, props, null, null);
+        schemaRegistry.unregisterSchema("events", TEST_EVENT_TYPE);
+        schemaRegistry.unregisterSchema("events", FLOAT_PROPERTY_EVENT_TYPE);
     }
 
-    private void registerEventType(final String type, final Set<PropertyType> properties, final Set<PropertyType> source, final Set<PropertyType> target) {
-        final Set<PropertyType> typeProps = new HashSet<>();
-        if (properties != null) {
-            PropertyType propertiesPropType = new PropertyType();
-            propertiesPropType.setItemId("properties");
-            propertiesPropType.setValueTypeId("set");
-            propertiesPropType.setChildPropertyTypes(properties);
-            typeProps.add(propertiesPropType);
-        }
-        if (source != null) {
-            PropertyType sourcePropType = new PropertyType();
-            sourcePropType.setItemId("source");
-            sourcePropType.setValueTypeId("set");
-            sourcePropType.setChildPropertyTypes(source);
-            typeProps.add(sourcePropType);
-        }
-        if (target != null) {
-            PropertyType targetPropType = new PropertyType();
-            targetPropType.setItemId("target");
-            targetPropType.setValueTypeId("set");
-            targetPropType.setChildPropertyTypes(target);
-            typeProps.add(targetPropType);
-        }
-        final EventType eventType = new EventType(type, typeProps, 1);
-        eventService.registerEventType(eventType);
+    private void registerEventType(String jsonSchemaFileName) {
+        InputStream jsonSchemaInputStream = this.getClass().getClassLoader().getResourceAsStream("schemas/events/" + jsonSchemaFileName);
+        schemaRegistry.registerSchema("events", jsonSchemaInputStream);
     }
 
     @Test
@@ -162,7 +144,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         String eventTypeOriginal = "test-event-type-original";
-        String eventTypeUpdated = "test-event-type-updated";
+        String eventTypeUpdated = TEST_EVENT_TYPE;
         Profile profile = new Profile(profileId);
         Session session = new Session(sessionId, profile, new Date(), scope);
         Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
@@ -172,8 +154,6 @@ public class ContextServletIT extends BaseIT {
         Thread.sleep(2000);
         event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
 
-        this.registerEventType(eventTypeUpdated);
-
         //Act
         ContextRequest contextRequest = new ContextRequest();
         contextRequest.setSessionId(session.getItemId());
@@ -199,7 +179,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         String eventTypeOriginal = "test-event-type-original";
-        String eventTypeUpdated = "test-event-type-updated";
+        String eventTypeUpdated = TEST_EVENT_TYPE;
         Profile profile = new Profile(profileId);
         Session session = new Session(sessionId, profile, new Date(), scope);
         Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
@@ -209,8 +189,6 @@ public class ContextServletIT extends BaseIT {
         Thread.sleep(2000);
         event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
 
-        this.registerEventType(eventTypeUpdated);
-
         //Act
         ContextRequest contextRequest = new ContextRequest();
         contextRequest.setSessionId(session.getItemId());
@@ -235,7 +213,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         String eventTypeOriginal = "test-event-type-original";
-        String eventTypeUpdated = "test-event-type-updated";
+        String eventTypeUpdated = TEST_EVENT_TYPE;
         Session session = new Session(sessionId, profile, new Date(), scope);
         Event event = new Event(eventId, eventTypeOriginal, session, profile, scope, null, null, new Date());
         this.eventService.send(event);
@@ -243,8 +221,6 @@ public class ContextServletIT extends BaseIT {
         Thread.sleep(2000);
         event.setEventType(eventTypeUpdated); //change the event so we can see the update effect
 
-        this.registerEventType(eventTypeUpdated);
-
         //Act
         ContextRequest contextRequest = new ContextRequest();
         contextRequest.setSessionId(session.getItemId());
@@ -267,7 +243,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         Event event = new Event();
-        event.setEventType(SEGMENT_EVENT_TYPE);
+        event.setEventType(TEST_EVENT_TYPE);
         event.setScope(scope);
 
         //Act
@@ -298,7 +274,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         Event event = new Event();
-        event.setEventType(SEGMENT_EVENT_TYPE);
+        event.setEventType(TEST_EVENT_TYPE);
         event.setScope(scope);
         String regularURI = URL + CONTEXT_URL;
         long oldTimestamp = LocalDateTime.now(ZoneId.of("UTC")).minusDays(SEGMENT_NUMBER_OF_DAYS + 1).toInstant(ZoneOffset.UTC).toEpochMilli();
@@ -330,7 +306,7 @@ public class ContextServletIT extends BaseIT {
         String sessionId = "test-session-id";
         String scope = "test-scope";
         Event event = new Event();
-        event.setEventType(SEGMENT_EVENT_TYPE);
+        event.setEventType(TEST_EVENT_TYPE);
         event.setScope(scope);
         String regularURI = URL + CONTEXT_URL;
         long futureTimestamp = LocalDateTime.now(ZoneId.of("UTC")).plusDays(1).toInstant(ZoneOffset.UTC).toEpochMilli();
@@ -371,8 +347,6 @@ public class ContextServletIT extends BaseIT {
         contextRequest.setProfileId(profileId);
         contextRequest.setEvents(Arrays.asList(event));
 
-        this.registerEventType(eventType);
-
         //Act
         HttpPost request = new HttpPost(URL + CONTEXT_URL);
         request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
@@ -391,7 +365,7 @@ public class ContextServletIT extends BaseIT {
         //Arrange
         String eventId = "valid-event-id-" + System.currentTimeMillis();
         String profileId = "valid-profile-id";
-        String eventType = "valid-event-type";
+        String eventType = FLOAT_PROPERTY_EVENT_TYPE;
         Event event = new Event();
         event.setEventType(eventType);
         event.setItemId(eventId);
@@ -403,13 +377,6 @@ public class ContextServletIT extends BaseIT {
         contextRequest.setProfileId(profileId);
         contextRequest.setEvents(Arrays.asList(event));
 
-        final Set<PropertyType> propertiesPropTypes = new HashSet<>();
-        PropertyType floatProp = new PropertyType();
-        floatProp.setItemId("floatProperty");
-        floatProp.setValueTypeId("float");
-        propertiesPropTypes.add(floatProp);
-        this.registerEventType(eventType, propertiesPropTypes, null, null);
-
         //Act
         HttpPost request = new HttpPost(URL + CONTEXT_URL);
         request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
@@ -429,7 +396,7 @@ public class ContextServletIT extends BaseIT {
         //Arrange
         String eventId = "invalid-event-value-id-" + System.currentTimeMillis();
         String profileId = "invalid-profile-id";
-        String eventType = "invalid-event-value-type";
+        String eventType = FLOAT_PROPERTY_EVENT_TYPE;
         Event event = new Event();
         event.setEventType(eventType);
         event.setItemId(eventId);
@@ -441,13 +408,6 @@ public class ContextServletIT extends BaseIT {
         contextRequest.setProfileId(profileId);
         contextRequest.setEvents(Arrays.asList(event));
 
-        final Set<PropertyType> propertiesPropTypes = new HashSet<>();
-        PropertyType floatProp = new PropertyType();
-        floatProp.setItemId("floatProperty");
-        floatProp.setValueTypeId("float");
-        propertiesPropTypes.add(floatProp);
-        this.registerEventType(eventType, propertiesPropTypes, null, null);
-
         //Act
         HttpPost request = new HttpPost(URL + CONTEXT_URL);
         request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
@@ -466,7 +426,7 @@ public class ContextServletIT extends BaseIT {
         //Arrange
         String eventId = "invalid-event-prop-id-" + System.currentTimeMillis();
         String profileId = "invalid-profile-id";
-        String eventType = "invalid-event-prop-type";
+        String eventType = FLOAT_PROPERTY_EVENT_TYPE;
         Event event = new Event();
         event.setEventType(eventType);
         event.setItemId(eventId);
@@ -478,17 +438,6 @@ public class ContextServletIT extends BaseIT {
         contextRequest.setProfileId(profileId);
         contextRequest.setEvents(Arrays.asList(event));
 
-        final Set<PropertyType> propertiesPropTypes = new HashSet<>();
-        PropertyType floatProp = new PropertyType();
-        floatProp.setItemId("floatProperty");
-        floatProp.setValueTypeId("float");
-        propertiesPropTypes.add(floatProp);
-        PropertyType geopointProp = new PropertyType();
-        geopointProp.setItemId("geopointProperty");
-        geopointProp.setValueTypeId("geopoint");
-        propertiesPropTypes.add(geopointProp);
-        this.registerEventType(eventType, propertiesPropTypes, null, null);
-
         //Act
         HttpPost request = new HttpPost(URL + CONTEXT_URL);
         request.addHeader(THIRD_PARTY_HEADER_NAME, UNOMI_KEY);
diff --git a/itests/src/test/resources/schemas/events/float-property-type.json b/itests/src/test/resources/schemas/events/float-property-type.json
new file mode 100644
index 0000000..a44061e
--- /dev/null
+++ b/itests/src/test/resources/schemas/events/float-property-type.json
@@ -0,0 +1,21 @@
+{
+  "$id": "https://unomi.apache.org/schemas/json/events/float-property-type/1-0-0",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "name":"events/float-property-type",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
+  "title": "FloatPropertyEvent",
+  "type": "object",
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
+  "properties" : {
+    "properties" : {
+      "type" : "object",
+      "properties" : {
+        "floatProperty" : { "type" : "number" }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/itests/src/test/resources/schemas/events/test-event-type.json b/itests/src/test/resources/schemas/events/test-event-type.json
new file mode 100644
index 0000000..46b56e2
--- /dev/null
+++ b/itests/src/test/resources/schemas/events/test-event-type.json
@@ -0,0 +1,13 @@
+{
+  "$id": "https://unomi.apache.org/schemas/json/events/test-event-type/1-0-0",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "name":"events/test-event-type",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
+  "title": "TestEvent",
+  "type": "object",
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }]
+}
\ No newline at end of file
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java
index 710ba11..f1bac4d 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java
@@ -18,7 +18,6 @@ package org.apache.unomi.rest.endpoints;
 
 import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
 import org.apache.unomi.api.Event;
-import org.apache.unomi.api.EventType;
 import org.apache.unomi.api.PartialList;
 import org.apache.unomi.api.query.Query;
 import org.apache.unomi.api.services.EventService;
@@ -91,15 +90,4 @@ public class EventServiceEndpoint {
         return eventService.getEventTypeIds();
     }
 
-    /**
-     * Returns the list of event properties
-     * @param typeName the type name identifier
-     * @return a List of EventProperty objects that make up the properties that the server has seen.
-     */
-    @GET
-    @Path("types/{typeName}")
-    public EventType getEventType(@PathParam("typeName") String typeName) {
-        return eventService.getEventType(typeName);
-    }
-
 }
diff --git a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java
index 7686797..be5ac44 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java
@@ -22,7 +22,6 @@ import inet.ipaddr.IPAddressString;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.unomi.api.Event;
 import org.apache.unomi.api.EventProperty;
-import org.apache.unomi.api.EventType;
 import org.apache.unomi.api.Metadata;
 import org.apache.unomi.api.PartialList;
 import org.apache.unomi.api.PropertyType;
@@ -64,8 +63,6 @@ public class EventServiceImpl implements EventService {
 
     private BundleContext bundleContext;
 
-    private EventTypeRegistry eventTypeRegistry;
-
     private SchemaRegistry schemaRegistry;
 
     private Set<String> predefinedEventTypeIds = new LinkedHashSet<String>();
@@ -115,10 +112,6 @@ public class EventServiceImpl implements EventService {
         this.shouldBeCheckedEventSourceId = shouldBeCheckedEventSourceId;
     }
 
-    public void setEventTypeRegistry(EventTypeRegistry eventTypeRegistry) {
-        this.eventTypeRegistry = eventTypeRegistry;
-    }
-
     public void setSchemaRegistry(SchemaRegistry schemaRegistry) {
         this.schemaRegistry = schemaRegistry;
     }
@@ -147,8 +140,7 @@ public class EventServiceImpl implements EventService {
     }
 
     public boolean isEventValid(Event event) {
-        this.schemaRegistry.isValid(event, "https://unomi.apache.org/schemas/json/events/" + event.getEventType() + ".json");
-        return this.eventTypeRegistry.isValid(event);
+        return this.schemaRegistry.isValid(event, "https://unomi.apache.org/schemas/json/events/" + event.getEventType() + "/1-0-0");
     }
 
     public String authenticateThirdPartyServer(String key, String ip) {
@@ -228,15 +220,6 @@ public class EventServiceImpl implements EventService {
     }
 
     @Override
-    public EventType getEventType(String typeName) {
-        return eventTypeRegistry.get(typeName);
-    }
-
-    public void registerEventType(final EventType eventType) {
-        eventTypeRegistry.register(eventType);
-    }
-
-    @Override
     public List<EventProperty> getEventProperties() {
         Map<String, Map<String, Object>> mappings = persistenceService.getPropertiesMapping(Event.ITEM_TYPE);
         List<EventProperty> props = new ArrayList<>(mappings.size());
diff --git a/services/src/main/java/org/apache/unomi/services/impl/events/EventTypeRegistryImpl.java b/services/src/main/java/org/apache/unomi/services/impl/events/EventTypeRegistryImpl.java
deleted file mode 100644
index a6327a0..0000000
--- a/services/src/main/java/org/apache/unomi/services/impl/events/EventTypeRegistryImpl.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.unomi.services.impl.events;
-
-import org.apache.commons.beanutils.PropertyUtils;
-import org.apache.unomi.api.*;
-import org.apache.unomi.api.services.EventTypeRegistry;
-import org.apache.unomi.persistence.spi.CustomObjectMapper;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.SynchronousBundleListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.util.*;
-
-public class EventTypeRegistryImpl implements EventTypeRegistry, SynchronousBundleListener {
-
-    private static final Logger logger = LoggerFactory.getLogger(EventTypeRegistryImpl.class.getName());
-
-    private final Map<Long, List<EventType>> eventTypesByBundle = new HashMap<>();
-
-    private final Map<String, EventType> eventTypesById = new LinkedHashMap<>();
-
-    private BundleContext bundleContext;
-
-    public void bundleChanged(BundleEvent event) {
-        switch (event.getType()) {
-            case BundleEvent.STARTED:
-                processBundleStartup(event.getBundle().getBundleContext());
-                break;
-            case BundleEvent.STOPPING:
-                processBundleStop(event.getBundle().getBundleContext());
-                break;
-        }
-    }
-
-    public void init() {
-        processBundleStartup(bundleContext);
-
-        // process already started bundles
-        for (Bundle bundle : bundleContext.getBundles()) {
-            if (bundle.getBundleContext() != null && bundle.getBundleId() != bundleContext.getBundle().getBundleId()) {
-                processBundleStartup(bundle.getBundleContext());
-            }
-        }
-
-        bundleContext.addBundleListener(this);
-        logger.info("Event registry initialized.");
-    }
-
-    public void destroy() {
-        bundleContext.removeBundleListener(this);
-        logger.info("Event registry shutdown.");
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public EventType get(String typeName) {
-        return eventTypesById.get(typeName);
-    }
-
-    public void register(EventType eventType) {
-        eventTypesById.put(eventType.getType(), eventType);
-    }
-
-    @Override
-    public boolean isValid(Event event) {
-        if (event == null) {
-            return false;
-        }
-        final EventType eventType = this.get(event.getEventType());
-        if (eventType == null) {
-            return false;
-        }
-
-        Set<PropertyType> propertiesPropertyTypes = findChildPropertyTypesById("properties", eventType.getPropertyTypes());
-        Set<PropertyType> sourcePropertyTypes = findChildPropertyTypesById("source", eventType.getPropertyTypes());
-        Set<PropertyType> targetPropertyTypes = findChildPropertyTypesById("target", eventType.getPropertyTypes());
-
-        return areObjectPropertiesValid(event.getProperties(), propertiesPropertyTypes) &&
-                areObjectPropertiesValid(event.getSource(), sourcePropertyTypes) &&
-                areObjectPropertiesValid(event.getTarget(), targetPropertyTypes);
-    }
-
-    /**
-     * Checks that all properties from map are defined in the property type set.
-     * Does not require all defined properties to be present in map.
-     *
-     * @param props map of properties to validate
-     * @param types set of a predefined event type properties
-     * @return boolean result of validation
-     */
-    private boolean areMapPropertiesValid(Map<Object, Object> props, Set<PropertyType> types) {
-        if (props == null || props.isEmpty() || types == null || types.isEmpty()) {
-            return true;
-        }
-        return props.entrySet().stream().allMatch(entry -> {
-            return types.stream().anyMatch(type -> {
-                if (!type.getItemId().equals(entry.getKey().toString())) {
-                    return false;
-                }
-                final Set<PropertyType> childTypes = type.getChildPropertyTypes();
-                if (childTypes.size() > 0 && entry.getValue() != null) {
-                    try {
-                        return areObjectPropertiesValid(entry.getValue(), childTypes);
-                    } catch (ClassCastException e) {
-                        logger.error("Event property '{}' value is invalid: {}", entry.getKey(), e.getCause());
-                        return false;
-                    }
-                } else {
-                    boolean valueTypeValid = testValueType(entry.getValue(), type.getValueTypeId());
-                    if (!valueTypeValid) {
-                        logger.warn("Event type validation error: value type for property {} is not valid", entry.getKey().toString());
-                    }
-                    return valueTypeValid;
-                }
-            });
-        });
-    }
-
-    private boolean areObjectPropertiesValid(Object object, Set<PropertyType> types) {
-        if (object == null) {
-            return true;
-        }
-        if (object instanceof Map) {
-            return areMapPropertiesValid((Map<Object,Object>) object, types);
-        }
-        PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(object);
-        return Arrays.stream(propertyDescriptors).allMatch(propertyDescriptor -> {
-            PropertyType propertyType = findPropertyTypeById(propertyDescriptor.getName(), types);
-            if (propertyType == null) {
-                logger.warn("Event type validation error: couldn't find property type for property {}", propertyDescriptor.getName());
-                return false;
-            }
-            if ("set".equals(propertyType.getValueTypeId())) {
-                boolean setPropertiesValid = false;
-                try {
-                    setPropertiesValid = areObjectPropertiesValid(PropertyUtils.getProperty(object, propertyDescriptor.getName()), propertyType.getChildPropertyTypes());
-                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
-                    logger.error("Error accessing property {} on object {}: {}", propertyDescriptor.getName(), object.toString(), e);
-                    return false;
-                }
-                if (!setPropertiesValid) {
-                    logger.warn("Event type validation error: set property for property {} are not valid", propertyDescriptor.getName());
-                    return false;
-                }
-            }
-            return true;
-        });
-    }
-
-    private Set<PropertyType> findChildPropertyTypesById(String id, Set<PropertyType> types) {
-        PropertyType propertyType = findPropertyTypeById(id, types);
-        if (propertyType == null) {
-            return new HashSet<>();
-        } else {
-            return propertyType.getChildPropertyTypes();
-        }
-    }
-
-    private PropertyType findPropertyTypeById(String id, Set<PropertyType> types) {
-        Optional<PropertyType> optionalPropertyType = types.stream().filter(propertyType -> propertyType.getItemId().equals(id)).findFirst();
-        return optionalPropertyType.orElse(null);
-
-    }
-
-    private boolean testValueType(final Object value, final String valueTypeId) {
-        switch (valueTypeId) {
-            case "integer":
-                return value instanceof Integer;
-            case "long":
-                return value instanceof Long;
-            case "float":
-                return value instanceof Double;
-            case "set":
-            case "json":
-                return value instanceof Map;
-            case "geopoint":
-                return value instanceof GeoPoint;
-            case "date":
-                return value instanceof Date;
-            case "boolean":
-                return value instanceof Boolean;
-            case "id":
-            case "string":
-                return value instanceof String;
-            default:
-                // return true if type is unknown cuz it may be custom
-                return true;
-        }
-    }
-
-    public Collection<EventType> getAll() {
-        return this.eventTypesById.values();
-    }
-
-    private void loadPredefinedEventTypes(BundleContext bundleContext) {
-        Enumeration<URL> predefinedEventTypes = bundleContext.getBundle().findEntries("META-INF/cxs/events", "*.json", true);
-        if (predefinedEventTypes == null) {
-            return;
-        }
-        List<EventType> bundleEventTypes = this.eventTypesByBundle.get(bundleContext.getBundle().getBundleId());
-
-        while (predefinedEventTypes.hasMoreElements()) {
-            URL predefinedEventTypeURL = predefinedEventTypes.nextElement();
-            logger.debug("Found predefined event type at " + predefinedEventTypeURL + ", loading... ");
-
-            try {
-                EventType eventType = CustomObjectMapper.getObjectMapper().readValue(predefinedEventTypeURL, EventType.class);
-                eventType.setPluginId(bundleContext.getBundle().getBundleId());
-                register(eventType);
-                bundleEventTypes.add(eventType);
-            } catch (Exception e) {
-                logger.error("Error while loading event type definition " + predefinedEventTypeURL, e);
-            }
-        }
-
-    }
-
-    private void processBundleStartup(BundleContext bundleContext) {
-        if (bundleContext == null) {
-            return;
-        }
-        eventTypesByBundle.put(bundleContext.getBundle().getBundleId(), new ArrayList<>());
-        loadPredefinedEventTypes(bundleContext);
-    }
-
-    private void processBundleStop(BundleContext bundleContext) {
-        if (bundleContext == null) {
-            return;
-        }
-        List<EventType> eventTypes = eventTypesByBundle.remove(bundleContext.getBundle().getBundleId());
-        if (eventTypes != null) {
-            for (EventType eventType : eventTypes) {
-                eventTypesById.remove(eventType.getType());
-            }
-        }
-    }
-}
diff --git a/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaRegistryImpl.java b/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaRegistryImpl.java
index 3e93519..289bdec 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaRegistryImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaRegistryImpl.java
@@ -17,12 +17,14 @@
 
 package org.apache.unomi.services.impl.schemas;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.networknt.schema.*;
 import com.networknt.schema.uri.URIFetcher;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.unomi.api.SchemaType;
+import org.apache.unomi.api.schema.json.JSONSchema;
+import org.apache.unomi.api.schema.json.JSONTypeFactory;
 import org.apache.unomi.api.services.ProfileService;
 import org.apache.unomi.api.services.SchemaRegistry;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
@@ -44,8 +46,8 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
 
     private static final Logger logger = LoggerFactory.getLogger(SchemaRegistryImpl.class.getName());
 
-    private final Map<Long, List<SchemaType>> schemaTypesByBundle = new HashMap<>();
-    private final Map<String, SchemaType> schemaTypesById = new HashMap<>();
+    private final Map<Long, List<JSONSchema>> schemaTypesByBundle = new HashMap<>();
+    private final Map<String, JSONSchema> schemaTypesById = new HashMap<>();
 
     private final Map<String, JsonSchema> jsonSchemasById = new LinkedHashMap<>();
 
@@ -55,6 +57,8 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
 
     private ProfileService profileService;
 
+    private JsonSchemaFactory jsonSchemaFactory;
+
     ObjectMapper objectMapper = new ObjectMapper();
 
     public void bundleChanged(BundleEvent event) {
@@ -69,6 +73,14 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
     }
 
     public void init() {
+
+        JsonMetaSchema jsonMetaSchema = JsonMetaSchema.builder(URI, JsonMetaSchema.getV201909())
+                .addKeyword(new PropertyTypeKeyword(profileService, this)).build();
+        jsonSchemaFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))
+                .addMetaSchema(jsonMetaSchema)
+                .defaultMetaSchemaURI(URI)
+                .uriFetcher(getBundleUriFetcher(bundleContext), "https", "http").build();
+
         processBundleStartup(bundleContext);
 
         // process already started bundles
@@ -112,12 +124,12 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
     }
 
     @Override
-    public List<SchemaType> getTargetSchemas(String target) {
-        return schemaTypesById.values().stream().filter(schemaType -> schemaType.getTarget().equals(target)).collect(Collectors.toList());
+    public List<JSONSchema> getTargetSchemas(String target) {
+        return schemaTypesById.values().stream().filter(jsonSchema -> jsonSchema.getTarget() != null && jsonSchema.getTarget().equals(target)).collect(Collectors.toList());
     }
 
     @Override
-    public SchemaType getSchema(String schemaId) {
+    public JSONSchema getSchema(String schemaId) {
         return schemaTypesById.get(schemaId);
     }
 
@@ -127,37 +139,23 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
             return;
         }
 
-        List<SchemaType> schemaTypes = this.schemaTypesByBundle.get(bundleContext.getBundle().getBundleId());
+        List<JSONSchema> jsonSchemas = this.schemaTypesByBundle.get(bundleContext.getBundle().getBundleId());
 
         while (predefinedSchemas.hasMoreElements()) {
             URL predefinedSchemaURL = predefinedSchemas.nextElement();
             logger.debug("Found predefined JSON schema at " + predefinedSchemaURL + ", loading... ");
 
-                JsonMetaSchema jsonMetaSchema = JsonMetaSchema.builder(URI, JsonMetaSchema.getV201909())
-                        .addKeyword(new PropertyTypeKeyword(profileService, this)).build();
-                JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))
-                        .addMetaSchema(jsonMetaSchema)
-                        .defaultMetaSchemaURI(URI)
-                        .uriFetcher(getBundleUriFetcher(bundleContext), "https", "http").build();
             try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) {
                 JsonSchema jsonSchema = jsonSchemaFactory.getSchema(schemaInputStream);
-                String schemaId = jsonSchema.getSchemaNode().get("$id").asText();
-                jsonSchemasById.put(schemaId, jsonSchema);
-                bundleIdBySchemaId.put(schemaId, bundleContext.getBundle().getBundleId());
-                SchemaType schemaType = new SchemaType();
-                schemaType.setPluginId(bundleContext.getBundle().getBundleId());
-                schemaType.setSchemaId(schemaId);
-                Map<String, Object> schemaTree = (Map<String, Object>) objectMapper.treeToValue(jsonSchema.getSchemaNode(), Map.class);
-                schemaType.setSchemaTree(schemaTree);
+                String schemaTarget = null;
                 String[] splitPath = predefinedSchemaURL.getPath().split("/");
                 if (splitPath.length > 5) {
                     String target = splitPath[4];
                     if (StringUtils.isNotBlank(target)) {
-                        schemaType.setTarget(target);
+                        schemaTarget = target;
                     }
                 }
-                schemaTypes.add(schemaType);
-                schemaTypesById.put(schemaId, schemaType);
+                registerSchema(bundleContext.getBundle().getBundleId(), jsonSchemas, schemaTarget, jsonSchema);
             } catch (Exception e) {
                 logger.error("Error while loading schema definition " + predefinedSchemaURL, e);
             }
@@ -165,6 +163,40 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
 
     }
 
+    public String registerSchema(String target, InputStream jsonSchemaInputStream) {
+        JsonSchema jsonSchema = jsonSchemaFactory.getSchema(jsonSchemaInputStream);
+        try {
+            return registerSchema(null, null, target, jsonSchema);
+        } catch (JsonProcessingException e) {
+            logger.error("Error registering JSON schema", e);
+            return null;
+        }
+    }
+
+    public boolean unregisterSchema(String target, String schemaId) {
+        jsonSchemasById.remove(schemaId);
+        schemaTypesById.remove(schemaId);
+        return true;
+    }
+
+    private String registerSchema(Long bundleId, List<JSONSchema> jsonSchemas, String target, JsonSchema jsonSchema) throws JsonProcessingException {
+        String schemaId = jsonSchema.getSchemaNode().get("$id").asText();
+        jsonSchemasById.put(schemaId, jsonSchema);
+        if (bundleContext != null) {
+            bundleIdBySchemaId.put(schemaId, bundleId);
+        }
+        Map<String, Object> schemaTree = (Map<String, Object>) objectMapper.treeToValue(jsonSchema.getSchemaNode(), Map.class);
+        JSONSchema unomiJsonSchema = new JSONSchema(schemaTree, new JSONTypeFactory(this), this);
+        unomiJsonSchema.setPluginId(bundleId);
+        unomiJsonSchema.setSchemaId(schemaId);
+        unomiJsonSchema.setTarget(target);
+        if (jsonSchemas != null) {
+            jsonSchemas.add(unomiJsonSchema);
+        }
+        schemaTypesById.put(schemaId, unomiJsonSchema);
+        return schemaId;
+    }
+
     private URIFetcher getBundleUriFetcher(BundleContext bundleContext) {
         return uri -> {
             logger.debug("Fetching schema {}", uri);
@@ -196,12 +228,12 @@ public class SchemaRegistryImpl implements SchemaRegistry, SynchronousBundleList
         if (bundleContext == null) {
             return;
         }
-        List<SchemaType> schemaTypes = schemaTypesByBundle.remove(bundleContext.getBundle().getBundleId());
-        if (schemaTypes != null) {
-            for (SchemaType schemaType : schemaTypes) {
-                jsonSchemasById.remove(schemaType.getSchemaId());
-                bundleIdBySchemaId.remove(schemaType.getSchemaId());
-                schemaTypesById.remove(schemaType.getSchemaId());
+        List<JSONSchema> JSONSchemas = schemaTypesByBundle.remove(bundleContext.getBundle().getBundleId());
+        if (JSONSchemas != null) {
+            for (JSONSchema JSONSchema : JSONSchemas) {
+                jsonSchemasById.remove(JSONSchema.getSchemaId());
+                bundleIdBySchemaId.remove(JSONSchema.getSchemaId());
+                schemaTypesById.remove(JSONSchema.getSchemaId());
             }
         }
     }
diff --git a/services/src/main/resources/META-INF/cxs/schemas/condition.json b/services/src/main/resources/META-INF/cxs/schemas/condition.json
index 000ee1d..71dbe42 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/condition.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/condition.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/condition.json",
+  "$id": "https://unomi.apache.org/schemas/json/condition/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Condition",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json b/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
index 85e78c8..22e1ad0 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/conditiontype.json",
+  "$id": "https://unomi.apache.org/schemas/json/conditiontype/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "ConditionType",
   "type": "object",
@@ -11,11 +11,11 @@
       "type" : "string"
     },
     "parentCondition" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/condition.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/condition/1-0-0"
     },
     "parameters" : {
       "type" : "object",
-      "additionalProperties": { "$ref" : "https://unomi.apache.org/schemas/json/parameter.json" },
+      "additionalProperties": { "$ref" : "https://unomi.apache.org/schemas/json/parameter/1-0-0" },
       "maxProperties": 50
     }
   }
diff --git a/services/src/main/resources/META-INF/cxs/schemas/consent.json b/services/src/main/resources/META-INF/cxs/schemas/consent.json
index c1eb229..bb357fe 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/consent.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/consent.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/consent.json",
+  "$id": "https://unomi.apache.org/schemas/json/consent/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Consent",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/consentType.json b/services/src/main/resources/META-INF/cxs/schemas/consentType.json
index 19f4bef..034a531 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/consentType.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/consentType.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/consentType.json",
+  "$id": "https://unomi.apache.org/schemas/json/consentType/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "ConsentType",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitem.json b/services/src/main/resources/META-INF/cxs/schemas/customitem.json
index 0c59480..3ae685a 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/customitem.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/customitem.json
@@ -1,11 +1,11 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/customitem.json",
+  "$id": "https://unomi.apache.org/schemas/json/customitem/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "CustomItem",
   "type": "object",
   "allOf": [
     {
-      "$ref": "https://unomi.apache.org/schemas/json/item.json"
+      "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0"
     }
   ],
   "properties": {
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json b/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
index f05ccb6..fb2874f 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
@@ -1,11 +1,18 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/customitems/page.json",
+  "$id": "https://unomi.apache.org/schemas/json/customitems/page/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "target" : "customitems",
+    "name":"page",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
   "title": "PageCustomItem",
   "type": "object",
   "allOf": [
     {
-      "$ref": "https://unomi.apache.org/schemas/json/customitem.json"
+      "$ref": "https://unomi.apache.org/schemas/json/customitem/1-0-0"
     }
   ],
   "properties": {
@@ -59,7 +66,7 @@
     "consentTypes": {
       "type" : ["null", "array"],
       "items" : {
-        "$href" : "https://unomi.apache.org/schemas/json/consentType.json"
+        "$href" : "https://unomi.apache.org/schemas/json/consentType/1-0-0"
       }
     }
   }
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json b/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
index b6de454..2d67e75 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
@@ -1,11 +1,18 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/customitems/site.json",
+  "$id": "https://unomi.apache.org/schemas/json/customitems/site/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "target" : "customitems",
+    "name": "site",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
   "title": "SiteCustomItem",
   "type": "object",
   "allOf": [
     {
-      "$ref": "https://unomi.apache.org/schemas/json/customitem.json"
+      "$ref": "https://unomi.apache.org/schemas/json/customitem/1-0-0"
     }
   ],
   "properties": {
diff --git a/services/src/main/resources/META-INF/cxs/schemas/event.json b/services/src/main/resources/META-INF/cxs/schemas/event.json
index 1b4a03e..66cb8ad 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/event.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/event.json
@@ -1,9 +1,9 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/event.json",
+  "$id": "https://unomi.apache.org/schemas/json/event/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Event",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/timestampeditem.json" }],
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/timestampeditem/1-0-0" }],
   "properties" : {
     "eventType" : {
       "type" : "string",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json b/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
index e203d47..1f748e0 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
@@ -1,20 +1,30 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/events/modifyConsent.json",
+  "$id": "https://unomi.apache.org/schemas/json/events/modifyConsent/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "target" : "events",
+    "name": "modifyConsent",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
   "title": "ModifyConsentEvent",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event.json" }],
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
   "properties" : {
     "properties" : {
-      "consent" : {
-        "$ref" : "https://unomi.apache.org/schemas/json/consent.json"
+      "type" : "object",
+      "properties" : {
+        "consent" : {
+          "$ref" : "https://unomi.apache.org/schemas/json/consent/1-0-0"
+        }
       }
     },
     "source" : {
-        "$ref" : "https://unomi.apache.org/schemas/json/customitems/page.json"
+        "$ref" : "https://unomi.apache.org/schemas/json/customitems/page/1-0-0"
     },
     "target" : {
-        "$ref" : "https://unomi.apache.org/schemas/json/customitem.json"
+        "$ref" : "https://unomi.apache.org/schemas/json/customitem/1-0-0"
     }
   }
 }
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/view.json b/services/src/main/resources/META-INF/cxs/schemas/events/view.json
index 5ea14a9..a85188a 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/events/view.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/events/view.json
@@ -1,20 +1,27 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/events/view.json",
+  "$id": "https://unomi.apache.org/schemas/json/events/view/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "self":{
+    "vendor":"org.apache.unomi",
+    "target" : "events",
+    "name": "view",
+    "format":"jsonschema",
+    "version":"1-0-0"
+  },
   "title": "ViewEvent",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event.json" }],
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
   "properties" : {
     "properties" : {
       "type" : "object",
-      "propertyTypes" : [ "events" ],
+      "unomiPropertyTypes" : [ "events" ],
       "maxProperties": 50
     },
     "source" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/customitems/site.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/customitems/site/1-0-0"
     },
     "target" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/customitems/page.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/customitems/page/1-0-0"
     }
   }
 }
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/goal.json b/services/src/main/resources/META-INF/cxs/schemas/goal.json
index ee7c715..57d922b 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/goal.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/goal.json
@@ -1,15 +1,15 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/goal.json",
+  "$id": "https://unomi.apache.org/schemas/json/goal/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Goal",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/metadataitem.json" }],
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/metadataitem/1-0-0" }],
   "properties" : {
     "startEvent" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/condition.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/condition/1-0-0"
     },
     "targetEvent" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/condition.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/condition/1-0-0"
     },
     "campaignId" : {
       "type" : "string"
diff --git a/services/src/main/resources/META-INF/cxs/schemas/item.json b/services/src/main/resources/META-INF/cxs/schemas/item.json
index b4d9f8a..400b144 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/item.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/item.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/item.json",
+  "$id": "https://unomi.apache.org/schemas/json/item/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Item",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/metadata.json b/services/src/main/resources/META-INF/cxs/schemas/metadata.json
index 2116bba..03d4f71 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/metadata.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/metadata.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/metadata.json",
+  "$id": "https://unomi.apache.org/schemas/json/metadata/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Metadata",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json b/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
index 325dafe..fcdbe1c 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
@@ -1,14 +1,14 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/metadataitem.json",
+  "$id": "https://unomi.apache.org/schemas/json/metadataitem/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "MetadataItem",
   "type": "object",
   "allOf": [
-    { "$ref": "https://unomi.apache.org/schemas/json/item.json" }
+    { "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0" }
   ],
   "properties" : {
     "metadata" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/metadata.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/metadata/1-0-0"
     }
   }
 }
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/parameter.json b/services/src/main/resources/META-INF/cxs/schemas/parameter.json
index abea6ae..cba8c6d 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/parameter.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/parameter.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/parameter.json",
+  "$id": "https://unomi.apache.org/schemas/json/parameter/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Parameter",
   "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/profile.json b/services/src/main/resources/META-INF/cxs/schemas/profile.json
index 2381b81..3bf8c81 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/profile.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/profile.json
@@ -1,11 +1,11 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/profile.json",
+  "$id": "https://unomi.apache.org/schemas/json/profile/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Profile",
   "type": "object",
   "allOf": [
     {
-      "$ref": "https://unomi.apache.org/schemas/json/item.json"
+      "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0"
     }
   ],
   "properties": {
diff --git a/services/src/main/resources/META-INF/cxs/schemas/session.json b/services/src/main/resources/META-INF/cxs/schemas/session.json
index b2534b4..61d6fed 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/session.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/session.json
@@ -1,11 +1,11 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/session.json",
+  "$id": "https://unomi.apache.org/schemas/json/session/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Session",
   "type": "object",
   "allOf": [
     {
-      "$ref": "https://unomi.apache.org/schemas/json/timestampeditem.json"
+      "$ref": "https://unomi.apache.org/schemas/json/timestampeditem/1-0-0"
     }
   ],
   "properties": {
@@ -13,7 +13,7 @@
       "type" : "string"
     },
     "profile" : {
-      "$ref" : "https://unomi.apache.org/schemas/json/profile.json"
+      "$ref" : "https://unomi.apache.org/schemas/json/profile/1-0-0"
     },
     "properties" : {
       "type" : "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json b/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
index bee6c8f..1d7c6ad 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
@@ -1,9 +1,9 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/timestampeditem.json",
+  "$id": "https://unomi.apache.org/schemas/json/timestampeditem/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "TimestampedItem",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/item.json" }],
+  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0" }],
   "properties" : {
     "timeStamp" : {
       "type" : ["null","string"],
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json b/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
index 8a3ed95..752057b 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/values/boolean.json",
+  "$id": "https://unomi.apache.org/schemas/json/values/boolean/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Boolean",
   "type": "boolean"
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/date.json b/services/src/main/resources/META-INF/cxs/schemas/values/date.json
index 7a39489..2ad0739 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/date.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/date.json
@@ -1,5 +1,5 @@
 {
-    "$id": "https://unomi.apache.org/schemas/json/values/date.json",
+    "$id": "https://unomi.apache.org/schemas/json/values/date/1-0-0",
     "$schema": "https://json-schema.org/draft/2019-09/schema",
     "title": "Date",
     "type": "string",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/email.json b/services/src/main/resources/META-INF/cxs/schemas/values/email.json
index 705f2f6..d425eff 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/email.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/email.json
@@ -1,5 +1,5 @@
 {
-    "$id": "https://unomi.apache.org/schemas/json/values/email.json",
+    "$id": "https://unomi.apache.org/schemas/json/values/email/1-0-0",
     "$schema": "https://json-schema.org/draft/2019-09/schema",
     "title": "Email",
     "type": "string",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/integer.json b/services/src/main/resources/META-INF/cxs/schemas/values/integer.json
index f5cb7b9..b3c68a6 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/integer.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/integer.json
@@ -1,5 +1,5 @@
 {
-    "$id": "https://unomi.apache.org/schemas/json/values/integer.json",
+    "$id": "https://unomi.apache.org/schemas/json/values/integer/1-0-0",
     "$schema": "https://json-schema.org/draft/2019-09/schema",
     "title": "Integer",
     "type": "integer"
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/long.json b/services/src/main/resources/META-INF/cxs/schemas/values/long.json
index 769c78a..9eb7c8d 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/long.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/long.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://unomi.apache.org/schemas/json/values/long.json",
+  "$id": "https://unomi.apache.org/schemas/json/values/long/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "title": "Long",
   "type": "integer"
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/set.json b/services/src/main/resources/META-INF/cxs/schemas/values/set.json
index 34b8611..9f43666 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/set.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/set.json
@@ -1,5 +1,5 @@
 {
-    "$id": "https://unomi.apache.org/schemas/json/values/set.json",
+    "$id": "https://unomi.apache.org/schemas/json/values/set/1-0-0",
     "$schema": "https://json-schema.org/draft/2019-09/schema",
     "title": "Set",
     "type": "object",
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/string.json b/services/src/main/resources/META-INF/cxs/schemas/values/string.json
index 6d5e0e8..f0b9c30 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/values/string.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/values/string.json
@@ -1,5 +1,5 @@
 {
-    "$id": "https://unomi.apache.org/schemas/json/values/string.json",
+    "$id": "https://unomi.apache.org/schemas/json/values/string/1-0-0",
     "$schema": "https://json-schema.org/draft/2019-09/schema",
     "title": "String",
     "type": "string"
diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 932b7d1..a8fa903 100644
--- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -101,12 +101,6 @@
         </interfaces>
     </service>
 
-    <bean id="eventTypeRegistryImpl" class="org.apache.unomi.services.impl.events.EventTypeRegistryImpl" init-method="init"
-          destroy-method="destroy">
-        <property name="bundleContext" ref="blueprintBundleContext"/>
-    </bean>
-    <service id="eventTypeRegistry" ref="eventTypeRegistryImpl" interface="org.apache.unomi.api.services.EventTypeRegistry"/>
-
     <bean id="schemaRegistryImpl" class="org.apache.unomi.services.impl.schemas.SchemaRegistryImpl" init-method="init"
           destroy-method="destroy">
         <property name="bundleContext" ref="blueprintBundleContext"/>
@@ -119,7 +113,6 @@
         <property name="definitionsService" ref="definitionsServiceImpl"/>
         <property name="sourceService" ref="sourceServiceImpl"/>
         <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="eventTypeRegistry" ref="eventTypeRegistryImpl"/>
         <property name="schemaRegistry" ref="schemaRegistryImpl" />
         <property name="predefinedEventTypeIds">
             <set>