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:58 UTC

[unomi] branch refacto-json-schema created (now 723d8edb5)

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

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


      at 723d8edb5 UNOMI-568: refacto json-schema implementation

This branch includes the following new commits:

     new 723d8edb5 UNOMI-568: refacto json-schema implementation

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



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

Posted by jk...@apache.org.
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>