You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by dg...@apache.org on 2022/05/02 08:53:29 UTC

[unomi] 01/01: UNOMI-562 : remove bean validation

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

dgriffon pushed a commit to branch remove-bean-validation
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 5f09dacbd8baef32b6a5d00978f51471985bde1e
Author: David Griffon <dg...@jahia.com>
AuthorDate: Mon May 2 10:52:46 2022 +0200

    UNOMI-562 : remove bean validation
---
 .../resources/schemas/events/dummy-event-type.json | 43 +++++++++++++++----
 .../deserializers/ContextRequestDeserializer.java  |  4 +-
 ...ava => EventsCollectorRequestDeserializer.java} | 10 ++---
 .../unomi/rest/endpoints/ContextJsonEndpoint.java  | 49 ++++++++++++++--------
 .../rest/endpoints/EventsCollectorEndpoint.java    |  8 +++-
 .../InvalidRequestException.java                   |  7 +++-
 .../exception/InvalidRequestExceptionMapper.java   |  4 +-
 .../org/apache/unomi/rest/server/RestServer.java   | 22 +---------
 .../RetroCompatibilityParamConverterProvider.java  |  7 +---
 .../rest/service/impl/RestServiceUtilsImpl.java    | 19 +++++----
 .../rest/validation/BeanValidationService.java     | 32 --------------
 .../HibernateValidationProviderResolver.java       | 37 ----------------
 .../JAXRSBeanValidationInInterceptorOverride.java  | 42 -------------------
 .../validation/impl/BeanValidationServiceImpl.java | 48 ---------------------
 .../request/RequestValidatorInterceptor.java       |  1 +
 .../rest/validation/wrapper/CookieWrapper.java     | 36 ----------------
 .../META-INF/cxs/schemas/contextrequestparams.json | 16 +++++++
 .../resources/META-INF/cxs/schemas/cookie.json     | 12 ++++++
 .../cxs/schemas/eventscollectorrequest.json        |  5 ++-
 19 files changed, 136 insertions(+), 266 deletions(-)

