You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2020/05/18 12:37:05 UTC

[syncope] branch 2_1_X updated: [SYNCOPE-1564] Fixing YAML support

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

ilgrosso pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/2_1_X by this push:
     new 9b0837f  [SYNCOPE-1564] Fixing YAML support
9b0837f is described below

commit 9b0837f125b9f71b937f411a6057f2de84fa4069
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Mon May 18 14:01:07 2020 +0200

    [SYNCOPE-1564] Fixing YAML support
---
 client/lib/pom.xml                                 |   8 +-
 .../client/lib/SyncopeClientFactoryBean.java       |  44 +++-
 common/lib/pom.xml                                 |   6 +
 .../org/apache/syncope/common/lib/BaseBean.java    |  12 +
 .../common/lib/to/AbstractAnnotatedBean.java       |   2 +
 .../common/lib/to/AbstractStartEndBean.java        |   2 +
 .../java/pushpull/stream/CSVStreamConnector.java   |   5 +-
 core/rest-cxf/pom.xml                              |  39 +++
 .../syncope/core/rest/cxf/CheckDomainFilter.java   |  45 ++--
 ...dObjectMapper.java => SyncopeObjectMapper.java} |   7 +-
 .../syncope/core/rest/cxf/SyncopeYAMLMapper.java   |  16 +-
 .../syncope/core/rest/cxf/batch/BatchProcess.java  |   2 +-
 .../core/rest/cxf/service/AbstractServiceImpl.java |   5 +-
 .../rest/cxf/service/AnyObjectServiceImpl.java     |   1 -
 .../rest-cxf/src/main/resources/restCXFContext.xml |   9 +-
 .../rest/cxf/service/AnyObjectServiceTest.java     | 289 +++++++++++++++++++++
 core/rest-cxf/src/test/resources/restCXFTest.xml   |  81 ++++++
 .../src/main/resources/jboss/restCXFContext.xml    |   9 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |   5 +-
 .../org/apache/syncope/fit/core/AuditITCase.java   |   2 +-
 .../org/apache/syncope/fit/core/BatchITCase.java   |  22 +-
 .../apache/syncope/fit/core/BpmnProcessITCase.java |   9 +-
 .../apache/syncope/fit/core/DynRealmITCase.java    |   2 +-
 .../syncope/fit/core/LinkedAccountITCase.java      |  10 +-
 .../org/apache/syncope/fit/core/OpenAPIITCase.java |   2 +-
 .../apache/syncope/fit/core/UserRequestITCase.java |  26 +-
 26 files changed, 566 insertions(+), 94 deletions(-)

diff --git a/client/lib/pom.xml b/client/lib/pom.xml
index fccf2d3..659f783 100644
--- a/client/lib/pom.xml
+++ b/client/lib/pom.xml
@@ -54,8 +54,12 @@ under the License.
     <dependency>
       <groupId>com.fasterxml.jackson.jaxrs</groupId>
       <artifactId>jackson-jaxrs-json-provider</artifactId>
-    </dependency>  
- 
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-yaml-provider</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>joda-time</groupId>
       <artifactId>joda-time</artifactId>
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
index 40d3b5d..8d9286f 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -19,18 +19,19 @@
 package org.apache.syncope.client.lib;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 import com.fasterxml.jackson.datatype.joda.JodaModule;
 import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
-import java.util.ArrayList;
+import com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import javax.ws.rs.core.MediaType;
 import javax.xml.bind.Marshaller;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.configuration.jsse.TLSClientParameters;
-import org.apache.cxf.feature.Feature;
 import org.apache.cxf.ext.logging.LoggingFeature;
 import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
