You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by jk...@apache.org on 2022/05/10 21:00:59 UTC

[unomi] 01/01: UNOMI-568: refacto json-schema implementation

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

jkevan pushed a commit to branch refacto-json-schema
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 723d8edb527d9b19e7d4bbb2946d365bd0cdc3f8
Author: Kevan <ke...@jahia.com>
AuthorDate: Tue May 10 22:50:42 2022 +0200

    UNOMI-568: refacto json-schema implementation
---
 .../unomi/api/schema/JSONSchemaExtension.java      |  83 -----
 extensions/{ => json-schema}/pom.xml               |  22 +-
 extensions/json-schema/rest/pom.xml                |  89 ++++++
 .../unomi/schema/rest}/JsonSchemaEndPoint.java     |  15 +-
 extensions/json-schema/services/pom.xml            | 154 ++++++++++
 .../apache/unomi/schema/api/JsonSchemaWrapper.java |  14 +-
 .../apache/unomi/schema/api}/SchemaService.java    |  81 +----
 .../unomi/schema/impl/SchemaServiceImpl.java       | 241 +++++++++++++++
 .../unomi/schema/listener/JsonSchemaListener.java  | 137 +++++++++
 .../resources/META-INF/cxs/schemas/condition.json  |   0
 .../META-INF/cxs/schemas/conditiontype.json        |   0
 .../resources/META-INF/cxs/schemas/consent.json    |   0
 .../META-INF/cxs/schemas/consentType.json          |   0
 .../resources/META-INF/cxs/schemas/customitem.json |   0
 .../META-INF/cxs/schemas/customitems/page.json     |   0
 .../META-INF/cxs/schemas/customitems/site.json     |   0
 .../main/resources/META-INF/cxs/schemas/event.json |   0
 .../cxs/schemas/events/anonymizeProfile.json       |   0
 .../cxs/schemas/events/articleCompleted.json       |   0
 .../META-INF/cxs/schemas/events/form.json          |   0
 .../META-INF/cxs/schemas/events/goal.json          |   0
 .../META-INF/cxs/schemas/events/identify.json      |   0
 .../cxs/schemas/events/incrementInterest.json      |   0
 .../META-INF/cxs/schemas/events/login.json         |   0
 .../META-INF/cxs/schemas/events/modifyConsent.json |   0
 .../cxs/schemas/events/profileDeleted.json         |   0
 .../cxs/schemas/events/profileUpdated.json         |   0
 .../META-INF/cxs/schemas/events/ruleFired.json     |   0
 .../META-INF/cxs/schemas/events/search.json        |   0
 .../cxs/schemas/events/sessionCreated.json         |   0
 .../cxs/schemas/events/sessionReassigned.json      |   0
 .../cxs/schemas/events/updateProperties.json       |   0
 .../META-INF/cxs/schemas/events/view.json          |   0
 .../main/resources/META-INF/cxs/schemas/goal.json  |   0
 .../main/resources/META-INF/cxs/schemas/item.json  |   0
 .../resources/META-INF/cxs/schemas/metadata.json   |   0
 .../META-INF/cxs/schemas/metadataitem.json         |   0
 .../resources/META-INF/cxs/schemas/parameter.json  |   0
 .../cxs/schemas/personalization/filter.json        |   0
 .../personalization/personalizationrequest.json    |   0
 .../personalization/personalizedcontent.json       |   0
 .../cxs/schemas/personalization/target.json        |   0
 .../resources/META-INF/cxs/schemas/profile.json    |   0
 .../resources/META-INF/cxs/schemas/session.json    |   0
 .../META-INF/cxs/schemas/timestampeditem.json      |  21 +-
 .../META-INF/cxs/schemas/values/boolean.json       |   0
 .../META-INF/cxs/schemas/values/date.json          |   0
 .../META-INF/cxs/schemas/values/email.json         |   0
 .../META-INF/cxs/schemas/values/integer.json       |   0
 .../META-INF/cxs/schemas/values/long.json          |   0
 .../resources/META-INF/cxs/schemas/values/set.json |   0
 .../META-INF/cxs/schemas/values/string.json        |   0
 .../resources/OSGI-INF/blueprint/blueprint.xml     |  54 ++++
 .../src/main/resources/org.apache.unomi.schema.cfg |  19 ++
 extensions/pom.xml                                 |   1 +
 graphql/cxs-impl/pom.xml                           |   6 +
 .../graphql/schema/GraphQLSchemaProvider.java      |  33 +-
 .../unomi/graphql/schema/GraphQLSchemaUpdater.java |   2 +-
 .../unomi/graphql}/schema/json/JSONArrayType.java  |   2 +-
 .../graphql}/schema/json/JSONBooleanType.java      |   2 +-
 .../unomi/graphql}/schema/json/JSONEnumType.java   |   2 +-
 .../graphql}/schema/json/JSONIntegerType.java      |   2 +-
 .../unomi/graphql}/schema/json/JSONNullType.java   |   2 +-
 .../unomi/graphql}/schema/json/JSONNumberType.java |   2 +-
 .../unomi/graphql}/schema/json/JSONObjectType.java |   2 +-
 .../unomi/graphql}/schema/json/JSONSchema.java     |   2 +-
 .../unomi/graphql}/schema/json/JSONStringType.java |   2 +-
 .../unomi/graphql}/schema/json/JSONType.java       |   2 +-
 .../graphql}/schema/json/JSONTypeFactory.java      |  10 +-
 .../types/resolvers/CDPEventInterfaceResolver.java |  13 +-
 .../java/org/apache/unomi/itests/JSONSchemaIT.java |  60 +---
 .../extension/extension-test-event-example.json    |  26 --
 kar/pom.xml                                        |   5 +
 kar/src/main/feature/feature.xml                   |   3 +
 .../resources/OSGI-INF/blueprint/blueprint.xml     |   2 +
 rest/pom.xml                                       |   6 +
 .../deserializers/ContextRequestDeserializer.java  |   6 +-
 .../EventsCollectorRequestDeserializer.java        |   6 +-
 .../unomi/rest/endpoints/ContextJsonEndpoint.java  |   8 +-
 .../endpoints/JsonSchemaExtensionEndPoint.java     | 109 -------
 .../org/apache/unomi/rest/server/RestServer.java   |   2 +-
 .../rest/service/impl/RestServiceUtilsImpl.java    |   9 +-
 .../META-INF/cxs/schemas/contextrequest.json       |   0
 .../META-INF/cxs/schemas/contextrequestparams.json |   0
 .../resources/META-INF/cxs/schemas/cookie.json     |   0
 .../cxs/schemas/eventscollectorrequest.json        |   0
 services/pom.xml                                   |  11 -
 .../services/impl/events/EventServiceImpl.java     |   5 -
 .../services/impl/schemas/SchemaServiceImpl.java   | 339 ---------------------
 .../impl/schemas/UnomiPropertyTypeKeyword.java     | 126 --------
 .../services/listener/JsonSchemaListener.java      | 217 -------------
 .../resources/OSGI-INF/blueprint/blueprint.xml     |  24 --
 .../main/resources/org.apache.unomi.services.cfg   |   3 -
 .../resources/OSGI-INF/blueprint/blueprint.xml     |   2 +
 94 files changed, 834 insertions(+), 1150 deletions(-)