diff --git a/itests/src/test/resources/schemas/events/dummy-event-type.json b/itests/src/test/resources/schemas/events/dummy-event-type.json
index 439f2f9f2..59f439abf 100644
--- a/itests/src/test/resources/schemas/events/dummy-event-type.json
+++ b/itests/src/test/resources/schemas/events/dummy-event-type.json
@@ -1,14 +1,43 @@
 {
   "$id": "https://unomi.apache.org/schemas/json/events/dummy_event_type/1-0-0",
   "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "self":{
-    "vendor":"org.apache.unomi",
-    "name":"events/dummy_event_type",
-    "format":"jsonschema",
-    "target":"events",
-    "version":"1-0-0"
+  "self": {
+    "vendor": "org.apache.unomi",
+    "name": "events/dummy_event_type",
+    "format": "jsonschema",
+    "target": "events",
+    "version": "1-0-0"
   },
   "title": "DummyEvent",
   "type": "object",
-  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }]
+  "allOf": [
+    {
+      "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
+    }
+  ],
+  "properties": {
+    "source": {
+      "type": "object",
+      "properties": {
+        "itemType": {
+          "type": "string"
+        },
+        "scope": {
+          "type": "string"
+        },
+        "itemId": {
+          "type": "string"
+        },
+        "properties": {
+          "type": "object",
+          "properties": {
+            "myProperty": {
+              "type": "string",
+              "maxLength": 20000
+            }
+          }
+        }
+      }
+    }
+  }
 }
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 5e5488f3b..1dcb653b8 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,7 +27,7 @@ import org.apache.unomi.api.Event;
 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.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -55,7 +55,7 @@ public class ContextRequestDeserializer extends StdDeserializer<ContextRequest>
         JsonNode node = jsonParser.getCodec().readTree(jsonParser);
         // Validate schema on it
         if (!schemaService.isValid(node, "https://unomi.apache.org/schemas/json/contextrequest/1-0-0")) {
-            throw new InvalidRequestException("Invalid received data", "Invalid received data");
+            throw new InvalidRequestException("Invalid Context request object", "Invalid received data");
         }
         ContextRequest cr = new ContextRequest();
         if (node.get("requireSegments") != null) {
diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
similarity index 86%
rename from rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java
rename to rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
index 5e78fc0a9..b544f2089 100644
--- a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
@@ -25,7 +25,7 @@ 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.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -34,15 +34,15 @@ import java.util.List;
 /**
  * Custom deserializer for EventCollectorRequest that do validate the events using JSon Schema
  */
-public class EventCollectorRequestDeserializer extends StdDeserializer<EventsCollectorRequest> {
+public class EventsCollectorRequestDeserializer extends StdDeserializer<EventsCollectorRequest> {
 
     private final SchemaService schemaService;
 
-    public EventCollectorRequestDeserializer(SchemaService schemaRegistry) {
+    public EventsCollectorRequestDeserializer(SchemaService schemaRegistry) {
         this(null, schemaRegistry);
     }
 
-    public EventCollectorRequestDeserializer(Class<EventsCollectorRequest> vc, SchemaService schemaService) {
+    public EventsCollectorRequestDeserializer(Class<EventsCollectorRequest> vc, SchemaService schemaService) {
         super(vc);
         this.schemaService = schemaService;
     }
@@ -51,7 +51,7 @@ public class EventCollectorRequestDeserializer extends StdDeserializer<EventsCol
     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")) {
-            throw new InvalidRequestException("Invalid received data", "Invalid received data");
+            throw new InvalidRequestException("Invalid events collector object", "Invalid received data");
         }
 
         // Validate schema on each event
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 7748b9aa9..324216586 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,18 +18,17 @@
 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;
 import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
 import org.apache.unomi.api.*;
 import org.apache.unomi.api.conditions.Condition;
-import org.apache.unomi.api.services.ConfigSharingService;
-import org.apache.unomi.api.services.EventService;
-import org.apache.unomi.api.services.PersonalizationService;
-import org.apache.unomi.api.services.PrivacyService;
-import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.RulesService;
+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.utils.Changes;
 import org.apache.unomi.utils.HttpUtils;
@@ -94,6 +93,8 @@ public class ContextJsonEndpoint {
     private ConfigSharingService configSharingService;
     @Reference
     private RestServiceUtils restServiceUtils;
+    @Reference
+    private SchemaService schemaService;
 
     @OPTIONS
     @Path("/context.js")
@@ -110,9 +111,9 @@ public class ContextJsonEndpoint {
     @POST
     @Produces(MediaType.TEXT_PLAIN)
     @Path("/context.js")
-    public Response contextJSAsPost(@Valid ContextRequest contextRequest,
-            @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
-            @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+    public Response contextJSAsPost(ContextRequest contextRequest,
+            @QueryParam("personaId") String personaId,
+            @QueryParam("sessionId") String sessionId,
             @QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
             @QueryParam("invalidateSession") boolean invalidateSession) throws JsonProcessingException {
         return contextJSAsGet(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile, invalidateSession);
@@ -121,9 +122,9 @@ public class ContextJsonEndpoint {
     @GET
     @Produces(MediaType.TEXT_PLAIN)
     @Path("/context.js")
-    public Response contextJSAsGet(@QueryParam("payload") @Valid ContextRequest contextRequest,
-            @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
-            @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+    public Response contextJSAsGet(@QueryParam("payload") ContextRequest contextRequest,
+            @QueryParam("personaId") String personaId,
+            @QueryParam("sessionId") String sessionId,
             @QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
             @QueryParam("invalidateSession") boolean invalidateSession) throws JsonProcessingException {
         ContextResponse contextResponse = contextJSONAsPost(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile,
@@ -138,9 +139,9 @@ public class ContextJsonEndpoint {
     @GET
     @Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
     @Path("/context.json")
-    public ContextResponse contextJSONAsGet(@QueryParam("payload") @Valid ContextRequest contextRequest,
-            @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
-            @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+    public ContextResponse contextJSONAsGet(@QueryParam("payload") ContextRequest contextRequest,
+            @QueryParam("personaId") String personaId,
+            @QueryParam("sessionId") String sessionId,
             @QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
             @QueryParam("invalidateSession") boolean invalidateSession) {
         return contextJSONAsPost(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile, invalidateSession);
@@ -149,11 +150,23 @@ public class ContextJsonEndpoint {
     @POST
     @Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
     @Path("/context.json")
-    public ContextResponse contextJSONAsPost(@Valid ContextRequest contextRequest,
-            @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
-            @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+    public ContextResponse contextJSONAsPost(ContextRequest contextRequest,
+            @QueryParam("personaId") String personaId,
+            @QueryParam("sessionId") String sessionId,
             @QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
             @QueryParam("invalidateSession") boolean invalidateSession) {
+
+        // Schema validation
+        ObjectNode paramsAsJson = JsonNodeFactory.instance.objectNode();
+        if (personaId != null) {
+            paramsAsJson.put("personaId", personaId);
+        }
+        if (sessionId != null) {
+            paramsAsJson.put("sessionId", sessionId);
+        }
+        if (!schemaService.isValid(paramsAsJson, "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0")) {
+            throw new InvalidRequestException("Invalid parameter", "Invalid received data");
+        }
         Date timestamp = new Date();
         if (timestampAsLong != null) {
             timestamp = new Date(timestampAsLong);
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
index 28d312a8d..11b4d8c62 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
@@ -28,6 +28,7 @@ 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.ProfileService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 import org.apache.unomi.rest.models.EventCollectorResponse;
 import org.apache.unomi.rest.service.RestServiceUtils;
 import org.apache.unomi.utils.Changes;
@@ -88,19 +89,22 @@ public class EventsCollectorEndpoint {
 
     @GET
     @Path("/eventcollector")
-    public EventCollectorResponse collectAsGet(@QueryParam("payload") @NotNull @Valid EventsCollectorRequest eventsCollectorRequest,
+    public EventCollectorResponse collectAsGet(@QueryParam("payload") EventsCollectorRequest eventsCollectorRequest,
                                                @QueryParam("timestamp") Long timestampAsString) {
         return doEvent(eventsCollectorRequest, timestampAsString);
     }
 
     @POST
     @Path("/eventcollector")
-    public EventCollectorResponse collectAsPost(@NotNull @Valid EventsCollectorRequest eventsCollectorRequest,
+    public EventCollectorResponse collectAsPost(EventsCollectorRequest eventsCollectorRequest,
             @QueryParam("timestamp") Long timestampAsLong) {
         return doEvent(eventsCollectorRequest, timestampAsLong);
     }
 
     private EventCollectorResponse doEvent(EventsCollectorRequest eventsCollectorRequest, Long timestampAsLong) {
+        if (eventsCollectorRequest == null) {
+            throw new InvalidRequestException("events collector cannot be empty", "Invalid received data");
+        }
         Date timestamp = new Date();
         if (timestampAsLong != null) {
             timestamp = new Date(timestampAsLong);
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
similarity index 83%
rename from rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java
rename to rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
index b41a6575f..d97495e6a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java
+++ b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.unomi.rest.validation.request;
+package org.apache.unomi.rest.exception;
 
 /**
  * Exception throw when the request exceed the configured limit size
@@ -26,6 +26,11 @@ public class InvalidRequestException extends RuntimeException {
      */
     private final String responseMessage;
 
+    /**
+     * Build an invalid request
+     * @param message message in the logs. It contains detailed information
+     * @param responseMessage message in the response, sent to the browser, must be vague as possible.
+     */
     public InvalidRequestException(String message, String responseMessage) {
         super(message);
         this.responseMessage = responseMessage;
diff --git a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
index 9dfd29e1a..c793f602f 100644
--- a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
+++ b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
@@ -16,7 +16,6 @@
  */
 package org.apache.unomi.rest.exception;
 
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
 import org.osgi.service.component.annotations.Component;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,7 +32,8 @@ public class InvalidRequestExceptionMapper implements ExceptionMapper<InvalidReq
 
     @Override
     public Response toResponse(InvalidRequestException exception) {
-        logger.error(exception.getMessage(), exception);
+        logger.error("{} - set InvalidRequestExceptionMapper to debug level to get full error", exception.getMessage());
+        logger.debug("error", exception);
 
         return Response.status(Response.Status.BAD_REQUEST).header("Content-Type", MediaType.TEXT_PLAIN)
                 .entity("Request rejected by the server because: " + exception.getResponseMessage()).build();
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 2d43dcb0d..0da55b996 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
@@ -26,8 +26,6 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
 import org.apache.cxf.jaxrs.openapi.OpenApiCustomizer;
 import org.apache.cxf.jaxrs.openapi.OpenApiFeature;
 import org.apache.cxf.jaxrs.security.SimpleAuthorizingFilter;
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor;
 import org.apache.cxf.message.Message;
 import org.apache.unomi.api.ContextRequest;
 import org.apache.unomi.api.EventsCollectorRequest;
@@ -37,10 +35,8 @@ import org.apache.unomi.rest.authentication.AuthenticationFilter;
 import org.apache.unomi.rest.authentication.AuthorizingInterceptor;
 import org.apache.unomi.rest.authentication.RestAuthenticationConfig;
 import org.apache.unomi.rest.deserializers.ContextRequestDeserializer;
-import org.apache.unomi.rest.deserializers.EventCollectorRequestDeserializer;
+import org.apache.unomi.rest.deserializers.EventsCollectorRequestDeserializer;
 import org.apache.unomi.rest.server.provider.RetroCompatibilityParamConverterProvider;
-import org.apache.unomi.rest.validation.JAXRSBeanValidationInInterceptorOverride;
-import org.apache.unomi.rest.validation.BeanValidationService;
 import org.apache.unomi.rest.validation.request.RequestValidatorInterceptor;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
@@ -75,7 +71,6 @@ public class RestServer {
     private Bus serverBus;
     private RestAuthenticationConfig restAuthenticationConfig;
     private List<ExceptionMapper> exceptionMappers = new ArrayList<>();
-    private BeanValidationService beanValidationService;
     private ConfigSharingService configSharingService;
     private SchemaService schemaService;
 
@@ -113,11 +108,6 @@ public class RestServer {
         refreshServer();
     }
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    public void setBeanValidationService(BeanValidationService beanValidationService) {
-        this.beanValidationService = beanValidationService;
-    }
-
     public void removeExceptionMapper(ExceptionMapper exceptionMapper) {
         this.exceptionMappers.remove(exceptionMapper);
         timeOfLastUpdate = System.currentTimeMillis();
@@ -213,7 +203,7 @@ public class RestServer {
 
         Map<Class, StdDeserializer<?>> desers = new HashMap<>();
         desers.put(ContextRequest.class, new ContextRequestDeserializer(schemaService));
-        desers.put(EventsCollectorRequest.class, new EventCollectorRequestDeserializer(schemaService));
+        desers.put(EventsCollectorRequest.class, new EventsCollectorRequestDeserializer(schemaService));
 
 
         // Build the server
@@ -251,14 +241,6 @@ public class RestServer {
         openApiFeature.setCustomizer(customizer);
         jaxrsServerFactoryBean.getFeatures().add(openApiFeature);
 
-        // Hibernate validator config
-        JAXRSBeanValidationInInterceptor beanValidationInInterceptor = new JAXRSBeanValidationInInterceptorOverride();
-        JAXRSBeanValidationOutInterceptor beanValidationOutInterceptor = new JAXRSBeanValidationOutInterceptor();
-        beanValidationInInterceptor.setProvider(beanValidationService.getBeanValidationProvider());
-        beanValidationOutInterceptor.setProvider(beanValidationService.getBeanValidationProvider());
-        inInterceptors.add(beanValidationInInterceptor);
-        outInterceptors.add(beanValidationOutInterceptor);
-
         // Request validator
         inInterceptors.add(new RequestValidatorInterceptor(configSharingService));
 
diff --git a/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java b/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
index d7b6f3e84..fabd37121 100644
--- a/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
+++ b/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
@@ -20,12 +20,9 @@ import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.unomi.api.ContextRequest;
 import org.apache.unomi.api.EventsCollectorRequest;
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.ProcessingException;
 import javax.ws.rs.ext.*;
-import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
@@ -65,7 +62,7 @@ public class RetroCompatibilityParamConverterProvider implements ParamConverterP
                     try {
                         return objectMapper.readValue(factory.createParser(value), rawType);
                     } catch (Exception e) {
-                        throw new InvalidRequestException("Invalid received data", "Invalid received data");
+                        throw new InvalidRequestException(String.format("Unable to deserialize object because %s", e.getMessage()), "Invalid received data");
                     }
                 }
 
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 9f05bd6be..4600f0c1e 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
@@ -16,6 +16,8 @@
  */
 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;
@@ -23,9 +25,9 @@ import org.apache.unomi.api.Session;
 import org.apache.unomi.api.services.ConfigSharingService;
 import org.apache.unomi.api.services.EventService;
 import org.apache.unomi.api.services.PrivacyService;
+import org.apache.unomi.api.services.SchemaService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 import org.apache.unomi.rest.service.RestServiceUtils;
-import org.apache.unomi.rest.validation.BeanValidationService;
-import org.apache.unomi.rest.validation.wrapper.CookieWrapper;
 import org.apache.unomi.utils.Changes;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
@@ -36,6 +38,7 @@ import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.BadRequestException;
 import java.util.Date;
 import java.util.List;
 
@@ -47,15 +50,14 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
     @Reference
     private ConfigSharingService configSharingService;
 
-    @Reference
-    private BeanValidationService beanValidationService;
-
     @Reference
     private PrivacyService privacyService;
 
     @Reference
     private EventService eventService;
 
+    @Reference SchemaService schemaService;
+
     public String getProfileIdCookieValue(HttpServletRequest httpServletRequest) {
         String cookieProfileId = null;
 
@@ -63,8 +65,11 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
 
         if (cookies != null) {
             for (Cookie cookie : cookies) {
-                if (configSharingService.getProperty("profileIdCookieName").equals(cookie.getName())) {
-                    beanValidationService.getBeanValidationProvider().validateBean(new CookieWrapper(cookie.getValue()));
+                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")) {
+                        throw new InvalidRequestException("Invalid profile ID format in cookie", "Invalid received data");
+                    }
                     cookieProfileId = cookie.getValue();
                 }
             }
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java b/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java
deleted file mode 100644
index b691fe7eb..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java
+++ /dev/null
@@ -1,32 +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.validation;
-
-import org.apache.cxf.validation.BeanValidationProvider;
-
-/**
- * This service is just here to provide the CXF BeanValidationProvider in the OSGI context as a service.
- */
-public interface BeanValidationService {
-
-    /**
-     * Get the CXF BeanValidationProvider instance
-     * @return the CXF BeanValidationProvider instance
-     */
-    BeanValidationProvider getBeanValidationProvider();
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java b/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java
deleted file mode 100644
index 485733c11..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java
+++ /dev/null
@@ -1,37 +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.validation;
-
-import static java.util.Collections.singletonList;
-import org.hibernate.validator.HibernateValidator;
-
-import javax.validation.ValidationProviderResolver;
-import javax.validation.spi.ValidationProvider;
-import java.util.List;
-
-/**
- * OSGi-friendly implementation of {@code javax.validation.ValidationProviderResolver} returning
- * {@code org.hibernate.validator.HibernateValidator} instance.
- *
- */
-public class HibernateValidationProviderResolver implements ValidationProviderResolver {
-
-    @Override
-    public List<ValidationProvider<?>> getValidationProviders() {
-        return singletonList(new HibernateValidator());
-    }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java b/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java
deleted file mode 100644
index 44a6d1105..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java
+++ /dev/null
@@ -1,42 +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.validation;
-
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
-import org.apache.cxf.message.Message;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * This class allows to replace the class loader use by
- * javax.el.FactoryFinder.newInstance(FactoryFinder.java:53)
- * to allow to retrieve com.sun.el.ExpressionFactoryImpl which is present in the class loader of this module
- */
-public class JAXRSBeanValidationInInterceptorOverride extends JAXRSBeanValidationInInterceptor {
-    @Override
-    protected void handleValidation(final Message message, final Object resourceInstance, final Method method,
-            final List<Object> arguments) {
-        ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-            Thread.currentThread().setContextClassLoader(JAXRSBeanValidationInInterceptorOverride.class.getClassLoader());
-            super.handleValidation(message, resourceInstance, method, arguments);
-        } finally {
-            Thread.currentThread().setContextClassLoader(currentContextClassLoader);
-        }
-    }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java b/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java
deleted file mode 100644
index 2bccc1811..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java
+++ /dev/null
@@ -1,48 +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.validation.impl;
-
-import org.apache.cxf.validation.BeanValidationProvider;
-import org.apache.unomi.rest.validation.HibernateValidationProviderResolver;
-import org.apache.unomi.rest.validation.BeanValidationService;
-import org.hibernate.validator.HibernateValidator;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-
-@Component(service = BeanValidationService.class)
-public class BeanValidationServiceImpl implements BeanValidationService {
-    private BeanValidationProvider beanValidationProvider;
-
-    @Activate
-    public void activate() {
-        // This is a TCCL (Thread context class loader) hack to for the javax.el.FactoryFinder to use Class.forName(className)
-        // instead of tccl.loadClass(className) to load the class "com.sun.el.ExpressionFactoryImpl".
-        ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
-        try {
-            Thread.currentThread().setContextClassLoader(null);
-            HibernateValidationProviderResolver validationProviderResolver = new HibernateValidationProviderResolver();
-            this.beanValidationProvider = new BeanValidationProvider(validationProviderResolver, HibernateValidator.class);
-        } finally {
-            Thread.currentThread().setContextClassLoader(currentContextClassLoader);
-        }
-    }
-
-    public BeanValidationProvider getBeanValidationProvider() {
-        return beanValidationProvider;
-    }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java b/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
index 4cc23434f..ae19c1039 100644
--- a/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
+++ b/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
@@ -22,6 +22,7 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
 import org.apache.unomi.api.services.ConfigSharingService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java b/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java
deleted file mode 100644
index 6a5040eba..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java
+++ /dev/null
@@ -1,36 +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.validation.wrapper;
-
-import org.apache.unomi.api.utils.ValidationPattern;
-
-import javax.validation.constraints.Pattern;
-
-/**
- * This class exists to allow to wrap a cookie value into an object and validate this object trough
- * the bean validation
- */
-public class CookieWrapper {
-
-    @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN)
-    private String cookie;
-
-    public CookieWrapper(String cookie) {
-        this.cookie = cookie;
-    }
-
-}
diff --git a/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json b/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
new file mode 100644
index 000000000..6e115f3cb
--- /dev/null
+++ b/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
@@ -0,0 +1,16 @@
+{
+  "$id": "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "title": "ContextRequestParams",
+  "type": "object",
+  "properties": {
+    "personaId" : {
+      "type" : "string",
+      "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+    },
+    "sessionId" : {
+      "type" : "string",
+      "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+    }
+  }
+}
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/cookie.json b/services/src/main/resources/META-INF/cxs/schemas/cookie.json
new file mode 100644
index 000000000..1e82ada08
--- /dev/null
+++ b/services/src/main/resources/META-INF/cxs/schemas/cookie.json
@@ -0,0 +1,12 @@
+{
+  "$id": "https://unomi.apache.org/schemas/json/cookie/1-0-0",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "title": "Cookie",
+  "type": "object",
+  "properties": {
+    "profileIdCookieName" : {
+      "type" : "string",
+      "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+    }
+  }
+}
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json b/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
index 39e98ff83..781ff2862 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
@@ -10,10 +10,11 @@
   ],
   "properties": {
     "events" : {
-      "type": ["null", "array"],
+      "type": ["array"],
       "items": {
         "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
-      }
+      },
+      "minItems": 1
     },
     "sessionId" : {
       "type": ["null", "string"],