@@ -74,6 +75,8 @@ public class SyncopeClientFactoryBean {
 
     private JAXBElementProvider<?> jaxbProvider;
 
+    private JacksonJaxbYAMLProvider yamlProvider;
+
     private RestClientExceptionMapper exceptionMapper;
 
     private String address;
@@ -91,7 +94,7 @@ public class SyncopeClientFactoryBean {
     protected JacksonJaxbJsonProvider defaultJsonProvider() {
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.registerModule(new JodaModule());
-        objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
         return new JacksonJaxbJsonProvider(objectMapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS);
     }
 
@@ -114,6 +117,13 @@ public class SyncopeClientFactoryBean {
         return defaultJAXBProvider;
     }
 
+    protected JacksonJaxbYAMLProvider defaultYamlProvider() {
+        YAMLMapper yamlMapper = new YAMLMapper();
+        yamlMapper.registerModule(new JodaModule());
+        yamlMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        return new JacksonJaxbYAMLProvider(yamlMapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS);
+    }
+
     protected RestClientExceptionMapper defaultExceptionMapper() {
         return new RestClientExceptionMapper();
     }
@@ -134,16 +144,14 @@ public class SyncopeClientFactoryBean {
         defaultRestClientFactoryBean.setThreadSafe(true);
         defaultRestClientFactoryBean.setInheritHeaders(true);
 
-        List<Feature> features = new ArrayList<>();
-        features.add(new LoggingFeature());
-        defaultRestClientFactoryBean.setFeatures(features);
+        defaultRestClientFactoryBean.setFeatures(Arrays.asList(new LoggingFeature()));
 
-        List<Object> providers = new ArrayList<>(4);
-        providers.add(new DateParamConverterProvider());
-        providers.add(getJaxbProvider());
-        providers.add(getJsonProvider());
-        providers.add(getExceptionMapper());
-        defaultRestClientFactoryBean.setProviders(providers);
+        defaultRestClientFactoryBean.setProviders(Arrays.asList(
+                new DateParamConverterProvider(),
+                getJsonProvider(),
+                getJaxbProvider(),
+                getYamlProvider(),
+                getExceptionMapper()));
 
         return defaultRestClientFactoryBean;
     }
@@ -169,6 +177,16 @@ public class SyncopeClientFactoryBean {
         return this;
     }
 
+    public JacksonJaxbYAMLProvider getYamlProvider() {
+        return yamlProvider == null
+                ? defaultYamlProvider()
+                : yamlProvider;
+    }
+
+    public void setYamlProvider(final JacksonJaxbYAMLProvider yamlProvider) {
+        this.yamlProvider = yamlProvider;
+    }
+
     public RestClientExceptionMapper getExceptionMapper() {
         return exceptionMapper == null
                 ? defaultExceptionMapper()
diff --git a/common/lib/pom.xml b/common/lib/pom.xml
index a498f60..07033bd 100644
--- a/common/lib/pom.xml
+++ b/common/lib/pom.xml
@@ -54,6 +54,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-yaml</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java b/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java
index edfbeff..3156171 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java
@@ -19,7 +19,19 @@
 package org.apache.syncope.common.lib;
 
 import java.io.Serializable;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.to.AbstractAnnotatedBean;
+import org.apache.syncope.common.lib.to.AbstractStartEndBean;
+import org.apache.syncope.common.lib.to.AccessTokenTO;
+import org.apache.syncope.common.lib.to.ProvisioningReport;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.RemediationTO;
 
+@XmlType
+@XmlSeeAlso({ AbstractAnnotatedBean.class, AbstractStartEndBean.class, AccessTokenTO.class, AuditEntry.class,
+    ProvisioningReport.class, RealmTO.class, RemediationTO.class })
 public abstract class BaseBean implements Serializable {
 
     private static final long serialVersionUID = 8243277089603485380L;
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
index 7a4df9e..682a9ab 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
@@ -21,6 +21,7 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.Date;
+import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -31,6 +32,7 @@ import org.apache.syncope.common.lib.BaseBean;
  * Abstract wrapper for common system information.
  */
 @XmlType
+@XmlSeeAlso(AnyTO.class)
 public abstract class AbstractAnnotatedBean extends BaseBean implements EntityTO {
 
     private static final long serialVersionUID = -930797879027642457L;
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
index e1bbe0f..29e60c4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractStartEndBean.java
@@ -20,12 +20,14 @@ package org.apache.syncope.common.lib.to;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.Date;
+import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.BaseBean;
 
 @XmlType
+@XmlSeeAlso({ ExecTO.class, ReportTO.class, TaskTO.class })
 public class AbstractStartEndBean extends BaseBean {
 
     private static final long serialVersionUID = 2399577415544539917L;
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/CSVStreamConnector.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/CSVStreamConnector.java
index 5f9e994..634ddbd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/CSVStreamConnector.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/CSVStreamConnector.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.java.pushpull.stream;
 import com.fasterxml.jackson.databind.MappingIterator;
 import com.fasterxml.jackson.databind.SequenceWriter;
 import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvParser;
 import com.fasterxml.jackson.dataformat.csv.CsvSchema;
 import java.io.IOException;
 import java.io.InputStream;
@@ -109,7 +110,9 @@ public class CSVStreamConnector implements Connector, AutoCloseable {
     public MappingIterator<Map<String, String>> reader() throws IOException {
         synchronized (this) {
             if (reader == null) {
-                reader = new CsvMapper().readerFor(Map.class).with(schemaBuilder.build()).readValues(in);
+                reader = new CsvMapper().
+                        enable(CsvParser.Feature.SKIP_EMPTY_LINES).
+                        readerFor(Map.class).with(schemaBuilder.build()).readValues(in);
             }
         }
         return reader;
diff --git a/core/rest-cxf/pom.xml b/core/rest-cxf/pom.xml
index 61a6d9b..724e28d 100644
--- a/core/rest-cxf/pom.xml
+++ b/core/rest-cxf/pom.xml
@@ -146,6 +146,45 @@ under the License.
       <groupId>org.webjars</groupId>
       <artifactId>highlightjs</artifactId>
     </dependency>
+
+    <!-- TEST -->
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-transports-local</artifactId>
+      <version>${cxf.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.bval</groupId>
+      <artifactId>bval-jsr</artifactId>
+      <scope>test</scope>
+    </dependency>      
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>${slf4j.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
index f2aabad3..f46e199 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/CheckDomainFilter.java
@@ -46,35 +46,30 @@ public class CheckDomainFilter implements ContainerRequestFilter {
 
     @Override
     public void filter(final ContainerRequestContext reqContext) throws IOException {
-        final String domain = reqContext.getHeaderString(RESTHeaders.DOMAIN);
+        String domain = reqContext.getHeaderString(RESTHeaders.DOMAIN);
         if (domain != null && !SyncopeConstants.MASTER_DOMAIN.equals(domain)) {
-            AuthContextUtils.execWithAuthContext(
-                    SyncopeConstants.MASTER_DOMAIN, new AuthContextUtils.Executable<Void>() {
+            AuthContextUtils.execWithAuthContext(SyncopeConstants.MASTER_DOMAIN, () -> {
+                if (domainDAO.find(domain) == null) {
+                    String message = "Domain '" + domain + "' not available";
 
-                @Override
-                public Void exec() {
-                    if (domainDAO.find(domain) == null) {
-                        String message = "Domain '" + domain + "' not available";
+                    ErrorTO error = new ErrorTO();
+                    error.setStatus(Response.Status.NOT_FOUND.getStatusCode());
+                    error.setType(ClientExceptionType.NotFound);
+                    error.getElements().add(message);
 
-                        ErrorTO error = new ErrorTO();
-                        error.setStatus(Response.Status.NOT_FOUND.getStatusCode());
-                        error.setType(ClientExceptionType.NotFound);
-                        error.getElements().add(message);
-
-                        reqContext.abortWith(Response.status(Response.Status.NOT_FOUND).
-                                entity(error).
-                                header(HttpHeaders.CONTENT_TYPE,
-                                        reqContext.getAcceptableMediaTypes().isEmpty()
-                                        ? MediaType.APPLICATION_JSON
-                                        : reqContext.getAcceptableMediaTypes().get(0).toString()).
-                                header(RESTHeaders.ERROR_CODE,
-                                        ClientExceptionType.NotFound.name()).
-                                header(RESTHeaders.ERROR_INFO,
-                                        ClientExceptionType.NotFound.getInfoHeaderValue(message)).
-                                build());
-                    }
-                    return null;
+                    reqContext.abortWith(Response.status(Response.Status.NOT_FOUND).
+                            entity(error).
+                            header(HttpHeaders.CONTENT_TYPE,
+                                    reqContext.getAcceptableMediaTypes().isEmpty()
+                                    ? MediaType.APPLICATION_JSON
+                                    : reqContext.getAcceptableMediaTypes().get(0).toString()).
+                            header(RESTHeaders.ERROR_CODE,
+                                    ClientExceptionType.NotFound.name()).
+                            header(RESTHeaders.ERROR_INFO,
+                                    ClientExceptionType.NotFound.getInfoHeaderValue(message)).
+                            build());
                 }
+                return null;
             });
         }
     }
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/UnwrappedObjectMapper.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeObjectMapper.java
similarity index 93%
rename from core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/UnwrappedObjectMapper.java
rename to core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeObjectMapper.java
index 31b1dfd..42d121d 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/UnwrappedObjectMapper.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeObjectMapper.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.rest.cxf;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.joda.JodaModule;
 import java.io.File;
 import java.io.IOException;
@@ -32,15 +33,15 @@ import java.util.Map;
  * Jackson ObjectMapper that unwraps singleton map values and enable default
  * typing for handling abstract types serialization.
  */
-public class UnwrappedObjectMapper extends ObjectMapper {
+public class SyncopeObjectMapper extends ObjectMapper {
 
     private static final long serialVersionUID = -317191546835195103L;
 
-    public UnwrappedObjectMapper() {
+    public SyncopeObjectMapper() {
         super();
 
         registerModule(new JodaModule());
-        configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
     }
 
     /**
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeYAMLMapper.java
similarity index 61%
copy from common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java
copy to core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeYAMLMapper.java
index edfbeff..b9f2ba3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/BaseBean.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeYAMLMapper.java
@@ -16,12 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib;
+package org.apache.syncope.core.rest.cxf;
 
-import java.io.Serializable;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import com.fasterxml.jackson.datatype.joda.JodaModule;
 
-public abstract class BaseBean implements Serializable {
+public class SyncopeYAMLMapper extends YAMLMapper {
 
-    private static final long serialVersionUID = 8243277089603485380L;
+    private static final long serialVersionUID = 1022020055828974308L;
 
+    public SyncopeYAMLMapper() {
+        super();
+
+        registerModule(new JodaModule());
+        configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+    }
 }
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/batch/BatchProcess.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/batch/BatchProcess.java
index a76d418..e6426fd 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/batch/BatchProcess.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/batch/BatchProcess.java
@@ -92,7 +92,7 @@ public class BatchProcess implements Runnable {
 
         List<BatchResponseItem> batchResponseItems = new ArrayList<>(batchRequestItems.size());
 
-        batchRequestItems.forEach((BatchRequestItem reqItem) -> {
+        batchRequestItems.forEach(reqItem -> {
             LOG.debug("Batch item:\n{}", reqItem);
 
             AbstractHTTPDestination dest = destinationRegistry.getDestinationForPath(reqItem.getRequestURI(), true);
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
index 0f7c42d..c1a7c7f 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
@@ -227,9 +227,7 @@ abstract class AbstractServiceImpl implements JAXRSService {
 
         UriBuilder builder = uriInfo.getAbsolutePathBuilder();
         MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
-        queryParams.forEach((key, value) -> {
-            builder.queryParam(key, value.toArray());
-        });
+        queryParams.forEach((key, value) -> builder.queryParam(key, value.toArray()));
 
         if (result.getPage() > 1) {
             result.setPrev(builder.
@@ -246,5 +244,4 @@ abstract class AbstractServiceImpl implements JAXRSService {
 
         return result;
     }
-
 }
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
index 3a7d40b..fd2ead6 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
@@ -98,5 +98,4 @@ public class AnyObjectServiceImpl extends AbstractAnyService<AnyObjectTO, AnyObj
 
         return super.search(anyQuery);
     }
-
 }
diff --git a/core/rest-cxf/src/main/resources/restCXFContext.xml b/core/rest-cxf/src/main/resources/restCXFContext.xml
index 2d5ca80..8522d8b 100644
--- a/core/rest-cxf/src/main/resources/restCXFContext.xml
+++ b/core/rest-cxf/src/main/resources/restCXFContext.xml
@@ -65,12 +65,15 @@ under the License.
 
   <bean id="dateParamConverterProvider" class="org.apache.syncope.common.rest.api.DateParamConverterProvider"/>
 
-  <bean id="jacksonObjectMapper" class="org.apache.syncope.core.rest.cxf.UnwrappedObjectMapper"/>
+  <bean id="syncopeObjectMapper" class="org.apache.syncope.core.rest.cxf.SyncopeObjectMapper"/>
   <bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
-    <property name="mapper" ref="jacksonObjectMapper"/>
+    <property name="mapper" ref="syncopeObjectMapper"/>
   </bean>
 
-  <bean id="yamlProvider" class="com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider"/>
+  <bean id="syncopeYAMLMapper" class="org.apache.syncope.core.rest.cxf.SyncopeYAMLMapper"/>
+  <bean id="yamlProvider" class="com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider">
+    <property name="mapper" ref="syncopeYAMLMapper"/>
+  </bean>
 
   <bean id="exceptionMapper" class="org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper"/>
 
diff --git a/core/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java b/core/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
new file mode 100644
index 0000000..3f8bc1f
--- /dev/null
+++ b/core/rest-cxf/src/test/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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.syncope.core.rest.cxf.service;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.UUID;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.search.SearchBean;
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.jaxrs.ext.search.SearchContext;
+import org.apache.cxf.jaxrs.ext.search.SearchContextProvider;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.impl.UriBuilderImpl;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
+import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
+import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
+import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
+import org.apache.cxf.transport.local.LocalConduit;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.rest.api.DateParamConverterProvider;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyObjectService;
+import org.apache.syncope.core.logic.AnyObjectLogic;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
+import org.apache.syncope.core.rest.cxf.AddETagFilter;
+import org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import org.springframework.test.util.ReflectionTestUtils;
+
+@SpringJUnitConfig(locations = { "classpath:restCXFTest.xml" })
+public class AnyObjectServiceTest {
+
+    private static final String LOCAL_ADDRESS = "local://anyObjects";
+
+    private static Server SERVER;
+
+    @Autowired
+    private JAXBElementProvider<?> jaxbProvider;
+
+    @Autowired
+    private DateParamConverterProvider dateParamConverterProvider;
+
+    @Autowired
+    private JacksonJaxbJsonProvider jsonProvider;
+
+    @Autowired
+    private JacksonJaxbYAMLProvider yamlProvider;
+
+    @Autowired
+    private RestServiceExceptionMapper exceptionMapper;
+
+    @Autowired
+    private JAXRSBeanValidationInInterceptor validationInInterceptor;
+
+    @Autowired
+    private GZIPInInterceptor gzipInInterceptor;
+
+    @Autowired
+    private GZIPOutInterceptor gzipOutInterceptor;
+
+    @Autowired
+    private SearchContextProvider searchContextProvider;
+
+    @Autowired
+    private AddETagFilter addETagFilter;
+
+    @BeforeEach
+    public void setup() {
+        if (SERVER == null) {
+            AnyObjectDAO anyObjectDAO = mock(AnyObjectDAO.class);
+
+            AnyObjectLogic logic = mock(AnyObjectLogic.class);
+            when(logic.search(any(SearchCond.class), anyInt(), anyInt(), anyList(), anyString(), anyBoolean())).
+                    thenAnswer(ic -> {
+                        AnyObjectTO printer1 = new AnyObjectTO();
+                        printer1.setKey(UUID.randomUUID().toString());
+                        printer1.setName("printer1");
+                        printer1.setType("PRINTER");
+                        printer1.getPlainAttrs().add(new AttrTO.Builder().schema("location").value("here").build());
+
+                        AnyObjectTO printer2 = new AnyObjectTO();
+                        printer2.setKey(UUID.randomUUID().toString());
+                        printer2.setName("printer2");
+                        printer2.setType("PRINTER");
+                        printer2.getPlainAttrs().add(new AttrTO.Builder().schema("location").value("there").build());
+
+                        return Pair.of(2, Arrays.asList(printer1, printer2));
+                    });
+            when(logic.create(any(AnyObjectTO.class), anyBoolean())).thenAnswer(ic -> {
+                AnyObjectTO anyObjectTO = ic.getArgument(0);
+                anyObjectTO.setKey(UUID.randomUUID().toString());
+
+                ProvisioningResult<AnyObjectTO> result = new ProvisioningResult<>();
+                result.setEntity(anyObjectTO);
+                return result;
+            });
+
+            SearchCondVisitor searchCondVisitor = mock(SearchCondVisitor.class);
+            when(searchCondVisitor.getQuery()).thenReturn(new SearchCond());
+
+            @SuppressWarnings("unchecked")
+            SearchCondition<SearchBean> sc = mock(SearchCondition.class);
+            doNothing().when(sc).accept(any());
+            SearchContext searchContext = mock(SearchContext.class);
+            when(searchContext.getCondition(anyString(), eq(SearchBean.class))).thenReturn(sc);
+
+            UriInfo uriInfo = mock(UriInfo.class);
+            when(uriInfo.getAbsolutePathBuilder()).thenReturn(new UriBuilderImpl());
+            when(uriInfo.getQueryParameters()).thenReturn(new MetadataMap<>());
+
+            MessageContext messageContext = mock(MessageContext.class);
+            MockHttpServletRequest httpRequest = new MockHttpServletRequest();
+            httpRequest.addHeader(RESTHeaders.NULL_PRIORITY_ASYNC, "false");
+            when(messageContext.getHttpServletRequest()).thenReturn(httpRequest);
+            when(messageContext.getHttpServletResponse()).thenReturn(new MockHttpServletResponse());
+
+            Request request = mock(Request.class);
+            when(request.evaluatePreconditions(any(Date.class))).thenReturn(Response.notModified());
+            when(messageContext.getRequest()).thenReturn(request);
+
+            AnyObjectServiceImpl service = new AnyObjectServiceImpl();
+            ReflectionTestUtils.setField(service, "anyObjectDAO", anyObjectDAO);
+            ReflectionTestUtils.setField(service, "logic", logic);
+            ReflectionTestUtils.setField(service, "searchCondVisitor", searchCondVisitor);
+            ReflectionTestUtils.setField(service, "searchContext", searchContext);
+            ReflectionTestUtils.setField(service, "uriInfo", uriInfo);
+            ReflectionTestUtils.setField(service, "messageContext", messageContext);
+
+            JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+            sf.setAddress(LOCAL_ADDRESS);
+            sf.setResourceClasses(AnyObjectService.class);
+            sf.setResourceProvider(
+                    AnyObjectService.class,
+                    new SingletonResourceProvider(service, true));
+
+            sf.setInInterceptors(Arrays.asList(gzipInInterceptor, validationInInterceptor));
+            sf.setOutInterceptors(Arrays.asList(gzipOutInterceptor));
+
+            sf.setProviders(Arrays.asList(dateParamConverterProvider, jaxbProvider, jsonProvider, yamlProvider,
+                    exceptionMapper, searchContextProvider, addETagFilter));
+
+            SERVER = sf.create();
+        }
+
+        assertNotNull(SERVER);
+    }
+
+    private WebClient client(final MediaType mediaType) {
+        WebClient client = WebClient.create(LOCAL_ADDRESS, Arrays.asList(
+                dateParamConverterProvider, jsonProvider, jaxbProvider, yamlProvider));
+        WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
+        return client.accept(mediaType).type(mediaType).path("anyObjects");
+    }
+
+    private InputStream list(final MediaType mediaType) {
+        Response response = client(mediaType).
+                query("fiql", "$type==PRINTER").
+                query("page", "1").
+                query("size", "10").
+                get();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+
+        return (InputStream) response.getEntity();
+    }
+
+    private void checkList(final PagedResult<AnyObjectTO> list) {
+        assertEquals(2, list.getTotalCount());
+        assertEquals(2, list.getResult().size());
+
+        assertEquals("printer1", list.getResult().get(0).getName());
+        assertEquals("PRINTER", list.getResult().get(0).getType());
+
+        assertEquals("there", list.getResult().get(1).getPlainAttr("location").get().getValues().get(0));
+    }
+
+    @Test
+    public void jsonList() throws IOException {
+        InputStream in = list(MediaType.APPLICATION_JSON_TYPE);
+
+        PagedResult<AnyObjectTO> list = new ObjectMapper().
+                readValue(IOUtils.toString(in), new TypeReference<PagedResult<AnyObjectTO>>() {
+                });
+        checkList(list);
+    }
+
+    @Test
+    public void xmlList() throws IOException, JAXBException {
+        InputStream in = list(MediaType.APPLICATION_XML_TYPE);
+
+        JAXBContext context = JAXBContext.newInstance(PagedResult.class, AnyObjectTO.class);
+        @SuppressWarnings("unchecked")
+        PagedResult<AnyObjectTO> list = (PagedResult<AnyObjectTO>) context.createUnmarshaller().unmarshal(in);
+        checkList(list);
+    }
+
+    @Test
+    public void yamlList() throws IOException {
+        InputStream in = list(RESTHeaders.APPLICATION_YAML_TYPE);
+
+        PagedResult<AnyObjectTO> list = new YAMLMapper().
+                readValue(IOUtils.toString(in), new TypeReference<PagedResult<AnyObjectTO>>() {
+                });
+        checkList(list);
+    }
+
+    private void create(final MediaType mediaType) {
+        AnyObjectTO newPrinter = new AnyObjectTO();
+        newPrinter.setName("newPrinter");
+        newPrinter.setType("PRINTER");
+        newPrinter.getPlainAttrs().add(new AttrTO.Builder().schema("location").value("new").build());
+
+        Response response = client(mediaType).post(newPrinter);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        assertNotNull(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+    }
+
+    @Test
+    public void jsonCreate() {
+        create(MediaType.APPLICATION_JSON_TYPE);
+    }
+
+    @Test
+    public void xmlCreate() {
+        create(MediaType.APPLICATION_XML_TYPE);
+    }
+
+    @Test
+    public void yamlCreate() {
+        create(RESTHeaders.APPLICATION_YAML_TYPE);
+    }
+}
diff --git a/core/rest-cxf/src/test/resources/restCXFTest.xml b/core/rest-cxf/src/test/resources/restCXFTest.xml
new file mode 100644
index 0000000..3acbed5
--- /dev/null
+++ b/core/rest-cxf/src/test/resources/restCXFTest.xml
@@ -0,0 +1,81 @@
+<?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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+  <import resource="classpath:META-INF/cxf/cxf.xml"/>
+  <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+  <bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
+    <property name="namespacePrefixes">
+      <map>
+        <entry key="http://syncope.apache.org/2.1">
+          <value>syncope21</value>
+        </entry>
+      </map>      
+    </property>
+    <property name="depthProperties">
+      <bean id="depthProperties" class="org.apache.cxf.staxutils.DocumentDepthProperties">
+        <property name="innerElementCountThreshold" value="500"/>
+      </bean>
+    </property>
+    <property name="collectionWrapperMap">
+      <map>
+        <entry>
+          <key>
+            <value>org.apache.syncope.common.lib.policy.PolicyTO</value>
+          </key>
+          <value>policies</value>
+        </entry>
+      </map>
+    </property>
+  </bean>
+
+  <bean id="dateParamConverterProvider" class="org.apache.syncope.common.rest.api.DateParamConverterProvider"/>
+
+  <bean id="jacksonObjectMapper" class="org.apache.syncope.core.rest.cxf.UnwrappedObjectMapper"/>
+  <bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
+    <property name="mapper" ref="jacksonObjectMapper"/>
+  </bean>
+
+  <bean id="syncopeYAMLMapper" class="org.apache.syncope.core.rest.cxf.SyncopeYAMLMapper"/>
+  <bean id="yamlProvider" class="com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider">
+    <property name="mapper" ref="syncopeYAMLMapper"/>
+  </bean>
+
+  <bean id="exceptionMapper" class="org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper"/>
+
+  <bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider"/>
+  <bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
+    <property name="provider" ref="validationProvider"/>
+  </bean>
+
+  <bean id="gzipInInterceptor" class="org.apache.cxf.transport.common.gzip.GZIPInInterceptor"/>
+  <bean id="gzipOutInterceptor" class="org.apache.cxf.transport.common.gzip.GZIPOutInterceptor">
+    <property name="threshold" value="0"/>
+    <property name="force" value="true"/>
+  </bean>
+  
+  <bean id="searchContextProvider" class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/>
+    
+  <bean id="addETagFilter" class="org.apache.syncope.core.rest.cxf.AddETagFilter"/>
+</beans>
diff --git a/fit/core-reference/src/main/resources/jboss/restCXFContext.xml b/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
index 250cfdc..1f6bf42 100644
--- a/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
+++ b/fit/core-reference/src/main/resources/jboss/restCXFContext.xml
@@ -65,12 +65,15 @@ under the License.
 
   <bean id="dateParamConverterProvider" class="org.apache.syncope.common.rest.api.DateParamConverterProvider"/>
 
-  <bean id="jacksonObjectMapper" class="org.apache.syncope.core.rest.cxf.UnwrappedObjectMapper"/>
+  <bean id="syncopeObjectMapper" class="org.apache.syncope.core.rest.cxf.SyncopeObjectMapper"/>
   <bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
-    <property name="mapper" ref="jacksonObjectMapper"/>
+    <property name="mapper" ref="syncopeObjectMapper"/>
   </bean>
 
-  <bean id="yamlProvider" class="com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider"/>
+  <bean id="syncopeYAMLMapper" class="org.apache.syncope.core.rest.cxf.SyncopeYAMLMapper"/>
+  <bean id="yamlProvider" class="com.fasterxml.jackson.jaxrs.yaml.JacksonJaxbYAMLProvider">
+    <property name="mapper" ref="syncopeYAMLMapper"/>
+  </bean>
 
   <bean id="exceptionMapper" class="org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper"/>
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 1709427..d199310 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -121,7 +122,9 @@ public abstract class AbstractITCase {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractITCase.class);
 
-    protected static final ObjectMapper MAPPER = new ObjectMapper();
+    protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+    protected static final YAMLMapper YAML_MAPPER = new YAMLMapper();
 
     protected static final String ADMIN_UNAME = "admin";
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
index 8f4d881..76f2c83 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
@@ -225,7 +225,7 @@ public class AuditITCase extends AbstractITCase {
         entries = query(query, MAX_WAIT_SECONDS);
         assertEquals(pre + 1, entries.size());
 
-        ConnInstanceTO restore = MAPPER.readValue(entries.get(0).getBefore(), ConnInstanceTO.class);
+        ConnInstanceTO restore = OBJECT_MAPPER.readValue(entries.get(0).getBefore(), ConnInstanceTO.class);
         connectorService.update(restore);
 
         ldapConn = connectorService.read(connectorKey, null);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
index 8763f29..b31fba5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
@@ -71,17 +71,17 @@ public class BatchITCase extends AbstractITCase {
     private String requestBody(final String boundary) throws JsonProcessingException, JAXBException {
         List<BatchRequestItem> reqItems = new ArrayList<>();
 
-        // 1. create user as JSON
+        // 1. create user as YAML
         UserTO user = UserITCase.getUniqueSampleTO("batch@syncope.apache.org");
         assertNotEquals("/odd", user.getRealm());
-        String createUserPayload = MAPPER.writeValueAsString(user);
+        String createUserPayload = YAML_MAPPER.writeValueAsString(user);
 
         BatchRequestItem createUser = new BatchRequestItem();
         createUser.setMethod(HttpMethod.POST);
         createUser.setRequestURI("/users");
         createUser.setHeaders(new HashMap<>());
-        createUser.getHeaders().put(HttpHeaders.ACCEPT, Arrays.asList(MediaType.APPLICATION_JSON));
-        createUser.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON));
+        createUser.getHeaders().put(HttpHeaders.ACCEPT, Arrays.asList(RESTHeaders.APPLICATION_YAML));
+        createUser.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(RESTHeaders.APPLICATION_YAML));
         createUser.getHeaders().put(HttpHeaders.CONTENT_LENGTH, Arrays.asList(createUserPayload.length()));
         createUser.setContent(createUserPayload);
         reqItems.add(createUser);
@@ -108,7 +108,7 @@ public class BatchITCase extends AbstractITCase {
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(user.getUsername());
         userPatch.setRealm(new StringReplacePatchItem.Builder().value("/odd").build());
-        String updateUserPayload = MAPPER.writeValueAsString(userPatch);
+        String updateUserPayload = OBJECT_MAPPER.writeValueAsString(userPatch);
 
         BatchRequestItem updateUser = new BatchRequestItem();
         updateUser.setMethod(HttpMethod.PATCH);
@@ -153,8 +153,8 @@ public class BatchITCase extends AbstractITCase {
         assertNotNull(resItems.get(0).getHeaders().get(HttpHeaders.ETAG));
         assertNotNull(resItems.get(0).getHeaders().get(RESTHeaders.DOMAIN));
         assertNotNull(resItems.get(0).getHeaders().get(RESTHeaders.RESOURCE_KEY));
-        assertEquals(MediaType.APPLICATION_JSON, resItems.get(0).getHeaders().get(HttpHeaders.CONTENT_TYPE).get(0));
-        ProvisioningResult<UserTO> user = MAPPER.readValue(
+        assertEquals(RESTHeaders.APPLICATION_YAML, resItems.get(0).getHeaders().get(HttpHeaders.CONTENT_TYPE).get(0));
+        ProvisioningResult<UserTO> user = YAML_MAPPER.readValue(
                 resItems.get(0).getContent(), new TypeReference<ProvisioningResult<UserTO>>() {
         });
         assertNotNull(user.getEntity().getKey());
@@ -190,7 +190,7 @@ public class BatchITCase extends AbstractITCase {
         assertEquals(Response.Status.OK.getStatusCode(), resItems.get(5).getStatus());
         assertNotNull(resItems.get(5).getHeaders().get(RESTHeaders.DOMAIN));
         assertEquals(MediaType.APPLICATION_JSON, resItems.get(5).getHeaders().get(HttpHeaders.CONTENT_TYPE).get(0));
-        group = MAPPER.readValue(
+        group = OBJECT_MAPPER.readValue(
                 resItems.get(5).getContent(), new TypeReference<ProvisioningResult<GroupTO>>() {
         });
         assertNotNull(group);
@@ -268,15 +268,17 @@ public class BatchITCase extends AbstractITCase {
     private BatchRequest batchRequest() {
         BatchRequest batchRequest = adminClient.batch();
 
-        // 1. create user as JSON
+        // 1. create user as YAML
         UserService batchUserService = batchRequest.getService(UserService.class);
+        Client client = WebClient.client(batchUserService).reset();
+        client.type(RESTHeaders.APPLICATION_YAML).accept(RESTHeaders.APPLICATION_YAML);
         UserTO user = UserITCase.getUniqueSampleTO("batch@syncope.apache.org");
         assertNotEquals("/odd", user.getRealm());
         batchUserService.create(user, true);
 
         // 2. create group as XML
         GroupService batchGroupService = batchRequest.getService(GroupService.class);
-        Client client = WebClient.client(batchGroupService).reset();
+        client = WebClient.client(batchGroupService).reset();
         client.type(MediaType.APPLICATION_XML).accept(MediaType.APPLICATION_XML);
         GroupTO group = GroupITCase.getBasicSampleTO("batch");
         batchGroupService.create(group);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
index bc9711a..bcf4fbb 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.core;
 
+import static org.junit.Assume.assumeFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -28,6 +29,7 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.syncope.fit.AbstractITCase;
 import org.apache.syncope.fit.FlowableDetector;
@@ -41,17 +43,18 @@ public class BpmnProcessITCase extends AbstractITCase {
 
     @BeforeAll
     public static void findDefault() {
+        assumeFalse(clientFactory.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
         assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
+
         bpmnProcessService.list().stream().
                 filter(BpmnProcess::isUserWorkflow).findAny().
-                ifPresent(process -> {
-                    userWorkflowKey = process.getKey();
-                });
+                ifPresent(process -> userWorkflowKey = process.getKey());
         assertNotNull(userWorkflowKey);
     }
 
     @BeforeEach
     public void check() {
+        assumeFalse(clientFactory.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
         assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
index 2bb5c22..4787f42 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DynRealmITCase.java
@@ -239,7 +239,7 @@ public class DynRealmITCase extends AbstractITCase {
                 send();
         assertEquals(HttpStatus.OK_200, response.getStatus());
 
-        return (ArrayNode) MAPPER.readTree(response.getContent()).
+        return (ArrayNode) OBJECT_MAPPER.readTree(response.getContent()).
                 get("hits").get("hits").get(0).get("_source").get("dynRealms");
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
index 42066e5..d02251b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
@@ -461,7 +461,7 @@ public class LinkedAccountITCase extends AbstractITCase {
         WebClient webClient = WebClient.create(BUILD_TOOLS_ADDRESS + "/rest/users").
                 accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE);
 
-        ObjectNode user = MAPPER.createObjectNode();
+        ObjectNode user = OBJECT_MAPPER.createObjectNode();
         user.put("username", "linkedaccount1");
         user.put("password", "Password123");
         user.put("firstName", "Pasquale");
@@ -473,7 +473,7 @@ public class LinkedAccountITCase extends AbstractITCase {
         String user1Key = StringUtils.substringAfterLast(response.getHeaderString(HttpHeaders.LOCATION), "/");
         assertNotNull(user1Key);
 
-        user = MAPPER.createObjectNode();
+        user = OBJECT_MAPPER.createObjectNode();
         user.put("username", "vivaldi");
         user.put("password", "Password123");
         user.put("firstName", "Giovannino");
@@ -485,7 +485,7 @@ public class LinkedAccountITCase extends AbstractITCase {
         String user2Key = StringUtils.substringAfterLast(response.getHeaderString(HttpHeaders.LOCATION), "/");
         assertNotNull(user2Key);
 
-        user = MAPPER.createObjectNode();
+        user = OBJECT_MAPPER.createObjectNode();
         user.put("username", "not.vivaldi");
         user.put("password", "Password123");
         user.put("email", "not.vivaldi@syncope.org");
@@ -539,12 +539,12 @@ public class LinkedAccountITCase extends AbstractITCase {
             response = webClient.path(user1Key).delete();
             assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
 
-            user = MAPPER.createObjectNode();
+            user = OBJECT_MAPPER.createObjectNode();
             user.put("username", "linkedaccount2");
             response = webClient.replacePath(user2Key).put(user.toString());
             assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
 
-            user = MAPPER.createObjectNode();
+            user = OBJECT_MAPPER.createObjectNode();
             user.put("status", "INACTIVE");
             response = webClient.replacePath(user3Key).put(user.toString());
             assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OpenAPIITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OpenAPIITCase.java
index 75ca075..5c87c08 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OpenAPIITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OpenAPIITCase.java
@@ -40,7 +40,7 @@ public class OpenAPIITCase extends AbstractITCase {
         Response response = webClient.get();
         assumeTrue(response.getStatus() == 200);
 
-        JsonNode tree = MAPPER.readTree((InputStream) response.getEntity());
+        JsonNode tree = OBJECT_MAPPER.readTree((InputStream) response.getEntity());
         assertNotNull(tree);
 
         JsonNode info = tree.get("info");
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
index 021005a..6efce7c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.core;
 
+import static org.junit.Assume.assumeFalse;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -30,6 +31,7 @@ import javax.ws.rs.core.MediaType;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserRequestForm;
@@ -42,12 +44,14 @@ import org.apache.syncope.common.rest.api.service.UserRequestService;
 import org.apache.syncope.fit.AbstractITCase;
 import org.apache.syncope.fit.FlowableDetector;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 public class UserRequestITCase extends AbstractITCase {
 
     @BeforeAll
     public static void loadBpmnProcesses() throws IOException {
+        assumeFalse(clientFactory.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
         assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
 
         WebClient.client(bpmnProcessService).type(MediaType.APPLICATION_XML_TYPE);
@@ -59,10 +63,14 @@ public class UserRequestITCase extends AbstractITCase {
                 IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/verifyAddedVariables.bpmn20.xml")));
     }
 
-    @Test
-    public void twoLevelsApproval() {
+    @BeforeEach
+    public void check() {
+        assumeFalse(clientFactory.getContentType() == SyncopeClientFactoryBean.ContentType.YAML);
         assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
+    }
 
+    @Test
+    public void twoLevelsApproval() {
         UserTO user = createUser(UserITCase.getUniqueSampleTO("twoLevelsApproval@tirasa.net")).getEntity();
         assertNotNull(user);
         assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent());
@@ -141,8 +149,6 @@ public class UserRequestITCase extends AbstractITCase {
 
     @Test
     public void cancel() {
-        assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
-
         PagedResult<UserRequestForm> forms =
                 userRequestService.getForms(new UserRequestFormQuery.Builder().build());
         int preForms = forms.getTotalCount();
@@ -175,8 +181,6 @@ public class UserRequestITCase extends AbstractITCase {
 
     @Test
     public void userSelection() {
-        assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
-
         PagedResult<UserRequestForm> forms =
                 userRequestService.getForms(new UserRequestFormQuery.Builder().build());
         int preForms = forms.getTotalCount();
@@ -247,11 +251,9 @@ public class UserRequestITCase extends AbstractITCase {
         assertTrue(relationships.stream().
                 anyMatch(relationship -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(relationship.getOtherEndKey())));
     }
-    
+
     @Test
     public void addVariablesToUserRequestAtStart() {
-        assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService));
-
         PagedResult<UserRequestForm> forms =
                 userRequestService.getForms(new UserRequestFormQuery.Builder().build());
         int preForms = forms.getTotalCount();
@@ -263,7 +265,7 @@ public class UserRequestITCase extends AbstractITCase {
 
         WorkflowTaskExecInput testInput = new WorkflowTaskExecInput();
         testInput.getVariables().put("providedVariable", "test");
-        
+
         // start request as user
         UserRequest req = client.getService(UserRequestService.class).start("verifyAddedVariables", null, testInput);
         assertNotNull(req);
@@ -280,10 +282,10 @@ public class UserRequestITCase extends AbstractITCase {
         UserRequestForm form = userForms.getResult().get(0);
         form = userRequestService.claimForm(form.getTaskId());
         assertEquals(form.getProperty("providedVariable").get().getValue(), "test");
-        
+
         // cancel request
         userRequestService.cancel(req.getExecutionId(), "nothing in particular");
-       
+
         // no more forms available
         forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build());
         assertEquals(preForms, forms.getTotalCount());