UNOMI-568: refacto json-schema implementation (#421)
* UNOMI-568: refacto json-schema implementation
* UNOMI-568: code review handling comments and suggestions
* fix object mapper in integration tests
* Fail safe on missing schema + fix timestamp schema
* clean up test objects
* Set pom description to JSON Schema projects
* Send an error when a predefined schema is override.
* update code ql to v2
* provide codeql config to ignore itests folder in order to reduce result file
* set codeql to debug
* split codeQL workflows to have a dedicated java build
* do not upload file SARIF to github
Co-authored-by: David Griffon <dgriffon@jahia.com>
diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
new file mode 100644
index 0000000..df45fcf
--- /dev/null
+++ b/.github/codeql/codeql-config.yml
@@ -0,0 +1,4 @@
+name: "Unomi CodeQL config"
+
+paths-ignore:
+ - itests
\ No newline at end of file
diff --git a/.github/workflows/codeql-analysis-java.yml b/.github/workflows/codeql-analysis-java.yml
new file mode 100644
index 0000000..7e46387
--- /dev/null
+++ b/.github/workflows/codeql-analysis-java.yml
@@ -0,0 +1,47 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL JAVA"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '38 1 * * 0'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ config-file: ./.github/codeql/codeql-config.yml
+ languages: java
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ - run: mvn -U -ntp -e clean install -DskipTests
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ upload: false
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis-javascript.yml
similarity index 91%
rename from .github/workflows/codeql-analysis.yml
rename to .github/workflows/codeql-analysis-javascript.yml
index f631368..ce6239f 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis-javascript.yml
@@ -9,7 +9,7 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
-name: "CodeQL"
+name: "CodeQL Javascript"
on:
push:
@@ -28,7 +28,7 @@
strategy:
fail-fast: false
matrix:
- language: [ 'java', 'javascript' ]
+ language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
@@ -39,7 +39,7 @@
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -50,7 +50,7 @@
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@v2
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -64,4 +64,4 @@
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v2
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 652102d..0000000
--- 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/api/src/main/java/org/apache/unomi/api/services/SchemaService.java b/api/src/main/java/org/apache/unomi/api/services/SchemaService.java
deleted file mode 100644
index 7d6e654..0000000
--- a/api/src/main/java/org/apache/unomi/api/services/SchemaService.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.unomi.api.services;
-
-import 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;
-import java.util.List;
-
-/**
- * Service that allow to manage JSON schema. It allows to get, save and delete schemas
- */
-public interface SchemaService {
-
- /**
- * Retrieves json schema 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 metadata
- */
- PartialList<Metadata> getJsonSchemaMetadatas(int offset, int size, String sortBy);
-
- /**
- * Verify if a jsonNode is valid against a schema
- *
- * @param jsonNode 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);
-
- /**
- * Get a schema matching by a schema id
- *
- * @param schemaId Id of the schema
- * @return A JSON schema
- */
- JSONSchema getSchema(String schemaId);
-
- /**
- * Get a list a {@link org.apache.unomi.api.schema.json.JSONSchema}
- *
- * @param target to filter the schemas
- * @return a list of JSONSchema
- */
- List<JSONSchema> getSchemasByTarget(String target);
-
- /**
- * Save a new schema or update a schema
- *
- * @param schema as a String value
- */
- 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
- *
- * @param schemaId id of the schema to delete
- * @return true if the schema has been deleted
- */
- 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
- *
- * @param extensionStream inputStream of the extension to delete
- * @return true if the extension has been deleted
- */
- boolean deleteExtension(InputStream extensionStream) throws IOException;
-
- /**
- * Delete an extension by an id
- *
- * @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
- */
- PartialList<Metadata> getJsonSchemaExtensionsMetadatas(int offset, int size, String sortBy);
-
-}
diff --git a/extensions/json-schema/pom.xml b/extensions/json-schema/pom.xml
new file mode 100644
index 0000000..dcc6e61
--- /dev/null
+++ b/extensions/json-schema/pom.xml
@@ -0,0 +1,37 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.unomi</groupId>
+ <artifactId>unomi-extensions</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>unomi-json-schema-root</artifactId>
+ <name>Apache Unomi :: Extensions :: JSON Schema</name>
+ <description>JSON Schema extension for the Apache Unomi Context Server</description>
+ <packaging>pom</packaging>
+
+ <modules>
+ <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 0000000..df4ed2b
--- /dev/null
+++ b/extensions/json-schema/rest/pom.xml
@@ -0,0 +1,96 @@
+<?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>JSON Schema REST API for the Apache Unomi Context Server</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>org.apache.unomi</groupId>
+ <artifactId>unomi-rest</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 89%
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 dfc8900..26f0922 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,12 @@
* 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.rest.exception.InvalidRequestException;
+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 +28,7 @@
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;
@@ -91,8 +84,12 @@
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
public Response save(String jsonSchema) {
- schemaService.saveSchema(jsonSchema);
- return Response.ok().build();
+ try {
+ schemaService.saveSchema(jsonSchema);
+ return Response.ok().build();
+ } catch (Exception e) {
+ throw new InvalidRequestException(e.getMessage(), "Unable to save schema");
+ }
}
/**
diff --git a/extensions/json-schema/services/pom.xml b/extensions/json-schema/services/pom.xml
new file mode 100644
index 0000000..86a54c8
--- /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>JSON Schema service for the Apache Unomi Context Server</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 74%
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 3ae5077..ce12387 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,26 @@
* 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
+ * Object which represents a JSON schema, it's a wrapper because it contains some additional info used by the
+ * Service layer of Unomi like the id and the target.
+ * The JSON schema is store as String to avoid transformation during JSON schema resolution in the Unomi SchemaService.
+ * Also, it's extending MetadataItem so that it can be persisted like that in Unomi storage system.
*/
-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 +42,7 @@
* @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 +72,4 @@
public void setTarget(String target) {
this.target = target;
}
-}
+}
\ No newline at end of file
diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java
new file mode 100644
index 0000000..c479c40
--- /dev/null
+++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/api/SchemaService.java
@@ -0,0 +1,100 @@
+/*
+ * 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.api;
+
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.api.PartialList;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Service that allow to manage JSON schema. It allows to get, save and delete schemas
+ */
+public interface SchemaService {
+
+ /**
+ * Retrieves json schema 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 metadata
+ */
+ PartialList<Metadata> getJsonSchemaMetadatas(int offset, int size, String sortBy);
+
+ /**
+ * Verify if a jsonNode is valid against a schema
+ *
+ * @param data to validate
+ * @param schemaId id of the schema used for the validation
+ * @return true is the object is valid
+ */
+ boolean isValid(String data, String schemaId);
+
+ /**
+ * Get a schema matching by a schema id
+ *
+ * @param schemaId Id of the schema
+ * @return A JSON schema
+ */
+ JsonSchemaWrapper getSchema(String schemaId);
+
+ /**
+ * Get a list a {@link JsonSchemaWrapper}
+ *
+ * @param target to filter the schemas
+ * @return a list of JSONSchema
+ */
+ List<JsonSchemaWrapper> getSchemasByTarget(String target);
+
+ /**
+ * Save a new schema or update a schema
+ *
+ * @param schema as a String value
+ */
+ void saveSchema(String schema);
+
+ /**
+ * Delete a schema according to its id
+ *
+ * @param schemaId id of the schema to delete
+ * @return true if the schema has been deleted
+ */
+ boolean deleteSchema(String schemaId);
+
+ /**
+ * Load a predefined schema into memory
+ *
+ * @param schemaStream inputStream of the schema
+ */
+ void loadPredefinedSchema(InputStream schemaStream) throws IOException;
+
+ /**
+ * Unload a predefined schema into memory
+ *
+ * @param schemaStream inputStream of the schema to delete
+ * @return true if the schema has been deleted
+ */
+ 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 0000000..e91d297
--- /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 (Exception e) {
+ logger.error("Failed to process data to validate because {} - Set SchemaServiceImpl at DEBUG level for more detail ", e.getMessage());
+ logger.debug("full error",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 {
+ throw new IllegalArgumentException("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 0000000..9e674d5
--- /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 84%
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 b4e1528..b1e8156 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
@@ -6,8 +6,7 @@
"allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/item/1-0-0" }],
"properties" : {
"timeStamp" : {
- "type" : ["string"],
- "format" : "date-time"
+ "type" : ["string", "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 0000000..02e3280
--- /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 0000000..b930b86
--- /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 70105e5..5b7c58d 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 d79a7ce..3ff2923 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 eff1964..84b9ec8 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.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.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.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 @@
}
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 @@
}
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 @@
}
// 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 @@
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 7d6198d..37cd40a 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.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.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 95%
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 aa8cc2a..427b31e 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 aea431e..79f541e 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 57ba1e6..6cee489 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 9ae40dd..e873d12 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 809a29f..3cdd3ce 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 d591777..6233217 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 da28f41..be91e0a 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 97%
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 1e65f8e..fe159b0 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 c63f6b5..238c618 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 97%
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 d1c0474..2f8afa2 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 33f4b72..6b1ab82 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 @@
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 2d6cebb..1ded244 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 @@
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 @@
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/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index 9abf854..cece1ce 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -17,6 +17,7 @@
package org.apache.unomi.itests;
+import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.http.auth.AuthScope;
@@ -113,6 +114,13 @@
protected static final int DEFAULT_TRYING_TRIES = 30;
private final static String JSONSCHEMA_URL = "/cxs/jsonSchema";
+ protected final static ObjectMapper objectMapper;
+
+ static {
+ objectMapper = new ObjectMapper();
+ objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+
@Inject
@Filter(timeout = 600000)
protected PersistenceService persistenceService;
@@ -448,7 +456,6 @@
final HttpGet httpGet = new HttpGet(getFullUrl(url));
response = executeHttpRequest(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
- ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(response.getEntity().getContent(), clazz);
} else {
return null;
@@ -528,7 +535,6 @@
protected String resourceAsString(final String resource) {
final java.net.URL url = bundleContext.getBundle().getResource(resource);
try (InputStream stream = url.openStream()) {
- final ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(objectMapper.readTree(stream));
} catch (final Exception e) {
throw new RuntimeException(e);
diff --git a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
index 348bdc3..b90c0b0 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
@@ -17,7 +17,9 @@
package org.apache.unomi.itests;
+import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
@@ -59,7 +61,6 @@
public class BasicIT extends BaseIT {
private final static Logger LOGGER = LoggerFactory.getLogger(BasicIT.class);
- private final ObjectMapper objectMapper = new ObjectMapper();
private static final String SESSION_ID_0 = "aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d0";
private static final String SESSION_ID_1 = "aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d1";
diff --git a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
index e21608d..4e1b759 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
@@ -91,8 +91,6 @@
private static final int DEFAULT_TRYING_TIMEOUT = 2000;
private static final int DEFAULT_TRYING_TRIES = 30;
- private ObjectMapper objectMapper = new ObjectMapper();
-
@Inject
@Filter(timeout = 600000)
protected EventService eventService;
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 5b14aa7..97879bd 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 @@
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 @@
@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 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 @@
@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);
@@ -103,8 +98,16 @@
}
@Test
+ public void testSavePredefinedJSONSchema() throws IOException {
+ assertTrue("JSON schema list should be empty", persistenceService.getAllItems(JsonSchemaWrapper.class).isEmpty());
+ try (CloseableHttpResponse response = post(JSONSCHEMA_URL, "schemas/events/predefined-event-type.json", ContentType.TEXT_PLAIN)) {
+ assertEquals("Unable to save schema", 400, response.getStatusLine().getStatusCode());
+ }
+ }
+
+ @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,60 +127,17 @@
@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());
+ assertEquals("Unable to save schema", 400, response.getStatusLine().getStatusCode());
}
}
@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());
+ assertEquals("Unable to save schema", 400, 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/java/org/apache/unomi/itests/TestUtils.java b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
index 0b4073e..2767a38 100644
--- a/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
+++ b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
@@ -62,7 +62,6 @@
return null;
}
String jsonFromResponse = EntityUtils.toString(response.getEntity());
- // ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ObjectMapper mapper = CustomObjectMapper.getObjectMapper();
try {
T value = mapper.readValue(jsonFromResponse, clazz);
diff --git a/itests/src/test/resources/personalization-controlgroup.json b/itests/src/test/resources/personalization-controlgroup.json
index 8b8c74f..c4a1bcf 100644
--- a/itests/src/test/resources/personalization-controlgroup.json
+++ b/itests/src/test/resources/personalization-controlgroup.json
@@ -3,7 +3,6 @@
"itemId": "CMSServer",
"itemType": "custom",
"scope": "acme",
- "version": null,
"properties": {}
},
"requireSegments": true,
@@ -13,8 +12,6 @@
"requiredSessionProperties": [
"unomiControlGroups"
],
- "events": null,
- "filters": null,
"personalizations": [
{
"id": "perso1",
@@ -33,7 +30,6 @@
"id": "perso1content1",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -84,7 +80,6 @@
"id": "perso1content2",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -126,14 +121,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content3",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -175,14 +168,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content4",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -224,14 +215,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content5",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -273,14 +262,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content6",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -322,14 +309,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content7",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -371,14 +356,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content8",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -420,14 +403,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content9",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -469,14 +450,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content10",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -518,8 +497,7 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
}
]
},
@@ -534,7 +512,6 @@
"id": "perso2content1",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -585,7 +562,6 @@
"id": "perso2content2",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -627,14 +603,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso1content3",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -676,14 +650,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content4",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -725,14 +697,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content5",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -774,14 +744,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content6",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -823,14 +791,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content7",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -872,14 +838,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content8",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -921,14 +885,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content9",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -970,14 +932,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "perso2content10",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -1019,13 +979,10 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
}
]
}
],
- "profileOverrides": null,
- "sessionPropertiesOverrides": null,
"sessionId": "test-session-id"
}
\ No newline at end of file
diff --git a/itests/src/test/resources/personalization.json b/itests/src/test/resources/personalization.json
index 89ac156..652d50a 100644
--- a/itests/src/test/resources/personalization.json
+++ b/itests/src/test/resources/personalization.json
@@ -3,7 +3,6 @@
"itemId": "CMSServer",
"itemType": "custom",
"scope": "acme",
- "version": null,
"properties": {}
},
"requireSegments": true,
@@ -13,8 +12,6 @@
"requiredSessionProperties": [
"*"
],
- "events": null,
- "filters": null,
"personalizations": [
{
"id": "recommendations-by-interest",
@@ -27,7 +24,6 @@
"id": "ac02dbe3-2445-4727-acea-50cfed001996",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -35,7 +31,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -78,7 +74,6 @@
"id": "62194fdd-2a1c-46ce-8f9b-19dc168f3454",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -86,7 +81,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -120,14 +115,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "dbb3a797-d24e-4701-97ad-dc0a708fa06f",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -135,7 +128,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -169,14 +162,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "90664d1d-6558-4239-a024-8212f2652673",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -184,7 +175,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -218,14 +209,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "f13af275-2002-4200-bd58-96847c74dafb",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -233,7 +222,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -267,14 +256,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "2305ab1a-f6b1-47c1-bc46-a8c69c553d87",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -282,7 +269,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -316,14 +303,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "50c4064c-ef6e-4afe-adcf-f876111f50bc",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -331,7 +316,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -365,14 +350,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "55371bb0-c516-4038-ab6d-0acab57b4790",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -380,7 +363,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -414,14 +397,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "eaaa15eb-e2c2-49cf-bb99-20ea90bd3fdb",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -429,7 +410,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -463,14 +444,12 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
},
{
"id": "15cdd5dd-909d-4d91-8f79-62226b96843a",
"filters": [
{
- "appliesOn": null,
"condition": {
"parameterValues": {
"minimumEventCount": 1,
@@ -478,7 +457,7 @@
"type": "booleanCondition",
"parameterValues": {
"operator": "and",
- "subConditions" : [
+ "subConditions": [
{
"type": "eventTypeCondition",
"parameterValues": {
@@ -512,13 +491,10 @@
"score": -1000
}
}
- ],
- "properties": null
+ ]
}
]
}
],
- "profileOverrides": null,
- "sessionPropertiesOverrides": null,
"sessionId": "21bf6d3d-ba5d-4b8c-98bb-af4dcf506c03"
}
\ No newline at end of file
diff --git a/itests/src/test/resources/schemas/events/predefined-event-type.json b/itests/src/test/resources/schemas/events/predefined-event-type.json
new file mode 100644
index 0000000..8d9ffd9
--- /dev/null
+++ b/itests/src/test/resources/schemas/events/predefined-event-type.json
@@ -0,0 +1,14 @@
+{
+ "$id": "https://unomi.apache.org/schemas/json/event/1-0-0",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "self":{
+ "vendor":"org.apache.unomi",
+ "name":"testEventType",
+ "format":"jsonschema",
+ "target":"events",
+ "version":"1-0-0"
+ },
+ "title": "TestEvent",
+ "type": "object",
+ "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }]
+}
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 e03fecc..0000000
--- 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 f25e555..23824b2 100644
--- a/kar/pom.xml
+++ b/kar/pom.xml
@@ -116,6 +116,11 @@
</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>
<version>${project.version}</version>
</dependency>
diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml
index 3b0d695..7040610 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 050a2ae..4eb80ac 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/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
index 9e23a23..1d14d55 100644
--- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
+++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
@@ -17,6 +17,7 @@
package org.apache.unomi.persistence.spi;
+import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -58,6 +59,7 @@
super();
super.registerModule(new JaxbAnnotationModule());
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ setSerializationInclusion(JsonInclude.Include.NON_NULL);
ISO8601DateFormat dateFormat = new ISO8601DateFormat();
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
setDateFormat(dateFormat);
diff --git a/rest/pom.xml b/rest/pom.xml
index 77ae8fc..6631e9f 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -44,6 +44,12 @@
<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>
<scope>provided</scope>
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 ad33945..ba9d9aa 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.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 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 @@
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 0f23419..20d808d 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.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 @@
@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 @@
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 3242165..3f84bf1 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.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.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.List;
import java.util.Map;
import java.util.UUID;
-import java.util.Objects;
@WebService
@Consumes(MediaType.APPLICATION_JSON)
@@ -164,7 +160,7 @@
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 5033124..0000000
--- 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 0da55b9..f2b85fe 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.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.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 4600f0c..ac617d3 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.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.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 @@
@Reference
private EventService eventService;
- @Reference SchemaService schemaService;
+ @Reference
+ SchemaService schemaService;
public String getProfileIdCookieValue(HttpServletRequest httpServletRequest) {
String cookieProfileId = null;
@@ -67,7 +66,7 @@
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 c4acbb2..3f41968 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 736de11..5b81819 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 @@
private BundleContext bundleContext;
- private SchemaService schemaService;
-
private Set<String> predefinedEventTypeIds = new LinkedHashSet<String>();
private Set<String> restrictedEventTypeIds = new LinkedHashSet<String>();
@@ -114,9 +112,6 @@
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 56d70f2..0000000
--- 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 973d4ac..0000000
--- 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 21dab22..0000000
--- 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 1d1417c..68ce68e 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 1f9a9bd..452b759 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 @@
# 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 a6223d5..3e0ab69 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>