diff --git a/api/src/main/java/org/apache/unomi/api/schema/JSONSchemaExtension.java b/api/src/main/java/org/apache/unomi/api/schema/JSONSchemaExtension.java
deleted file mode 100644
index 652102dfa..000000000
--- a/api/src/main/java/org/apache/unomi/api/schema/JSONSchemaExtension.java
+++ /dev/null
@@ -1,83 +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.schema;
-
-import org.apache.unomi.api.Metadata;
-import org.apache.unomi.api.MetadataItem;
-
-/**
- * Object which represents a JSON schema extensions stored in the persistence service
- */
-public class JSONSchemaExtension extends MetadataItem {
-    public static final String ITEM_TYPE = "jsonSchemaExtension";
-
-    private String id;
-    private String extension;
-    private double priority;
-    private String schemaId;
-
-    public JSONSchemaExtension() {
-    }
-
-    /**
-     * Instantiates a new JSON schema with an id and a schema extension as string
-     *
-     * @param id        id of the extension
-     * @param schemaId  id of the schema
-     * @param extension as string
-     * @param priority  priority to process the extension
-     */
-    public JSONSchemaExtension(String id, String schemaId, String extension, float priority) {
-        super(new Metadata(id));
-        this.id = id;
-        this.extension = extension;
-        this.priority = priority;
-        this.schemaId = schemaId;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getExtension() {
-        return extension;
-    }
-
-    public void setExtension(String extension) {
-        this.extension = extension;
-    }
-
-    public double getPriority() {
-        return priority;
-    }
-
-    public void setPriority(double priority) {
-        this.priority = priority;
-    }
-
-    public String getSchemaId() {
-        return schemaId;
-    }
-
-    public void setSchemaId(String schemaId) {
-        this.schemaId = schemaId;
-    }
-}
diff --git a/extensions/pom.xml b/extensions/json-schema/pom.xml
similarity index 67%
copy from extensions/pom.xml
copy to extensions/json-schema/pom.xml
index 70105e5f5..e869e05d0 100644
--- a/extensions/pom.xml
+++ b/extensions/json-schema/pom.xml
@@ -13,33 +13,25 @@
   ~ 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
+  ~ limitations under the License.
   -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
-
     <parent>
         <groupId>org.apache.unomi</groupId>
-        <artifactId>unomi-root</artifactId>
+        <artifactId>unomi-extensions</artifactId>
         <version>2.0.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>unomi-extensions</artifactId>
-    <name>Apache Unomi :: Extensions</name>
-    <description>Apache Unomi Context Server extensions</description>
+    <artifactId>unomi-json-schema-root</artifactId>
+    <name>Apache Unomi :: Extensions :: JSON Schema</name>
+    <description>TODO</description>
     <packaging>pom</packaging>
 
     <modules>
-        <module>lists-extension</module>
-        <module>privacy-extension</module>
-        <module>geonames</module>
-        <module>router</module>
-        <module>salesforce-connector</module>
-        <module>unomi-mailchimp</module>
-        <module>weather-update</module>
-        <module>web-tracker</module>
-        <module>groovy-actions</module>
+        <module>services</module>
+        <module>rest</module>
     </modules>
 
 </project>
diff --git a/extensions/json-schema/rest/pom.xml b/extensions/json-schema/rest/pom.xml
new file mode 100644
index 000000000..e69f1a8bf
--- /dev/null
+++ b/extensions/json-schema/rest/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.unomi</groupId>
+        <artifactId>unomi-json-schema-root</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>unomi-json-schema-rest</artifactId>
+    <name>Apache Unomi :: Extensions :: JSON Schema :: REST API</name>
+    <description>TODO</description>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-json-schema-services</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-security-cors</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaEndPoint.java b/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java
similarity index 92%
rename from rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaEndPoint.java
rename to extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java
index dfc8900eb..c7115e791 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaEndPoint.java
+++ b/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.unomi.rest.endpoints;
+package org.apache.unomi.schema.rest;
 
 import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
 import org.apache.unomi.api.Metadata;
-import org.apache.unomi.api.services.SchemaService;
+import org.apache.unomi.schema.api.SchemaService;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
@@ -27,15 +27,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.Base64;
@@ -92,6 +84,7 @@ public class JsonSchemaEndPoint {
     @Produces(MediaType.APPLICATION_JSON)
     public Response save(String jsonSchema) {
         schemaService.saveSchema(jsonSchema);
+        // TODO we should return error in case save failed (for example saving a schema with an ID of an already existing predefined schema is forbidden)
         return Response.ok().build();
     }
 
diff --git a/extensions/json-schema/services/pom.xml b/extensions/json-schema/services/pom.xml
new file mode 100644
index 000000000..8a5cee47e
--- /dev/null
+++ b/extensions/json-schema/services/pom.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.unomi</groupId>
+        <artifactId>unomi-json-schema-root</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>unomi-json-schema-services</artifactId>
+    <name>Apache Unomi :: Extensions :: JSON Schema :: Service</name>
+    <description>TODO</description>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <version.schema>1.0.69</version.schema>
+        <version.schema.jackson>2.12.1</version.schema.jackson>
+        <version.schema.itu>1.5.1</version.schema.itu>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-persistence-spi</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <!-- dependencies required for json-schema framework -->
+        <dependency>
+            <groupId>com.networknt</groupId>
+            <artifactId>json-schema-validator</artifactId>
+            <version>${version.schema}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.ethlo.time</groupId>
+            <artifactId>itu</artifactId>
+            <version>${version.schema.itu}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>${version.schema.jackson}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${version.schema.jackson}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>${version.schema.jackson}</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
+                        <Unomi-Source-Folders>${project.basedir}</Unomi-Source-Folders>
+                        <Export-Package>
+                            org.apache.unomi.schema.api
+                        </Export-Package>
+                        <Import-Package>
+                            sun.misc;resolution:=optional,
+                            org.jcodings;resolution:=optional,
+                            org.jcodings.specific;resolution:=optional,
+                            org.joni;resolution:=optional,
+                            org.joni.exception;resolution:=optional,
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-artifacts</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>attach-artifact</goal>
+                        </goals>
+                        <configuration>
+                            <artifacts>
+                                <artifact>
+                                    <file>
+                                        src/main/resources/org.apache.unomi.schema.cfg
+                                    </file>
+                                    <type>cfg</type>
+                                    <classifier>schemacfg</classifier>
+                                </artifact>
+                            </artifacts>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/api/src/main/java/org/apache/unomi/api/schema/UnomiJSONSchema.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/JsonSchemaWrapper.java
similarity index 86%
rename from api/src/main/java/org/apache/unomi/api/schema/UnomiJSONSchema.java
rename to extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/JsonSchemaWrapper.java
index 3ae507709..444a306d8 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/UnomiJSONSchema.java
+++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/JsonSchemaWrapper.java
@@ -14,22 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.unomi.api.schema;
+
+package org.apache.unomi.schema.api;
 
 import org.apache.unomi.api.Metadata;
 import org.apache.unomi.api.MetadataItem;
 
-/**
- * Object which represents a JSON schema stored in the persistence service
- */
-public class UnomiJSONSchema extends MetadataItem {
+public class JsonSchemaWrapper extends MetadataItem {
     public static final String ITEM_TYPE = "jsonSchema";
 
     private String id;
     private String schema;
     private String target;
 
-    public UnomiJSONSchema(){}
+    public JsonSchemaWrapper(){}
 
     /**
      * Instantiates a new JSON schema with an id and a schema as string
@@ -38,7 +36,7 @@ public class UnomiJSONSchema extends MetadataItem {
      * @param schema as string
      * @param target of the schema
      */
-    public UnomiJSONSchema(String id, String schema, String target) {
+    public JsonSchemaWrapper(String id, String schema, String target) {
         super(new Metadata(id));
         this.id = id;
         this.schema = schema;
@@ -68,4 +66,4 @@ public class UnomiJSONSchema extends MetadataItem {
     public void setTarget(String target) {
         this.target = target;
     }
-}
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/unomi/api/services/SchemaService.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java
similarity index 54%
rename from api/src/main/java/org/apache/unomi/api/services/SchemaService.java
rename to extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java
index 7d6e65480..2692891a0 100644
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaService.java
+++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java
@@ -15,12 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.unomi.api.services;
+package org.apache.unomi.schema.api;
 
-import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.unomi.api.Metadata;
 import org.apache.unomi.api.PartialList;
-import org.apache.unomi.api.schema.json.JSONSchema;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -48,11 +46,11 @@ public interface SchemaService {
     /**
      * Verify if a jsonNode is valid against a schema
      *
-     * @param jsonNode   to validate
+     * @param data   to validate
      * @param schemaId id of the schema used for the validation
      * @return true is the object is valid
      */
-    boolean isValid(JsonNode jsonNode, String schemaId);
+    boolean isValid(String data, String schemaId);
 
     /**
      * Get a schema matching by a schema id
@@ -60,15 +58,15 @@ public interface SchemaService {
      * @param schemaId Id of the schema
      * @return A JSON schema
      */
-    JSONSchema getSchema(String schemaId);
+    JsonSchemaWrapper getSchema(String schemaId);
 
     /**
-     * Get a list a {@link org.apache.unomi.api.schema.json.JSONSchema}
+     * Get a list a {@link JsonSchemaWrapper}
      *
      * @param target to filter the schemas
      * @return a list of JSONSchema
      */
-    List<JSONSchema> getSchemasByTarget(String target);
+    List<JsonSchemaWrapper> getSchemasByTarget(String target);
 
     /**
      * Save a new schema or update a schema
@@ -77,20 +75,6 @@ public interface SchemaService {
      */
     void saveSchema(String schema);
 
-    /**
-     * Save a new schema or update a schema
-     *
-     * @param schemaStream inputStream of the schema
-     */
-    void saveSchema(InputStream schemaStream) throws IOException;
-
-    /**
-     * Load a predefined schema into memory
-     *
-     * @param schemaStream inputStream of the schema
-     */
-    void loadPredefinedSchema(InputStream schemaStream);
-
     /**
      * Delete a schema according to its id
      *
@@ -100,56 +84,17 @@ public interface SchemaService {
     boolean deleteSchema(String schemaId);
 
     /**
-     * Delete a schema
-     *
-     * @param schemaStream inputStream of the schema to delete
-     * @return true if the schema has been deleted
-     */
-    boolean deleteSchema(InputStream schemaStream);
-
-    /**
-     * Save an extension of a JSON schema
-     *
-     * @param extensionStream inputStream of the extension
-     */
-    void saveExtension(InputStream extensionStream) throws IOException;
-
-    /**
-     * Save an extension of a JSON schema
-     *
-     * @param extension as String value
-     */
-    void saveExtension(String extension) throws IOException;
-
-    /**
-     * Delete an extension
+     * Load a predefined schema into memory
      *
-     * @param extensionStream inputStream of the extension to delete
-     * @return true if the extension has been deleted
+     * @param schemaStream inputStream of the schema
      */
-    boolean deleteExtension(InputStream extensionStream) throws IOException;
+    void loadPredefinedSchema(InputStream schemaStream) throws IOException;
 
     /**
-     * Delete an extension by an id
+     * unload a predefined schema into memory
      *
-     * @param extensionId id of the extension
-     * @return true if the extension has been deleted
-     */
-    boolean deleteExtension(String extensionId);
-
-    /**
-     * Retrieves json schema extension metadatas, ordered according to the specified {@code sortBy} String and and paged: only {@code size}
-     * of them
-     * are retrieved, starting with the {@code
-     * offset}-th one.
-     *
-     * @param offset zero or a positive integer specifying the position of the first element in the total ordered collection of matching elements
-     * @param size   a positive integer specifying how many matching elements should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy an optional ({@code null} if no sorting is required) String of comma ({@code ,}) separated property names on which ordering should be performed, ordering elements according to the property order in the
-     *               String, considering each in turn and moving on to the next one in case of equality of all preceding ones. Each property name is optionally followed by
-     *               a column ({@code :}) and an order specifier: {@code asc} or {@code desc}.
-     * @return a {@link PartialList} of json schema extension metadata
+     * @param schemaStream inputStream of the schema to delete
+     * @return true if the schema has been deleted
      */
-    PartialList<Metadata> getJsonSchemaExtensionsMetadatas(int offset, int size, String sortBy);
-
+    boolean unloadPredefinedSchema(InputStream schemaStream);
 }
diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java
new file mode 100644
index 000000000..ddd2e4b7d
--- /dev/null
+++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java
@@ -0,0 +1,241 @@
+/*
+ * 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.schema.impl;
+
+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.io.IOUtils;
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.api.PartialList;
+import org.apache.unomi.api.services.SchedulerService;
+import org.apache.unomi.persistence.spi.PersistenceService;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+public class SchemaServiceImpl implements SchemaService {
+
+    private static final String URI = "https://json-schema.org/draft/2019-09/schema";
+
+    private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class.getName());
+
+    ObjectMapper objectMapper = new ObjectMapper();
+
+    private final Map<String, JsonSchemaWrapper> predefinedUnomiJSONSchemaById = new HashMap<>();
+    private Map<String, JsonSchemaWrapper> schemasById = new HashMap<>();
+
+    private Integer jsonSchemaRefreshInterval = 1000;
+    private ScheduledFuture<?> scheduledFuture;
+
+    private BundleContext bundleContext;
+    private PersistenceService persistenceService;
+    private SchedulerService schedulerService;
+    private JsonSchemaFactory jsonSchemaFactory;
+
+
+    @Override
+    public PartialList<Metadata> getJsonSchemaMetadatas(int offset, int size, String sortBy) {
+        PartialList<JsonSchemaWrapper> items = persistenceService.getAllItems(JsonSchemaWrapper.class, offset, size, sortBy);
+        List<Metadata> details = new LinkedList<>();
+        for (JsonSchemaWrapper definition : items.getList()) {
+            details.add(definition.getMetadata());
+        }
+        return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize(), items.getTotalSizeRelation());
+    }
+
+    @Override
+    public boolean isValid(String data, String schemaId) {
+        JsonSchema jsonSchema = null;
+        JsonNode jsonNode = null;
+
+        try {
+            jsonNode = objectMapper.readTree(data);
+            jsonSchema = jsonSchemaFactory.getSchema(new URI(schemaId));
+        } catch (JsonProcessingException | URISyntaxException e) {
+            logger.error("Failed to process data to validate", e);
+            return false;
+        }
+
+        if (jsonNode == null) {
+            logger.warn("No data to validate");
+            return false;
+        }
+
+        if (jsonSchema == null) {
+            logger.warn("No schema found for {}", schemaId);
+            return false;
+        }
+
+        Set<ValidationMessage> validationMessages = jsonSchema.validate(jsonNode);
+        if (validationMessages == null || validationMessages.isEmpty()) {
+            return true;
+        }
+        for (ValidationMessage validationMessage : validationMessages) {
+            logger.error("Error validating object against schema {}: {}", schemaId, validationMessage);
+        }
+        return false;
+    }
+
+    @Override
+    public List<JsonSchemaWrapper> getSchemasByTarget(String target) {
+        return schemasById.values().stream().filter(jsonSchemaWrapper -> jsonSchemaWrapper.getTarget() != null && jsonSchemaWrapper.getTarget().equals(target))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void saveSchema(String schema) {
+        JsonSchema jsonSchema = jsonSchemaFactory.getSchema(schema);
+        JsonNode schemaNode = jsonSchema.getSchemaNode();
+        String id = schemaNode.get("$id").asText();
+
+        if (!predefinedUnomiJSONSchemaById.containsKey(id)) {
+            String target = schemaNode.at("/self/target").asText();
+            String name = schemaNode.at("/self/name").asText();
+
+            if ("events".equals(target) && !name.matches("[_A-Za-z][_0-9A-Za-z]*")) {
+                throw new IllegalArgumentException(
+                        "The \"/self/name\" value should match the following regular expression [_A-Za-z][_0-9A-Za-z]* for the Json schema on events");
+            }
+
+            JsonSchemaWrapper jsonSchemaWrapper = new JsonSchemaWrapper(id, schema, target);
+            persistenceService.save(jsonSchemaWrapper);
+            schemasById.put(id, jsonSchemaWrapper);
+        } else {
+            // TODO we should crash error in case save failed, so that caller can react on save fail and get the reason why using Exceptions
+            logger.error("Trying to save a Json Schema that is using the ID of an existing Json Schema provided by Unomi is forbidden");
+        }
+    }
+
+    @Override
+    public boolean deleteSchema(String schemaId) {
+        // forbidden to delete predefined Unomi schemas
+        if (!predefinedUnomiJSONSchemaById.containsKey(schemaId)) {
+            schemasById.remove(schemaId);
+            return persistenceService.remove(schemaId, JsonSchemaWrapper.class);
+        }
+        return false;
+    }
+
+    @Override
+    public void loadPredefinedSchema(InputStream schemaStream) throws IOException {
+        String jsonSchema = IOUtils.toString(schemaStream);
+
+        // check that schema is valid and get the id
+        JsonNode schemaNode = jsonSchemaFactory.getSchema(jsonSchema).getSchemaNode();
+        String schemaId = schemaNode.get("$id").asText();
+        String target = schemaNode.at("/self/target").asText();
+        JsonSchemaWrapper jsonSchemaWrapper = new JsonSchemaWrapper(schemaId, jsonSchema, target);
+
+        predefinedUnomiJSONSchemaById.put(schemaId, jsonSchemaWrapper);
+        schemasById.put(schemaId, jsonSchemaWrapper);
+    }
+
+    @Override
+    public boolean unloadPredefinedSchema(InputStream schemaStream) {
+        JsonNode schemaNode = jsonSchemaFactory.getSchema(schemaStream).getSchemaNode();
+        String schemaId = schemaNode.get("$id").asText();
+
+        return predefinedUnomiJSONSchemaById.remove(schemaId) != null && schemasById.remove(schemaId) != null;
+    }
+
+    @Override
+    public JsonSchemaWrapper getSchema(String schemaId) {
+        return schemasById.get(schemaId);
+    }
+
+    private URIFetcher getUriFetcher() {
+        return uri -> {
+            logger.debug("Fetching schema {}", uri);
+            JsonSchemaWrapper jsonSchemaWrapper = schemasById.get(uri.toString());
+            if (jsonSchemaWrapper == null) {
+                logger.error("Couldn't find schema {}", uri);
+                return null;
+            }
+            return IOUtils.toInputStream(jsonSchemaWrapper.getSchema());
+        };
+    }
+
+    private void refreshJSONSchemas() {
+        schemasById = new HashMap<>();
+        schemasById.putAll(predefinedUnomiJSONSchemaById);
+
+        persistenceService.getAllItems(JsonSchemaWrapper.class).forEach(
+                JsonSchemaWrapper -> schemasById.put(JsonSchemaWrapper.getId(), JsonSchemaWrapper));
+    }
+
+    private void initializeTimers() {
+        TimerTask task = new TimerTask() {
+            @Override
+            public void run() {
+                refreshJSONSchemas();
+            }
+        };
+        scheduledFuture = schedulerService.getScheduleExecutorService()
+                .scheduleWithFixedDelay(task, 0, jsonSchemaRefreshInterval, TimeUnit.MILLISECONDS);
+    }
+
+    public void init() {
+        JsonMetaSchema jsonMetaSchema = JsonMetaSchema.builder(URI, JsonMetaSchema.getV201909())
+                .addKeyword(new NonValidationKeyword("self"))
+                .build();
+
+        jsonSchemaFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))
+                .addMetaSchema(jsonMetaSchema)
+                .defaultMetaSchemaURI(URI)
+                .uriFetcher(getUriFetcher(), "https", "http")
+                .build();
+
+        initializeTimers();
+        logger.info("Schema service initialized.");
+    }
+
+    public void destroy() {
+        scheduledFuture.cancel(true);
+        logger.info("Schema service shutdown.");
+    }
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    public void setSchedulerService(SchedulerService schedulerService) {
+        this.schedulerService = schedulerService;
+    }
+
+    public void setJsonSchemaRefreshInterval(Integer jsonSchemaRefreshInterval) {
+        this.jsonSchemaRefreshInterval = jsonSchemaRefreshInterval;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+}
diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java
new file mode 100644
index 000000000..9e674d545
--- /dev/null
+++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java
@@ -0,0 +1,137 @@
+/*
+ * 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.schema.listener;
+
+import org.apache.unomi.persistence.spi.PersistenceService;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
+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.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+/**
+ * An implementation of a BundleListener for the JSON schema.
+ * It will load the pre-defined schema files in the folder META-INF/cxs/schemas.
+ * It will load the extension of schema in the folder META-INF/cxs/schemasextensions.
+ * The scripts will be stored in the ES index jsonSchema and the extension will be stored in jsonSchemaExtension
+ */
+public class JsonSchemaListener implements SynchronousBundleListener {
+
+    private static final Logger logger = LoggerFactory.getLogger(JsonSchemaListener.class.getName());
+    public static final String ENTRIES_LOCATION = "META-INF/cxs/schemas";
+
+    private PersistenceService persistenceService;
+    private SchemaService schemaService;
+    private BundleContext bundleContext;
+
+    public void setPersistenceService(PersistenceService persistenceService) {
+        this.persistenceService = persistenceService;
+    }
+
+    public void setSchemaService(SchemaService schemaService) {
+        this.schemaService = schemaService;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public void postConstruct() {
+        logger.info("JSON schema listener initializing...");
+        logger.debug("postConstruct {}", bundleContext.getBundle());
+        createIndexes();
+
+        loadPredefinedSchemas(bundleContext, true);
+
+        for (Bundle bundle : bundleContext.getBundles()) {
+            if (bundle.getBundleContext() != null && bundle.getBundleId() != bundleContext.getBundle().getBundleId()) {
+                loadPredefinedSchemas(bundle.getBundleContext(), true);
+            }
+        }
+
+        bundleContext.addBundleListener(this);
+        logger.info("JSON schema listener initialized.");
+    }
+
+    public void preDestroy() {
+        bundleContext.removeBundleListener(this);
+        logger.info("JSON schema listener shutdown.");
+    }
+
+    private void processBundleStartup(BundleContext bundleContext) {
+        if (bundleContext == null) {
+            return;
+        }
+        loadPredefinedSchemas(bundleContext, true);
+    }
+
+    private void processBundleStop(BundleContext bundleContext) {
+        if (bundleContext == null) {
+            return;
+        }
+        loadPredefinedSchemas(bundleContext, false);
+    }
+
+    public void bundleChanged(BundleEvent event) {
+        switch (event.getType()) {
+            case BundleEvent.STARTED:
+                processBundleStartup(event.getBundle().getBundleContext());
+                break;
+            case BundleEvent.STOPPING:
+                if (!event.getBundle().getSymbolicName().equals(bundleContext.getBundle().getSymbolicName())) {
+                    processBundleStop(event.getBundle().getBundleContext());
+                }
+                break;
+        }
+    }
+
+    public void createIndexes() {
+        if (persistenceService.createIndex(JsonSchemaWrapper.ITEM_TYPE)) {
+            logger.info("{} index created", JsonSchemaWrapper.ITEM_TYPE);
+        } else {
+            logger.info("{} index already exists", JsonSchemaWrapper.ITEM_TYPE);
+        }
+    }
+
+    private void loadPredefinedSchemas(BundleContext bundleContext, boolean load) {
+        Enumeration<URL> predefinedSchemas = bundleContext.getBundle().findEntries(ENTRIES_LOCATION, "*.json", true);
+        if (predefinedSchemas == null) {
+            return;
+        }
+
+        while (predefinedSchemas.hasMoreElements()) {
+            URL predefinedSchemaURL = predefinedSchemas.nextElement();
+            logger.debug("Found predefined JSON schema at {}, {}... ", predefinedSchemaURL, load ? "loading" : "unloading");
+            try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) {
+                if (load) {
+                    schemaService.loadPredefinedSchema(schemaInputStream);
+                } else {
+                    schemaService.unloadPredefinedSchema(schemaInputStream);
+                }
+            } catch (Exception e) {
+                logger.error("Error while {} schema definition {}", load ? "loading" : "unloading", predefinedSchemaURL, e);
+            }
+        }
+    }
+}
diff --git a/services/src/main/resources/META-INF/cxs/schemas/condition.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/condition.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/condition.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/condition.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/conditiontype.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/consent.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/consent.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/consent.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/consent.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/consentType.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/consentType.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/consentType.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/consentType.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitem.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitem.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/customitem.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitem.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitems/page.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/customitems/site.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/event.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/event.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/event.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/event.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/anonymizeProfile.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/anonymizeProfile.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/anonymizeProfile.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/anonymizeProfile.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/articleCompleted.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/articleCompleted.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/articleCompleted.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/articleCompleted.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/form.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/form.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/form.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/form.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/goal.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/goal.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/goal.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/goal.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/identify.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/identify.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/identify.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/identify.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/incrementInterest.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/incrementInterest.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/incrementInterest.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/incrementInterest.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/login.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/login.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/login.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/login.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/modifyConsent.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/profileDeleted.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/profileDeleted.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/profileDeleted.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/profileDeleted.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/profileUpdated.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/profileUpdated.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/profileUpdated.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/profileUpdated.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/ruleFired.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/ruleFired.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/ruleFired.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/ruleFired.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/search.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/search.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/search.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/search.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/sessionCreated.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/sessionCreated.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/sessionCreated.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/sessionCreated.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/sessionReassigned.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/sessionReassigned.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/sessionReassigned.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/sessionReassigned.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/updateProperties.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/updateProperties.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/updateProperties.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/updateProperties.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/events/view.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/view.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/events/view.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/events/view.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/goal.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/goal.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/goal.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/goal.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/item.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/item.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/item.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/item.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/metadata.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/metadata.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/metadata.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/metadata.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/metadataitem.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/parameter.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/parameter.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/parameter.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/parameter.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/personalization/filter.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/filter.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/personalization/filter.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/filter.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizationrequest.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizationrequest.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/personalization/personalizationrequest.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizationrequest.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizedcontent.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizedcontent.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/personalization/personalizedcontent.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/personalizedcontent.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/personalization/target.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/target.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/personalization/target.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/personalization/target.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/profile.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/profile.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/profile.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/profile.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/session.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/session.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/session.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/session.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
similarity index 50%
rename from services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
index b4e1528d3..d7fa16343 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
+++ b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/timestampeditem.json
@@ -4,10 +4,21 @@
   "title": "TimestampedItem",
   "type": "object",
   "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0" }],
-  "properties" : {
-    "timeStamp" : {
-      "type" : ["string"],
-      "format" : "date-time"
+  "oneOf": [
+    {
+      "properties" : {
+        "timeStamp" : {
+          "type" : "string",
+          "format" : "date-time"
+        }
+      }
+    },
+    {
+      "properties" : {
+        "timeStamp" : {
+          "type" : "integer"
+        }
+      }
     }
-  }
+  ]
 }
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/boolean.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/date.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/date.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/date.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/date.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/email.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/email.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/email.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/email.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/integer.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/integer.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/integer.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/integer.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/long.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/long.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/long.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/long.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/set.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/set.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/set.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/set.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/values/string.json b/extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/string.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/values/string.json
rename to extensions/json-schema/services/src/main/resources/META-INF/cxs/schemas/values/string.json
diff --git a/extensions/json-schema/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/extensions/json-schema/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..02e3280c0
--- /dev/null
+++ b/extensions/json-schema/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<blueprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+           xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+    <cm:property-placeholder persistent-id="org.apache.unomi.schema" update-strategy="reload">
+        <cm:default-properties>
+            <cm:property name="json.schema.refresh.interval" value="1000"/>
+        </cm:default-properties>
+    </cm:property-placeholder>
+
+    <reference id="profileService" interface="org.apache.unomi.api.services.ProfileService"/>
+    <reference id="persistenceService" interface="org.apache.unomi.persistence.spi.PersistenceService"/>
+    <reference id="schedulerService" interface="org.apache.unomi.api.services.SchedulerService"/>
+
+    <bean id="schemaServiceImpl" class="org.apache.unomi.schema.impl.SchemaServiceImpl" init-method="init"
+          destroy-method="destroy">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+        <property name="persistenceService" ref="persistenceService"/>
+        <property name="schedulerService" ref="schedulerService"/>
+        <property name="jsonSchemaRefreshInterval" value="${json.schema.refresh.interval}"/>
+    </bean>
+    <service id="schemaService" ref="schemaServiceImpl" interface="org.apache.unomi.schema.api.SchemaService"/>
+
+    <bean id="jsonSchemaListenerImpl" class="org.apache.unomi.schema.listener.JsonSchemaListener"
+          init-method="postConstruct" destroy-method="preDestroy">
+        <property name="persistenceService" ref="persistenceService"/>
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+        <property name="schemaService" ref="schemaServiceImpl"/>
+    </bean>
+    <service id="jsonSchemaListener" ref="jsonSchemaListenerImpl">
+        <interfaces>
+            <value>org.osgi.framework.SynchronousBundleListener</value>
+        </interfaces>
+    </service>
+</blueprint>
diff --git a/extensions/json-schema/services/src/main/resources/org.apache.unomi.schema.cfg b/extensions/json-schema/services/src/main/resources/org.apache.unomi.schema.cfg
new file mode 100644
index 000000000..b930b866f
--- /dev/null
+++ b/extensions/json-schema/services/src/main/resources/org.apache.unomi.schema.cfg
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+# The interval in milliseconds to reload the json schemas in memory
+services.json.schema.refresh.interval=${org.apache.unomi.json.schema.refresh.interval:-1000}
\ No newline at end of file
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 70105e5f5..5b7c58d8c 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -40,6 +40,7 @@
         <module>weather-update</module>
         <module>web-tracker</module>
         <module>groovy-actions</module>
+        <module>json-schema</module>
     </modules>
 
 </project>
diff --git a/graphql/cxs-impl/pom.xml b/graphql/cxs-impl/pom.xml
index d79a7cef2..3ff2923cf 100644
--- a/graphql/cxs-impl/pom.xml
+++ b/graphql/cxs-impl/pom.xml
@@ -149,6 +149,12 @@
             <version>${project.version}</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-json-schema-services</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
 </project>
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 eff196418..84b9ec8bc 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
@@ -16,6 +16,8 @@
  */
 package org.apache.unomi.graphql.schema;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.networknt.schema.JsonSchema;
 import graphql.annotations.AnnotationsSchemaCreator;
 import graphql.annotations.processor.GraphQLAnnotations;
 import graphql.annotations.processor.ProcessingElementsContainer;
@@ -34,11 +36,10 @@ import graphql.schema.GraphQLSchema;
 import graphql.schema.GraphQLType;
 import graphql.schema.visibility.GraphqlFieldVisibility;
 import org.apache.unomi.api.PropertyType;
-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.graphql.schema.json.JSONObjectType;
+import org.apache.unomi.graphql.schema.json.JSONSchema;
+import org.apache.unomi.graphql.schema.json.JSONType;
 import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.graphql.CDPGraphQLConstants;
 import org.apache.unomi.graphql.converters.UnomiToGraphQLConverter;
 import org.apache.unomi.graphql.fetchers.CustomEventOrSetPropertyDataFetcher;
@@ -55,6 +56,7 @@ import org.apache.unomi.graphql.providers.GraphQLMutationProvider;
 import org.apache.unomi.graphql.providers.GraphQLQueryProvider;
 import org.apache.unomi.graphql.providers.GraphQLSubscriptionProvider;
 import org.apache.unomi.graphql.providers.GraphQLTypeFunctionProvider;
+import org.apache.unomi.graphql.schema.json.JSONTypeFactory;
 import org.apache.unomi.graphql.types.input.CDPEventFilterInput;
 import org.apache.unomi.graphql.types.input.CDPEventInput;
 import org.apache.unomi.graphql.types.input.CDPEventProcessor;
@@ -69,8 +71,11 @@ import org.apache.unomi.graphql.types.output.CDPPersona;
 import org.apache.unomi.graphql.types.output.CDPProfile;
 import org.apache.unomi.graphql.types.output.RootMutation;
 import org.apache.unomi.graphql.types.output.RootQuery;
+import org.apache.unomi.graphql.utils.GraphQLObjectMapper;
 import org.apache.unomi.graphql.utils.ReflectionUtil;
 import org.apache.unomi.graphql.utils.StringUtils;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -331,7 +336,8 @@ public class GraphQLSchemaProvider {
     }
 
     private void registerDynamicUnomiInputEvents(GraphQLSchema.Builder schemaBuilder) {
-        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events");
+        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events").stream()
+                .map(jsonSchemaWrapper -> buildJSONSchema(jsonSchemaWrapper, schemaService)).collect(Collectors.toList());
 
         if (!unomiEventTypes.isEmpty()) {
             for (JSONSchema unomiEventType : unomiEventTypes) {
@@ -353,7 +359,8 @@ public class GraphQLSchemaProvider {
     }
 
     private void registerDynamicUnomiOutputEvents(GraphQLSchema.Builder schemaBuilder) {
-        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events");
+        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events").stream()
+                .map(jsonSchemaWrapper -> buildJSONSchema(jsonSchemaWrapper, schemaService)).collect(Collectors.toList());
 
         if (!unomiEventTypes.isEmpty()) {
             final GraphQLCodeRegistry.Builder codeRegisterBuilder = graphQLAnnotations.getContainer().getCodeRegistryBuilder();
@@ -650,7 +657,8 @@ public class GraphQLSchemaProvider {
         }
 
         // now add all unomi defined event types
-        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events");
+        final List<JSONSchema> unomiEventTypes = schemaService.getSchemasByTarget("events").stream()
+                .map(jsonSchemaWrapper -> buildJSONSchema(jsonSchemaWrapper, schemaService)).collect(Collectors.toList());
         unomiEventTypes.forEach(eventType -> {
             final String typeName = UnomiToGraphQLConverter.convertEventType(eventType.getName());
             final GraphQLInputType eventInputType = (GraphQLInputType) getFromTypeRegistry(typeName + "Input");
@@ -668,6 +676,17 @@ public class GraphQLSchemaProvider {
         registerInTypeRegistry(CDPEventInput.TYPE_NAME, builder.build());
     }
 
+    public static JSONSchema buildJSONSchema(JsonSchemaWrapper jsonSchemaWrapper, SchemaService schemaService) {
+        Map<String, Object> schemaMap;
+        try {
+            schemaMap = GraphQLObjectMapper.getInstance().readValue(jsonSchemaWrapper.getSchema(), Map.class);
+        } catch (JsonProcessingException e) {
+            logger.error("Failed to process Json object, e");
+            schemaMap = Collections.emptyMap();
+        }
+        return new JSONSchema(schemaMap, new JSONTypeFactory(schemaService));
+    }
+
     private void registerDynamicEventFilterInputFields() {
         final List<GraphQLInputObjectField> fieldDefinitions = new ArrayList<>();
 
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 7d6198d93..37cd40a09 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
@@ -21,7 +21,6 @@ import graphql.execution.SubscriptionExecutionStrategy;
 import graphql.schema.GraphQLCodeRegistry;
 import graphql.schema.GraphQLSchema;
 import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.graphql.fetchers.event.UnomiEventPublisher;
 import org.apache.unomi.graphql.providers.GraphQLAdditionalTypesProvider;
 import org.apache.unomi.graphql.providers.GraphQLCodeRegistryProvider;
@@ -37,6 +36,7 @@ import org.apache.unomi.graphql.types.output.CDPPersona;
 import org.apache.unomi.graphql.types.output.CDPProfile;
 import org.apache.unomi.graphql.types.output.CDPProfileInterface;
 import org.apache.unomi.graphql.types.output.CDPPropertyInterface;
+import org.apache.unomi.schema.api.SchemaService;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONArrayType.java
similarity index 96%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONArrayType.java
index aa8cc2a34..427b31e18 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONArrayType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONArrayType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.List;
 import java.util.Map;
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONBooleanType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONBooleanType.java
index aea431e78..79f541ec7 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONBooleanType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONBooleanType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONEnumType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONEnumType.java
index 57ba1e668..6cee489a9 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONEnumType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONEnumType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONIntegerType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONIntegerType.java
index 9ae40dd84..e873d12fb 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONIntegerType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONIntegerType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNullType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNullType.java
index 809a29fea..3cdd3ce5a 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONNullType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNullType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNumberType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNumberType.java
index d5917772f..6233217d7 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONNumberType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONNumberType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java
similarity index 97%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java
index da28f41e3..be91e0a2b 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONObjectType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.HashMap;
 import java.util.List;
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONSchema.java
similarity index 98%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONSchema.java
index 1e65f8e6e..fe159b0a0 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONSchema.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONSchema.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.unomi.api.schema.json;
+package org.apache.unomi.graphql.schema.json;
 
 import org.apache.unomi.api.PluginType;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONStringType.java
similarity index 95%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONStringType.java
index c63f6b5c5..238c61853 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONStringType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONStringType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.Map;
 
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONType.java
similarity index 98%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONType.java
index d1c047438..2f8afa290 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONType.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONType.java
@@ -14,7 +14,7 @@
  * 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.graphql.schema.json;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java
similarity index 89%
rename from api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java
rename to graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java
index 33f4b72fb..6b1ab8255 100644
--- a/api/src/main/java/org/apache/unomi/api/schema/json/JSONTypeFactory.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java
@@ -14,9 +14,11 @@
  * 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.graphql.schema.json;
 
-import org.apache.unomi.api.services.SchemaService;
+import org.apache.unomi.graphql.schema.GraphQLSchemaProvider;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,9 +51,9 @@ public class JSONTypeFactory {
     List<JSONType> getTypes(Map<String, Object> schemaTree) {
         if (schemaTree.containsKey("$ref")) {
             String schemaId = (String) schemaTree.get("$ref");
-            JSONSchema refSchema = schemaService.getSchema(schemaId);
+            JsonSchemaWrapper refSchema = schemaService.getSchema(schemaId);
             if (refSchema != null) {
-                schemaTree = refSchema.getSchemaTree();
+                schemaTree = GraphQLSchemaProvider.buildJSONSchema(refSchema, schemaService).getSchemaTree();
             } else {
                 System.err.println("Couldn't find schema for ref " + schemaId);
             }
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 2d6cebbdd..1ded2441a 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,11 +18,13 @@ package org.apache.unomi.graphql.types.resolvers;
 
 import graphql.TypeResolutionEnvironment;
 import graphql.schema.GraphQLObjectType;
-import org.apache.unomi.api.schema.json.JSONSchema;
-import org.apache.unomi.api.services.SchemaService;
+import org.apache.unomi.graphql.schema.GraphQLSchemaProvider;
+import org.apache.unomi.graphql.schema.json.JSONSchema;
 import org.apache.unomi.graphql.converters.UnomiToGraphQLConverter;
 import org.apache.unomi.graphql.services.ServiceManager;
 import org.apache.unomi.graphql.types.output.CDPEventInterface;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
 
 public class CDPEventInterfaceResolver extends BaseTypeResolver {
 
@@ -32,11 +34,10 @@ public class CDPEventInterfaceResolver extends BaseTypeResolver {
         SchemaService schemaService = serviceManager.getService(SchemaService.class);
 
         final CDPEventInterface eventInterface = env.getObject();
-        final JSONSchema eventSchema =
-                schemaService.getSchema("https://unomi.apache.org/schemas/json/events/" + eventInterface.getEvent().getEventType() + "/1-0"
-                        + "-0");
+        final JsonSchemaWrapper eventSchema = schemaService.getSchema("https://unomi.apache.org/schemas/json/events/" + eventInterface.getEvent().getEventType() + "/1-0-0");
         if (eventSchema != null) {
-            final String typeName = UnomiToGraphQLConverter.convertEventType(eventSchema.getName());
+            final JSONSchema jsonSchema = GraphQLSchemaProvider.buildJSONSchema(eventSchema, schemaService);
+            final String typeName = UnomiToGraphQLConverter.convertEventType(jsonSchema.getName());
             return env.getSchema().getObjectType(typeName);
         } else {
             return super.getType(env);
diff --git a/itests/src/test/java/org/apache/unomi/itests/JSONSchemaIT.java b/itests/src/test/java/org/apache/unomi/itests/JSONSchemaIT.java
index 5b14aa7c0..e3fc2c40c 100644
--- a/itests/src/test/java/org/apache/unomi/itests/JSONSchemaIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/JSONSchemaIT.java
@@ -19,10 +19,9 @@ package org.apache.unomi.itests;
 
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.entity.ContentType;
-import org.apache.unomi.api.schema.UnomiJSONSchema;
-import org.apache.unomi.api.schema.JSONSchemaExtension;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.persistence.spi.PersistenceService;
+import org.apache.unomi.schema.api.JsonSchemaWrapper;
+import org.apache.unomi.schema.api.SchemaService;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -50,7 +49,6 @@ import static org.junit.Assert.assertTrue;
 @ExamReactorStrategy(PerSuite.class)
 public class JSONSchemaIT extends BaseIT {
     private final static String JSONSCHEMA_URL = "/cxs/jsonSchema";
-    private final static String JSONSCHEMAEXTENSION_URL = "/cxs/jsonSchemaExtension";
     private static final int DEFAULT_TRYING_TIMEOUT = 2000;
     private static final int DEFAULT_TRYING_TRIES = 30;
 
@@ -66,14 +64,11 @@ public class JSONSchemaIT extends BaseIT {
     public void setUp() throws InterruptedException {
         keepTrying("Couldn't find json schema endpoint", () -> get(JSONSCHEMA_URL, List.class), Objects::nonNull, DEFAULT_TRYING_TIMEOUT,
                 DEFAULT_TRYING_TRIES);
-        keepTrying("Couldn't find json schema extension endpoint", () -> get(JSONSCHEMAEXTENSION_URL, List.class), Objects::nonNull,
-                DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
     }
 
     @After
     public void tearDown() {
         schemaService.deleteSchema("https://unomi.apache.org/schemas/json/events/testEventType/1-0-0");
-        schemaService.deleteExtension("extension-test-event-1");
     }
 
     @Test
@@ -92,7 +87,7 @@ public class JSONSchemaIT extends BaseIT {
     @Test
     public void testSaveNewValidJSONSchema() throws InterruptedException {
 
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(UnomiJSONSchema.class).isEmpty());
+        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JsonSchemaWrapper.class).isEmpty());
 
         CloseableHttpResponse response = post(JSONSCHEMA_URL, "schemas/events/test-event-type.json", ContentType.TEXT_PLAIN);
 
@@ -104,7 +99,7 @@ public class JSONSchemaIT extends BaseIT {
 
     @Test
     public void testDeleteJSONSchema() throws InterruptedException {
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(UnomiJSONSchema.class).isEmpty());
+        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JsonSchemaWrapper.class).isEmpty());
 
         post(JSONSCHEMA_URL, "schemas/events/test-event-type.json", ContentType.TEXT_PLAIN);
 
@@ -124,7 +119,7 @@ public class JSONSchemaIT extends BaseIT {
 
     @Test
     public void testSaveNewInvalidJSONSchema() throws IOException {
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(UnomiJSONSchema.class).isEmpty());
+        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JsonSchemaWrapper.class).isEmpty());
         try (CloseableHttpResponse response = post(JSONSCHEMA_URL, "schemas/events/test-invalid.json", ContentType.TEXT_PLAIN)) {
             assertEquals("Save should have failed", 500, response.getStatusLine().getStatusCode());
         }
@@ -132,52 +127,9 @@ public class JSONSchemaIT extends BaseIT {
 
     @Test
     public void testSaveSchemaWithInvalidName() throws IOException {
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(UnomiJSONSchema.class).isEmpty());
+        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JsonSchemaWrapper.class).isEmpty());
         try (CloseableHttpResponse response = post(JSONSCHEMA_URL, "schemas/events/test-invalid-name.json", ContentType.TEXT_PLAIN)) {
             assertEquals("Save should have failed", 500, response.getStatusLine().getStatusCode());
         }
     }
-    @Test
-    public void testGetJsonSchemaExtensionsMetadatas() throws InterruptedException {
-        List jsonSchemaExtensions = get(JSONSCHEMAEXTENSION_URL, List.class);
-        assertTrue("JSON schema extension list should be empty", jsonSchemaExtensions.isEmpty());
-
-        post(JSONSCHEMAEXTENSION_URL, "schemas/extension/extension-test-event-example.json", ContentType.TEXT_PLAIN);
-
-        jsonSchemaExtensions = keepTrying("Couldn't find json extensions", () -> get(JSONSCHEMAEXTENSION_URL, List.class),
-                (list) -> !list.isEmpty(), DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
-        assertFalse("JSON schema list should not be empty", jsonSchemaExtensions.isEmpty());
-        assertEquals("JSON schema list should not be empty", 1, jsonSchemaExtensions.size());
-    }
-
-    @Test
-    public void testSaveNewJSONSchemaExtension() throws InterruptedException {
-
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JSONSchemaExtension.class).isEmpty());
-
-        CloseableHttpResponse response = post(JSONSCHEMAEXTENSION_URL, "schemas/extension/extension-test-event-example.json",
-                ContentType.TEXT_PLAIN);
-
-        assertEquals("Invalid response code", 200, response.getStatusLine().getStatusCode());
-
-        keepTrying("Couldn't find json schemas extensions", () -> get(JSONSCHEMAEXTENSION_URL, List.class), (list) -> !list.isEmpty(),
-                DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
-    }
-
-    @Test
-    public void testDeleteJSONSchemaExtension() throws InterruptedException {
-        assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JSONSchemaExtension.class).isEmpty());
-
-        post(JSONSCHEMAEXTENSION_URL, "schemas/extension/extension-test-event-example.json", ContentType.TEXT_PLAIN);
-
-        keepTrying("Couldn't find json schemas extension", () -> get(JSONSCHEMAEXTENSION_URL, List.class), (list) -> !list.isEmpty(),
-                DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
-
-        CloseableHttpResponse response = delete(JSONSCHEMAEXTENSION_URL + "/extension-test-event-1");
-        assertEquals("Invalid response code", 204, response.getStatusLine().getStatusCode());
-
-        keepTrying("wait for empty list of schemas extensions", () -> get(JSONSCHEMAEXTENSION_URL, List.class), List::isEmpty,
-                DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
-    }
-
 }
diff --git a/itests/src/test/resources/schemas/extension/extension-test-event-example.json b/itests/src/test/resources/schemas/extension/extension-test-event-example.json
deleted file mode 100644
index e03feccd8..000000000
--- a/itests/src/test/resources/schemas/extension/extension-test-event-example.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "id": "extension-test-event-1",
-  "schemaId": "https://unomi.apache.org/schemas/json/events/test-event-type/1-0-0",
-  "description": "An event for example",
-  "name": "Name of the event",
-  "priority": 10,
-  "extension": {
-    "allOf": [
-      {
-        "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
-      }
-    ],
-    "properties": {
-      "properties": {
-        "type": "object",
-        "properties": {
-          "floatProperty": {
-            "type": "number",
-            "maximum": "100",
-            "description": "Extension of float property"
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/kar/pom.xml b/kar/pom.xml
index f25e555f9..23824b273 100644
--- a/kar/pom.xml
+++ b/kar/pom.xml
@@ -114,6 +114,11 @@
             <artifactId>cxs-geonames-rest</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-json-schema-services</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.unomi</groupId>
             <artifactId>unomi-groovy-actions-services</artifactId>
diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml
index 3b0d695ea..704061013 100644
--- a/kar/src/main/feature/feature.xml
+++ b/kar/src/main/feature/feature.xml
@@ -45,6 +45,7 @@
         <configfile finalname="/etc/hazelcast.xml">mvn:org.apache.unomi/unomi-services/${project.version}/xml/hazelcastconfig</configfile>
         <configfile finalname="/etc/org.apache.unomi.geonames.cfg">mvn:org.apache.unomi/cxs-geonames-services/${project.version}/cfg/geonamescfg</configfile>
         <configfile finalname="/etc/org.apache.unomi.groovy.actions.cfg">mvn:org.apache.unomi/unomi-groovy-actions-services/${project.version}/cfg/groovyactionscfg</configfile>
+        <configfile finalname="/etc/org.apache.unomi.schema.cfg">mvn:org.apache.unomi/unomi-json-schema-services/${project.version}/cfg/schemacfg</configfile>
         <bundle start-level="75">mvn:commons-io/commons-io/2.4</bundle>
         <bundle start-level="75">mvn:com.fasterxml.jackson.core/jackson-core/${version.jackson.core}</bundle>
         <bundle start-level="75">mvn:com.github.fge/btf/1.2</bundle>
@@ -72,6 +73,8 @@
         <bundle start-level="75" start="false">mvn:org.apache.unomi/unomi-persistence-spi/${project.version}</bundle>
         <bundle start-level="76" start="false">mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}</bundle>
         <bundle start-level="77" start="false">mvn:org.apache.unomi/unomi-services/${project.version}</bundle>
+        <bundle start-level="77" start="false">mvn:org.apache.unomi/unomi-json-schema-services/${project.version}</bundle>
+        <bundle start-level="77" start="false">mvn:org.apache.unomi/unomi-json-schema-rest/${project.version}</bundle>
         <bundle start-level="77" start="false">mvn:org.apache.unomi/cxs-lists-extension-services/${project.version}</bundle>
         <bundle start-level="77" start="false">mvn:org.apache.unomi/cxs-lists-extension-rest/${project.version}</bundle>
         <bundle start-level="77" start="false">mvn:org.apache.unomi/cxs-geonames-services/${project.version}</bundle>
diff --git a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 050a2ae19..4eb80acb1 100644
--- a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -49,6 +49,8 @@
                 <entry key="org.apache.unomi.cxs-geonames-rest" value="false"/>
                 <entry key="org.apache.unomi.cxs-privacy-extension-services" value="false"/>
                 <entry key="org.apache.unomi.cxs-privacy-extension-rest" value="false"/>
+                <entry key="org.apache.unomi.json-schema-services" value="false"/>
+                <entry key="org.apache.unomi.json-schema-rest" value="false"/>
                 <entry key="org.apache.unomi.rest" value="false"/>
                 <entry key="org.apache.unomi.wab" value="false"/>
                 <entry key="org.apache.unomi.plugins-base" value="false"/>
diff --git a/rest/pom.xml b/rest/pom.xml
index 77ae8fc83..6631e9f72 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -43,6 +43,12 @@
             <artifactId>unomi-persistence-spi</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-json-schema-services</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
index ad3394596..ba9d9aa50 100644
--- a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
@@ -27,8 +27,8 @@ import org.apache.unomi.api.Event;
 import org.apache.unomi.api.Item;
 import org.apache.unomi.api.Profile;
 import org.apache.unomi.api.services.PersonalizationService;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.rest.exception.InvalidRequestException;
+import org.apache.unomi.schema.api.SchemaService;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -55,7 +55,7 @@ public class ContextRequestDeserializer extends StdDeserializer<ContextRequest>
     public ContextRequest deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
         JsonNode node = jsonParser.getCodec().readTree(jsonParser);
         // Validate schema on it
-        if (!schemaService.isValid(node, "https://unomi.apache.org/schemas/json/contextrequest/1-0-0")) {
+        if (!schemaService.isValid(node.toString(), "https://unomi.apache.org/schemas/json/contextrequest/1-0-0")) {
             throw new InvalidRequestException("Invalid Context request object", "Invalid received data");
         }
         ContextRequest cr = new ContextRequest();
@@ -86,7 +86,7 @@ public class ContextRequestDeserializer extends StdDeserializer<ContextRequest>
             ArrayNode events = (ArrayNode) eventsNode;
             List<Event> filteredEvents = new ArrayList<>();
             for (JsonNode event : events) {
-                if (schemaService.isValid(event, "https://unomi.apache.org/schemas/json/events/" + event.get("eventType").textValue() + "/1-0-0")) {
+                if (schemaService.isValid(event.toString(), "https://unomi.apache.org/schemas/json/events/" + event.get("eventType").textValue() + "/1-0-0")) {
                     filteredEvents.add(jsonParser.getCodec().treeToValue(event, Event.class));
                 }
             }
diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
index 0f234192e..20d808d8a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
@@ -24,8 +24,8 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import org.apache.unomi.api.Event;
 import org.apache.unomi.api.EventsCollectorRequest;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.rest.exception.InvalidRequestException;
+import org.apache.unomi.schema.api.SchemaService;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -50,7 +50,7 @@ public class EventsCollectorRequestDeserializer extends StdDeserializer<EventsCo
     @Override
     public EventsCollectorRequest deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
         JsonNode node = jsonParser.getCodec().readTree(jsonParser);
-        if (!schemaService.isValid(node, "https://unomi.apache.org/schemas/json/eventscollectorrequest/1-0-0")) {
+        if (!schemaService.isValid(node.toString(), "https://unomi.apache.org/schemas/json/eventscollectorrequest/1-0-0")) {
             throw new InvalidRequestException("Invalid events collector object", "Invalid received data");
         }
 
@@ -59,7 +59,7 @@ public class EventsCollectorRequestDeserializer extends StdDeserializer<EventsCo
         final JsonNode eventsNode = node.get("events");
         if (eventsNode instanceof ArrayNode) {
             for (JsonNode event : eventsNode) {
-                if (schemaService.isValid(event, "https://unomi.apache.org/schemas/json/events/" + event.get("eventType").textValue() + "/1-0-0")) {
+                if (schemaService.isValid(event.toString(), "https://unomi.apache.org/schemas/json/events/" + event.get("eventType").textValue() + "/1-0-0")) {
                     filteredEvents.add(jsonParser.getCodec().treeToValue(event, Event.class));
                 }
             }
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
index 324216586..3f84bf15b 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
@@ -18,7 +18,6 @@
 package org.apache.unomi.rest.endpoints;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.commons.lang3.StringUtils;
@@ -26,10 +25,10 @@ import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
 import org.apache.unomi.api.*;
 import org.apache.unomi.api.conditions.Condition;
 import org.apache.unomi.api.services.*;
-import org.apache.unomi.api.utils.ValidationPattern;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.apache.unomi.rest.exception.InvalidRequestException;
 import org.apache.unomi.rest.service.RestServiceUtils;
+import org.apache.unomi.schema.api.SchemaService;
 import org.apache.unomi.utils.Changes;
 import org.apache.unomi.utils.HttpUtils;
 import org.osgi.service.component.annotations.Component;
@@ -43,8 +42,6 @@ import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import javax.validation.constraints.Pattern;
 import javax.ws.rs.*;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
@@ -57,7 +54,6 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
-import java.util.Objects;
 
 @WebService
 @Consumes(MediaType.APPLICATION_JSON)
@@ -164,7 +160,7 @@ public class ContextJsonEndpoint {
         if (sessionId != null) {
             paramsAsJson.put("sessionId", sessionId);
         }
-        if (!schemaService.isValid(paramsAsJson, "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0")) {
+        if (!schemaService.isValid(paramsAsJson.toString(), "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0")) {
             throw new InvalidRequestException("Invalid parameter", "Invalid received data");
         }
         Date timestamp = new Date();
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaExtensionEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaExtensionEndPoint.java
deleted file mode 100644
index 5033124e8..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/JsonSchemaExtensionEndPoint.java
+++ /dev/null
@@ -1,109 +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.rest.endpoints;
-
-import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.apache.unomi.api.Metadata;
-import org.apache.unomi.api.services.SchemaService;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.util.List;
-
-@WebService
-@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
-@CrossOriginResourceSharing(allowAllOrigins = true, allowCredentials = true)
-@Path("/jsonSchemaExtension")
-@Component(service = JsonSchemaExtensionEndPoint.class, property = "osgi.jaxrs.resource=true")
-public class JsonSchemaExtensionEndPoint {
-
-    private static final Logger logger = LoggerFactory.getLogger(JsonSchemaExtensionEndPoint.class.getName());
-
-    @Reference
-    private SchemaService schemaService;
-
-    public JsonSchemaExtensionEndPoint() {
-        logger.info("Initializing JSON schema extension endpoint...");
-    }
-
-    @WebMethod(exclude = true)
-    public void setSchemaService(SchemaService schemaService) {
-        this.schemaService = schemaService;
-    }
-
-    /**
-     * Retrieves the 50 first json schema extension metadatas by default.
-     *
-     * @param offset zero or a positive integer specifying the position of the first element in the total ordered collection of matching elements
-     * @param size   a positive integer specifying how many matching elements should be retrieved or {@code -1} if all of them should be retrieved
-     * @param sortBy an optional ({@code null} if no sorting is required) String of comma ({@code ,}) separated property names on which ordering should be performed, ordering
-     *               elements according to the property order in the
-     *               String, considering each in turn and moving on to the next one in case of equality of all preceding ones. Each property name is optionally followed by
-     *               a column ({@code :}) and an order specifier: {@code asc} or {@code desc}.
-     * @return a List of the 50 first json schema metadata
-     */
-    @GET
-    @Path("/")
-    public List<Metadata> getJsonSchemaExtensionsMetadatas(@QueryParam("offset") @DefaultValue("0") int offset,
-            @QueryParam("size") @DefaultValue("50") int size, @QueryParam("sort") String sortBy) {
-        return schemaService.getJsonSchemaExtensionsMetadatas(offset, size, sortBy).getList();
-    }
-
-    /**
-     * Save a JSON schema extension
-     *
-     * @param jsonSchemaExtension the schema as string to save
-     * @return Response of the API call
-     */
-    @POST
-    @Path("/")
-    @Consumes(MediaType.TEXT_PLAIN)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response save(String jsonSchemaExtension) throws IOException {
-        schemaService.saveExtension(jsonSchemaExtension);
-        return Response.ok().build();
-    }
-
-    /**
-     * Deletes a JSON schema extension.
-     * The id is a Base64 id as the id have is basically an URL
-     *
-     * @param id the identifier of the JSON schema that we want to delete
-     */
-    @DELETE
-    @Path("/{id}")
-    public void remove(@PathParam("id") String id) {
-        schemaService.deleteExtension(id);
-    }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
index 0da55b996..f2b85feb7 100644
--- a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
@@ -30,7 +30,6 @@ import org.apache.cxf.message.Message;
 import org.apache.unomi.api.ContextRequest;
 import org.apache.unomi.api.EventsCollectorRequest;
 import org.apache.unomi.api.services.ConfigSharingService;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.rest.authentication.AuthenticationFilter;
 import org.apache.unomi.rest.authentication.AuthorizingInterceptor;
 import org.apache.unomi.rest.authentication.RestAuthenticationConfig;
@@ -38,6 +37,7 @@ import org.apache.unomi.rest.deserializers.ContextRequestDeserializer;
 import org.apache.unomi.rest.deserializers.EventsCollectorRequestDeserializer;
 import org.apache.unomi.rest.server.provider.RetroCompatibilityParamConverterProvider;
 import org.apache.unomi.rest.validation.request.RequestValidatorInterceptor;
+import org.apache.unomi.schema.api.SchemaService;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.ServiceReference;
diff --git a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
index 4600f0c1e..ac617d3d7 100644
--- a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
+++ b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
@@ -17,7 +17,6 @@
 package org.apache.unomi.rest.service.impl;
 
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.TextNode;
 import org.apache.unomi.api.Event;
 import org.apache.unomi.api.Persona;
 import org.apache.unomi.api.Profile;
@@ -25,9 +24,9 @@ import org.apache.unomi.api.Session;
 import org.apache.unomi.api.services.ConfigSharingService;
 import org.apache.unomi.api.services.EventService;
 import org.apache.unomi.api.services.PrivacyService;
-import org.apache.unomi.api.services.SchemaService;
 import org.apache.unomi.rest.exception.InvalidRequestException;
 import org.apache.unomi.rest.service.RestServiceUtils;
+import org.apache.unomi.schema.api.SchemaService;
 import org.apache.unomi.utils.Changes;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
@@ -38,7 +37,6 @@ import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.BadRequestException;
 import java.util.Date;
 import java.util.List;
 
@@ -56,7 +54,8 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
     @Reference
     private EventService eventService;
 
-    @Reference SchemaService schemaService;
+    @Reference
+    SchemaService schemaService;
 
     public String getProfileIdCookieValue(HttpServletRequest httpServletRequest) {
         String cookieProfileId = null;
@@ -67,7 +66,7 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
             for (Cookie cookie : cookies) {
                 final Object profileIdCookieName = configSharingService.getProperty("profileIdCookieName");
                 if (profileIdCookieName.equals(cookie.getName())) {
-                    if (!schemaService.isValid(JsonNodeFactory.instance.objectNode().put("profileIdCookieName", cookie.getValue()), "https://unomi.apache.org/schemas/json/cookie/1-0-0")) {
+                    if (!schemaService.isValid(JsonNodeFactory.instance.objectNode().put("profileIdCookieName", cookie.getValue()).toString(), "https://unomi.apache.org/schemas/json/cookie/1-0-0")) {
                         throw new InvalidRequestException("Invalid profile ID format in cookie", "Invalid received data");
                     }
                     cookieProfileId = cookie.getValue();
diff --git a/services/src/main/resources/META-INF/cxs/schemas/contextrequest.json b/rest/src/main/resources/META-INF/cxs/schemas/contextrequest.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/contextrequest.json
rename to rest/src/main/resources/META-INF/cxs/schemas/contextrequest.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json b/rest/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
rename to rest/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/cookie.json b/rest/src/main/resources/META-INF/cxs/schemas/cookie.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/cookie.json
rename to rest/src/main/resources/META-INF/cxs/schemas/cookie.json
diff --git a/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json b/rest/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
similarity index 100%
rename from services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
rename to rest/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
diff --git a/services/pom.xml b/services/pom.xml
index c4acbb2f5..3f41968ee 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -171,13 +171,6 @@
             <version>${project.version}</version>
             <scope>provided</scope>
         </dependency>
-
-        <dependency>
-            <groupId>com.networknt</groupId>
-            <artifactId>json-schema-validator</artifactId>
-            <version>1.0.49</version>
-        </dependency>
-
     </dependencies>
 
     <build>
@@ -191,10 +184,6 @@
                         <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                         <Import-Package>
                             sun.misc;resolution:=optional,
-                            org.jcodings;resolution:=optional,
-                            org.jcodings.specific;resolution:=optional,
-                            org.joni;resolution:=optional,
-                            org.joni.exception;resolution:=optional,
                             *
                         </Import-Package>
                     </instructions>
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 736de11cb..5b81819b9 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
@@ -65,8 +65,6 @@ public class EventServiceImpl implements EventService {
 
     private BundleContext bundleContext;
 
-    private SchemaService schemaService;
-
     private Set<String> predefinedEventTypeIds = new LinkedHashSet<String>();
 
     private Set<String> restrictedEventTypeIds = new LinkedHashSet<String>();
@@ -114,9 +112,6 @@ public class EventServiceImpl implements EventService {
         this.shouldBeCheckedEventSourceId = shouldBeCheckedEventSourceId;
     }
 
-    public void setSchemaService(SchemaService schemaService) {
-        this.schemaService = schemaService;
-    }
     public void setPersistenceService(PersistenceService persistenceService) {
         this.persistenceService = persistenceService;
     }
diff --git a/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaServiceImpl.java
deleted file mode 100644
index 56d70f29c..000000000
--- a/services/src/main/java/org/apache/unomi/services/impl/schemas/SchemaServiceImpl.java
+++ /dev/null
@@ -1,339 +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.schemas;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.networknt.schema.JsonMetaSchema;
-import com.networknt.schema.JsonSchema;
-import com.networknt.schema.JsonSchemaFactory;
-import com.networknt.schema.NonValidationKeyword;
-import com.networknt.schema.SpecVersion;
-import com.networknt.schema.ValidationMessage;
-import com.networknt.schema.uri.URIFetcher;
-import org.apache.commons.io.IOUtils;
-import org.apache.unomi.api.Metadata;
-import org.apache.unomi.api.PartialList;
-import org.apache.unomi.api.schema.JSONSchemaExtension;
-import org.apache.unomi.api.schema.UnomiJSONSchema;
-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.SchedulerService;
-import org.apache.unomi.api.services.SchemaService;
-import org.apache.unomi.persistence.spi.CustomObjectMapper;
-import org.apache.unomi.persistence.spi.PersistenceService;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TimerTask;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-public class SchemaServiceImpl implements SchemaService {
-
-    private static final String URI = "https://json-schema.org/draft/2019-09/schema";
-
-    private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class.getName());
-
-    private final Map<String, JSONSchema> predefinedUnomiJSONSchemaById = new HashMap<>();
-
-    private Map<String, JSONSchema> schemasById = new HashMap<>();
-
-    private Map<String, JSONSchemaExtension> extensionById = new HashMap<>();
-
-    private BundleContext bundleContext;
-
-    private ProfileService profileService;
-
-    private PersistenceService persistenceService;
-
-    private SchedulerService schedulerService;
-
-    private JsonSchemaFactory jsonSchemaFactory;
-
-    ObjectMapper objectMapper = new ObjectMapper();
-
-    private ScheduledFuture<?> scheduledFuture;
-
-    private Integer jsonSchemaRefreshInterval = 1000;
-
-    public void setPersistenceService(PersistenceService persistenceService) {
-        this.persistenceService = persistenceService;
-    }
-
-    public void setSchedulerService(SchedulerService schedulerService) {
-        this.schedulerService = schedulerService;
-    }
-
-    public void setJsonSchemaRefreshInterval(Integer jsonSchemaRefreshInterval) {
-        this.jsonSchemaRefreshInterval = jsonSchemaRefreshInterval;
-    }
-
-    @Override
-    public PartialList<Metadata> getJsonSchemaMetadatas(int offset, int size, String sortBy) {
-        PartialList<UnomiJSONSchema> items = persistenceService.getAllItems(UnomiJSONSchema.class, offset, size, sortBy);
-        List<Metadata> details = new LinkedList<>();
-        for (UnomiJSONSchema definition : items.getList()) {
-            details.add(definition.getMetadata());
-        }
-        return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize(), items.getTotalSizeRelation());
-    }
-
-    @Override
-    public boolean isValid(JsonNode jsonNode, String schemaId) {
-        String schemaAsString;
-        JsonSchema jsonSchema = null;
-        try {
-            JSONSchema validationSchema = schemasById.get(schemaId);
-            if (validationSchema != null) {
-                schemaAsString = objectMapper.writeValueAsString(schemasById.get(schemaId).getSchemaTree());
-                jsonSchema = jsonSchemaFactory.getSchema(schemaAsString);
-            } else {
-                logger.warn("No schema found for {}", schemaId);
-            }
-        } catch (JsonProcessingException e) {
-            logger.error("Failed to process json schema", e);
-        }
-
-        if (jsonSchema != null) {
-
-            Set<ValidationMessage> validationMessages = jsonSchema.validate(jsonNode);
-            if (validationMessages == null || validationMessages.isEmpty()) {
-                return true;
-            }
-            for (ValidationMessage validationMessage : validationMessages) {
-                logger.error("Error validating object against schema {}: {}", schemaId, validationMessage);
-            }
-            return false;
-        }
-        return false;
-    }
-
-    @Override
-    public List<JSONSchema> getSchemasByTarget(String target) {
-        return schemasById.values().stream().filter(jsonSchema -> jsonSchema.getTarget() != null && jsonSchema.getTarget().equals(target))
-                .collect(Collectors.toList());
-
-    }
-
-    @Override
-    public void saveSchema(String schema) {
-        JsonSchema jsonSchema = jsonSchemaFactory.getSchema(schema);
-        if (jsonSchema.getSchemaNode().at("/self/target").asText().equals("events") && !jsonSchema.getSchemaNode().at("/self/name").asText()
-                .matches("[_A-Za-z][_0-9A-Za-z]*")) {
-            throw new IllegalArgumentException(
-                    "The \"/self/name\" value should match the following regular expression [_A-Za-z][_0-9A-Za-z]* for the Json schema on"
-                            + " events");
-        }
-        if (predefinedUnomiJSONSchemaById.get(jsonSchema.getSchemaNode().get("$id").asText()) == null) {
-            persistenceService.save(buildUnomiJsonSchema(schema));
-            JSONSchema localSchema = buildJSONSchema(jsonSchema);
-            schemasById.put(jsonSchema.getSchemaNode().get("$id").asText(), localSchema);
-        } else {
-            logger.error("Can not store a JSON Schema which have the id of a schema preovided by Unomi");
-        }
-    }
-
-    @Override
-    public void saveSchema(InputStream schemaStream) throws IOException {
-        saveSchema(IOUtils.toString(schemaStream));
-    }
-
-    @Override
-    public void loadPredefinedSchema(InputStream schemaStream) {
-        JsonSchema jsonSchema = jsonSchemaFactory.getSchema(schemaStream);
-        JSONSchema localJsonSchema = buildJSONSchema(jsonSchema);
-
-        predefinedUnomiJSONSchemaById.put(jsonSchema.getSchemaNode().get("$id").asText(), localJsonSchema);
-        schemasById.put(jsonSchema.getSchemaNode().get("$id").asText(), localJsonSchema);
-    }
-
-    @Override
-    public boolean deleteSchema(String schemaId) {
-        schemasById.remove(schemaId);
-        return persistenceService.remove(schemaId, UnomiJSONSchema.class);
-    }
-
-    @Override
-    public boolean deleteSchema(InputStream schemaStream) {
-        JsonNode schemaNode = jsonSchemaFactory.getSchema(schemaStream).getSchemaNode();
-        return deleteSchema(schemaNode.get("$id").asText());
-    }
-
-    @Override
-    public void saveExtension(InputStream extensionStream) throws IOException {
-        saveExtension(IOUtils.toString(extensionStream));
-    }
-
-    @Override
-    public void saveExtension(String extension) throws IOException {
-        JSONSchemaExtension jsonSchemaExtension = buildExtension(extension);
-        persistenceService.save(jsonSchemaExtension);
-        extensionById.put(jsonSchemaExtension.getId(), jsonSchemaExtension);
-    }
-
-    @Override
-    public boolean deleteExtension(InputStream extensionStream) throws IOException {
-        JsonNode jsonNode = objectMapper.readTree(extensionStream);
-        return deleteExtension(jsonNode.get("id").asText());
-    }
-
-    @Override
-    public boolean deleteExtension(String extensionId) {
-        extensionById.remove(extensionId);
-        return persistenceService.remove(extensionId, JSONSchemaExtension.class);
-    }
-
-    @Override
-    public PartialList<Metadata> getJsonSchemaExtensionsMetadatas(int offset, int size, String sortBy) {
-        PartialList<JSONSchemaExtension> items = persistenceService.getAllItems(JSONSchemaExtension.class, offset, size, sortBy);
-        List<Metadata> details = new LinkedList<>();
-        for (JSONSchemaExtension definition : items.getList()) {
-            details.add(definition.getMetadata());
-        }
-        return new PartialList<>(details, items.getOffset(), items.getPageSize(), items.getTotalSize(), items.getTotalSizeRelation());
-    }
-
-    private JSONSchemaExtension buildExtension(String extension) throws JsonProcessingException {
-        JsonNode jsonNode = objectMapper.readTree(extension);
-        JSONSchemaExtension jsonSchemaExtension = new JSONSchemaExtension();
-        jsonSchemaExtension.setId(jsonNode.get("id").asText());
-        jsonSchemaExtension.setSchemaId(jsonNode.get("schemaId").asText());
-        jsonSchemaExtension.setExtension(jsonNode.get("extension").toString());
-        jsonSchemaExtension.setPriority(jsonNode.get("priority").asDouble());
-        Metadata metadata = new Metadata();
-        metadata.setId(jsonNode.get("id").asText());
-        metadata.setDescription(jsonNode.get("description").asText());
-        metadata.setName(jsonNode.get("name").asText());
-        jsonSchemaExtension.setMetadata(metadata);
-        return jsonSchemaExtension;
-    }
-
-    @Override
-    public JSONSchema getSchema(String schemaId) {
-        return schemasById.get(schemaId);
-    }
-
-    private JSONSchema buildJSONSchema(JsonSchema jsonSchema) {
-        return Optional.of(jsonSchema).map(jsonSchemaToProcess -> {
-            try {
-                return (Map<String, Object>) objectMapper.treeToValue(jsonSchemaToProcess.getSchemaNode(), Map.class);
-            } catch (JsonProcessingException e) {
-                logger.error("Failed to process Json object, e");
-            }
-            return Collections.<String, Object>emptyMap();
-        }).map(jsonSchemaToProcess -> {
-            JSONSchema schema = new JSONSchema(jsonSchemaToProcess, new JSONTypeFactory(this));
-            schema.setPluginId(bundleContext.getBundle().getBundleId());
-            return schema;
-        }).get();
-    }
-
-    private UnomiJSONSchema buildUnomiJsonSchema(String schema) {
-        JsonNode schemaNode = jsonSchemaFactory.getSchema(schema).getSchemaNode();
-        return new UnomiJSONSchema(schemaNode.get("$id").asText(), schema, schemaNode.at("/self/target").asText());
-    }
-
-    public JsonSchema getJsonSchema(String schemaId) {
-        String schemaAsString = null;
-        try {
-            schemaAsString = objectMapper.writeValueAsString(schemasById.get(schemaId).getSchemaTree());
-        } catch (JsonProcessingException e) {
-            logger.error("Failed to process json schema", e);
-        }
-        return jsonSchemaFactory.getSchema(schemaAsString);
-    }
-
-    private URIFetcher getUriFetcher() {
-        return uri -> {
-            logger.debug("Fetching schema {}", uri);
-            String schemaAsString = null;
-            try {
-                schemaAsString = objectMapper.writeValueAsString(schemasById.get(uri.toString()).getSchemaTree());
-            } catch (JsonProcessingException e) {
-                logger.error("Failed to process json schema", e);
-            }
-            JsonSchema schema = jsonSchemaFactory.getSchema(schemaAsString);
-            if (schema == null) {
-                logger.error("Couldn't find schema {}", uri);
-                return null;
-            }
-            return IOUtils.toInputStream(schema.getSchemaNode().asText());
-        };
-    }
-
-    private void refreshJSONSchemas() {
-        schemasById = new HashMap<>();
-        schemasById.putAll(predefinedUnomiJSONSchemaById);
-        persistenceService.getAllItems(UnomiJSONSchema.class).forEach(
-                jsonSchema -> schemasById.put(jsonSchema.getId(), buildJSONSchema(jsonSchemaFactory.getSchema(jsonSchema.getSchema()))));
-    }
-
-    private void refreshJSONSchemasExtensions() {
-        extensionById = new HashMap<>();
-        persistenceService.getAllItems(JSONSchemaExtension.class).forEach(extension -> extensionById.put(extension.getId(), extension));
-    }
-
-    private void initializeTimers() {
-        TimerTask task = new TimerTask() {
-            @Override
-            public void run() {
-                refreshJSONSchemas();
-                refreshJSONSchemasExtensions();
-            }
-        };
-        scheduledFuture = schedulerService.getScheduleExecutorService()
-                .scheduleWithFixedDelay(task, 0, jsonSchemaRefreshInterval, TimeUnit.MILLISECONDS);
-    }
-
-    public void init() {
-        JsonMetaSchema jsonMetaSchema = JsonMetaSchema.builder(URI, JsonMetaSchema.getV201909())
-                .addKeyword(new UnomiPropertyTypeKeyword(profileService, this)).addKeyword(new NonValidationKeyword("self")).build();
-        jsonSchemaFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))
-                .addMetaSchema(jsonMetaSchema).defaultMetaSchemaURI(URI).uriFetcher(getUriFetcher(), "https", "http").build();
-
-        initializeTimers();
-        logger.info("Schema service initialized.");
-    }
-
-    public void destroy() {
-        scheduledFuture.cancel(true);
-        logger.info("Schema service shutdown.");
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public void setProfileService(ProfileService profileService) {
-        this.profileService = profileService;
-    }
-}
diff --git a/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java b/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java
deleted file mode 100644
index 973d4acf0..000000000
--- a/services/src/main/java/org/apache/unomi/services/impl/schemas/UnomiPropertyTypeKeyword.java
+++ /dev/null
@@ -1,126 +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.schemas;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.networknt.schema.AbstractJsonValidator;
-import com.networknt.schema.AbstractKeyword;
-import com.networknt.schema.CustomErrorMessageType;
-import com.networknt.schema.JsonSchema;
-import com.networknt.schema.JsonSchemaException;
-import com.networknt.schema.JsonValidator;
-import com.networknt.schema.ValidationContext;
-import com.networknt.schema.ValidationMessage;
-import org.apache.unomi.api.PropertyType;
-import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.SchemaService;
-
-import java.text.MessageFormat;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-class UnomiPropertyTypeKeyword extends AbstractKeyword {
-
-    private final ProfileService profileService;
-    private final SchemaServiceImpl schemaService;
-
-    private static final class UnomiPropertyTypeJsonValidator extends AbstractJsonValidator {
-
-        String schemaPath;
-        JsonNode schemaNode;
-        JsonSchema parentSchema;
-        ValidationContext validationContext;
-        ProfileService profileService;
-        SchemaServiceImpl schemaService;
-
-        public UnomiPropertyTypeJsonValidator(String keyword, String schemaPath, JsonNode schemaNode, JsonSchema parentSchema,
-                ValidationContext validationContext, ProfileService profileService, SchemaServiceImpl schemaService) {
-            super(keyword);
-            this.schemaPath = schemaPath;
-            this.schemaNode = schemaNode;
-            this.parentSchema = parentSchema;
-            this.validationContext = validationContext;
-            this.profileService = profileService;
-            this.schemaService = schemaService;
-        }
-
-        @Override
-        public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
-            Set<ValidationMessage> validationMessages = new HashSet<>();
-            Iterator<String> fieldNames = node.fieldNames();
-            while (fieldNames.hasNext()) {
-                String fieldName = fieldNames.next();
-                PropertyType propertyType = getPropertyType(fieldName);
-                if (propertyType == null) {
-                    validationMessages.add(buildValidationMessage(CustomErrorMessageType
-                            .of("property-not-found", new MessageFormat("{0} : Couldn''t find property type with id={1}")), at, fieldName));
-                } else {
-                    // @todo further validation, if it can be used in this context (event, profile, session)
-                    String valueTypeId = propertyType.getValueTypeId();
-                    JsonSchema jsonSchema = schemaService
-                            .getJsonSchema("https://unomi.apache.org/schemas/json/values/" + valueTypeId + ".json");
-                    if (jsonSchema == null) {
-                        validationMessages.add(buildValidationMessage(CustomErrorMessageType
-                                        .of("value-schema-not-found", new MessageFormat("{0} : Couldn''t find schema type with id={1}")), at,
-                                "https://unomi.apache.org/schemas/json/values/" + valueTypeId + ".json"));
-                    } else {
-                        Set<ValidationMessage> propertyValidationMessages = jsonSchema.validate(node.get(fieldName));
-                        if (propertyValidationMessages != null) {
-                            validationMessages.addAll(propertyValidationMessages);
-                        }
-                    }
-                }
-            }
-            return validationMessages;
-        }
-
-        private PropertyType getPropertyType(String fieldName) {
-            Map<String, PropertyType> propertyTypes = new HashMap<>();
-            if (schemaNode.size() > 0) {
-                for (Iterator<JsonNode> it = schemaNode.iterator(); it.hasNext(); ) {
-                    JsonNode target = it.next();
-                    if ("_all".equals(target.asText())) {
-                        return profileService.getPropertyType(fieldName);
-                    } else {
-                        Collection<PropertyType> targetPropertyTypes = profileService.getTargetPropertyTypes(target.asText());
-                        targetPropertyTypes.stream().map(propertyType -> propertyTypes.put(propertyType.getItemId(), propertyType));
-                    }
-                }
-                return propertyTypes.get(fieldName);
-            } else {
-                return profileService.getPropertyType(fieldName);
-            }
-        }
-    }
-
-    public UnomiPropertyTypeKeyword(ProfileService profileService, SchemaServiceImpl schemaService) {
-        super("unomiPropertyTypes");
-        this.profileService = profileService;
-        this.schemaService = schemaService;
-    }
-
-    @Override
-    public JsonValidator newValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext)
-            throws JsonSchemaException, Exception {
-        return new UnomiPropertyTypeJsonValidator(this.getValue(), schemaPath, schemaNode, parentSchema, validationContext, profileService,
-                schemaService);
-    }
-}
diff --git a/services/src/main/java/org/apache/unomi/services/listener/JsonSchemaListener.java b/services/src/main/java/org/apache/unomi/services/listener/JsonSchemaListener.java
deleted file mode 100644
index 21dab227f..000000000
--- a/services/src/main/java/org/apache/unomi/services/listener/JsonSchemaListener.java
+++ /dev/null
@@ -1,217 +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.listener;
-
-import org.apache.unomi.api.schema.JSONSchemaExtension;
-import org.apache.unomi.api.schema.UnomiJSONSchema;
-import org.apache.unomi.api.services.SchemaService;
-import org.apache.unomi.persistence.spi.PersistenceService;
-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.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
-
-/**
- * An implementation of a BundleListener for the JSON schema.
- * It will load the pre-defined schema files in the folder META-INF/cxs/schemas.
- * It will load the extension of schema in the folder META-INF/cxs/schemasextensions.
- * The scripts will be stored in the ES index jsonSchema and the extension will be stored in jsonSchemaExtension
- */
-public class JsonSchemaListener implements SynchronousBundleListener {
-
-    private static final Logger logger = LoggerFactory.getLogger(JsonSchemaListener.class.getName());
-    public static final String ENTRIES_LOCATION = "META-INF/cxs/schemas";
-
-    public static final String EXTENSIONS_ENTRIES_LOCATION = "META-INF/cxs/schemasextensions";
-
-    private PersistenceService persistenceService;
-
-    private SchemaService schemaService;
-
-    private BundleContext bundleContext;
-
-    public void setPersistenceService(PersistenceService persistenceService) {
-        this.persistenceService = persistenceService;
-    }
-
-    public void setSchemaService(SchemaService schemaService) {
-        this.schemaService = schemaService;
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public void postConstruct() {
-        logger.info("JSON schema listener initializing...");
-        logger.debug("postConstruct {}", bundleContext.getBundle());
-        createIndexes();
-
-        loadPredefinedSchemas(bundleContext);
-
-        for (Bundle bundle : bundleContext.getBundles()) {
-            if (bundle.getBundleContext() != null && bundle.getBundleId() != bundleContext.getBundle().getBundleId()) {
-                saveSchemas(bundle.getBundleContext());
-                saveExtensions(bundle.getBundleContext());
-            }
-        }
-
-        bundleContext.addBundleListener(this);
-        logger.info("JSON schema listener initialized.");
-    }
-
-    public void preDestroy() {
-        bundleContext.removeBundleListener(this);
-        logger.info("JSON schema listener shutdown.");
-    }
-
-    private void processBundleStartup(BundleContext bundleContext) {
-        if (bundleContext == null) {
-            return;
-        }
-        saveSchemas(bundleContext);
-    }
-
-    private void processBundleStop(BundleContext bundleContext) {
-        if (bundleContext == null) {
-            return;
-        }
-        unloadSchemas(bundleContext);
-        unloadExtensions(bundleContext);
-    }
-
-    public void bundleChanged(BundleEvent event) {
-        switch (event.getType()) {
-            case BundleEvent.STARTED:
-                processBundleStartup(event.getBundle().getBundleContext());
-                break;
-            case BundleEvent.STOPPING:
-                if (!event.getBundle().getSymbolicName().equals(bundleContext.getBundle().getSymbolicName())) {
-                    processBundleStop(event.getBundle().getBundleContext());
-                }
-                break;
-        }
-    }
-
-    public void createIndexes() {
-        if (persistenceService.createIndex(UnomiJSONSchema.ITEM_TYPE)) {
-            logger.info("{} index created", UnomiJSONSchema.ITEM_TYPE);
-        } else {
-            logger.info("{} index already exists", UnomiJSONSchema.ITEM_TYPE);
-        }
-        if (persistenceService.createIndex(JSONSchemaExtension.ITEM_TYPE)) {
-            logger.info("{} index created", JSONSchemaExtension.ITEM_TYPE);
-        } else {
-            logger.info("{} index already exists", JSONSchemaExtension.ITEM_TYPE);
-        }
-    }
-
-    private void saveSchemas(BundleContext bundleContext) {
-        Enumeration<URL> predefinedSchemas = bundleContext.getBundle().findEntries(ENTRIES_LOCATION, "*.json", true);
-        if (predefinedSchemas == null) {
-            return;
-        }
-
-        while (predefinedSchemas.hasMoreElements()) {
-            URL predefinedSchemaURL = predefinedSchemas.nextElement();
-            logger.debug("Found JSON schema at {}, loading... ", predefinedSchemaURL);
-
-            try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) {
-                schemaService.saveSchema(schemaInputStream);
-            } catch (Exception e) {
-                logger.error("Error while loading schema definition {}", predefinedSchemaURL, e);
-            }
-        }
-    }
-
-    private void loadPredefinedSchemas(BundleContext bundleContext) {
-        Enumeration<URL> predefinedSchemas = bundleContext.getBundle().findEntries(ENTRIES_LOCATION, "*.json", true);
-        if (predefinedSchemas == null) {
-            return;
-        }
-
-        while (predefinedSchemas.hasMoreElements()) {
-            URL predefinedSchemaURL = predefinedSchemas.nextElement();
-            logger.debug("Found predefined JSON schema at {}, loading... ", predefinedSchemaURL);
-            try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) {
-                schemaService.loadPredefinedSchema(schemaInputStream);
-            } catch (Exception e) {
-                logger.error("Error while loading schema definition {}", predefinedSchemaURL, e);
-            }
-        }
-    }
-
-    private void unloadSchemas(BundleContext bundleContext) {
-        Enumeration<URL> predefinedSchemas = bundleContext.getBundle().findEntries(ENTRIES_LOCATION, "*.json", true);
-        if (predefinedSchemas == null) {
-            return;
-        }
-
-        while (predefinedSchemas.hasMoreElements()) {
-            URL predefinedSchemaURL = predefinedSchemas.nextElement();
-            logger.debug("Found predefined JSON schema at {}, loading... ", predefinedSchemaURL);
-
-            try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) {
-                schemaService.deleteSchema(schemaInputStream);
-            } catch (Exception e) {
-                logger.error("Error while removing schema at {}", predefinedSchemaURL, e);
-            }
-        }
-    }
-
-    private void saveExtensions(BundleContext bundleContext) {
-        Enumeration<URL> extensions = bundleContext.getBundle().findEntries(EXTENSIONS_ENTRIES_LOCATION, "*.json", true);
-        if (extensions == null) {
-            return;
-        }
-
-        while (extensions.hasMoreElements()) {
-            URL extensionURL = extensions.nextElement();
-            logger.debug("Found JSON schema extension at {}, loading... ", extensionURL);
-
-            try (InputStream extensionInputStream = extensionURL.openStream()) {
-                schemaService.saveExtension(extensionInputStream);
-            } catch (Exception e) {
-                logger.error("Error while loading schema extension at {}", extensionURL, e);
-            }
-        }
-    }
-
-    private void unloadExtensions(BundleContext bundleContext) {
-        Enumeration<URL> extensions = bundleContext.getBundle().findEntries(EXTENSIONS_ENTRIES_LOCATION, "*.json", true);
-        if (extensions == null) {
-            return;
-        }
-
-        while (extensions.hasMoreElements()) {
-            URL predefinedSchemaURL = extensions.nextElement();
-            logger.debug("Found JSON schema extension at {}, loading... ", predefinedSchemaURL);
-
-            try (InputStream extensionInputStream = predefinedSchemaURL.openStream()) {
-                schemaService.deleteExtension(extensionInputStream);
-            } catch (Exception e) {
-                logger.error("Error while loading schema extension at {}", predefinedSchemaURL, e);
-            }
-        }
-    }
-}
diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 1d1417c12..68ce68e9f 100644
--- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -45,7 +45,6 @@
             <cm:property name="events.shouldBeCheckedEventSourceId" value="false"/>
             <cm:property name="rules.optimizationActivated" value="true"/>
             <cm:property name="schedules.thread.poolSize" value="5"/>
-            <cm:property name="json.schema.refresh.interval" value="1000"/>
         </cm:default-properties>
     </cm:property-placeholder>
 
@@ -102,34 +101,11 @@
         </interfaces>
     </service>
 
-    <bean id="schemaServiceImpl" class="org.apache.unomi.services.impl.schemas.SchemaServiceImpl" init-method="init"
-          destroy-method="destroy">
-        <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="profileService" ref="profileServiceImpl"/>
-        <property name="persistenceService" ref="persistenceService"/>
-        <property name="schedulerService" ref="schedulerServiceImpl"/>
-        <property name="jsonSchemaRefreshInterval" value="${services.json.schema.refresh.interval}"/>
-    </bean>
-    <service id="schemaService" ref="schemaServiceImpl" interface="org.apache.unomi.api.services.SchemaService"/>
-
-    <bean id="jsonSchemaListenerImpl" class="org.apache.unomi.services.listener.JsonSchemaListener"
-          init-method="postConstruct" destroy-method="preDestroy">
-        <property name="persistenceService" ref="persistenceService"/>
-        <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="schemaService" ref="schemaServiceImpl"/>
-    </bean>
-    <service id="jsonSchemaListener" ref="jsonSchemaListenerImpl">
-        <interfaces>
-            <value>org.osgi.framework.SynchronousBundleListener</value>
-        </interfaces>
-    </service>
-
     <bean id="eventServiceImpl" class="org.apache.unomi.services.impl.events.EventServiceImpl">
         <property name="persistenceService" ref="persistenceService"/>
         <property name="definitionsService" ref="definitionsServiceImpl"/>
         <property name="sourceService" ref="sourceServiceImpl"/>
         <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="schemaService" ref="schemaServiceImpl"/>
         <property name="predefinedEventTypeIds">
             <set>
                 <value>view</value>
diff --git a/services/src/main/resources/org.apache.unomi.services.cfg b/services/src/main/resources/org.apache.unomi.services.cfg
index 1f9a9bd6a..452b7591b 100644
--- a/services/src/main/resources/org.apache.unomi.services.cfg
+++ b/services/src/main/resources/org.apache.unomi.services.cfg
@@ -77,6 +77,3 @@ rules.optimizationActivated=${org.apache.unomi.rules.optimizationActivated:-true
 
 # The number of threads to compose the pool size of the scheduler.
 scheduler.thread.poolSize=${org.apache.unomi.scheduler.thread.poolSize:-5}
-
-# The interval in milliseconds to reload the json schemas in memory
-services.json.schema.refresh.interval=${org.apache.unomi.json.schema.refresh.interval:-1000}
diff --git a/tools/shell-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/tools/shell-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index a6223d592..3e0ab6974 100644
--- a/tools/shell-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/tools/shell-commands/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -44,6 +44,8 @@
                 <value>org.apache.unomi.cxs-geonames-rest</value>
                 <value>org.apache.unomi.cxs-privacy-extension-services</value>
                 <value>org.apache.unomi.cxs-privacy-extension-rest</value>
+                <value>org.apache.unomi.json-schema-services</value>
+                <value>org.apache.unomi.json-schema-rest</value>
                 <value>org.apache.unomi.rest</value>
                 <value>org.apache.unomi.wab</value>
                 <value>org.apache.unomi.plugins-base</value>