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/02/12 11:29:00 UTC

[syncope] branch master updated (562f5da -> b865da0)

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

ilgrosso pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git.


    from 562f5da  Allow for ActionLinksTogglePanel extension in subclasses
     new 7cd9b5d  [SYNCOPE-1517] Making JdbcAuditAppender configurable (but still enabled by default)
     new b865da0  Upgrading Elasticsearch and asciidoctorj-pdf

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


Summary of changes:
 .../client/console/audit/AuditHistoryDetails.java  |  16 +-
 .../console/audit/AuditHistoryDirectoryPanel.java  |  35 ++--
 .../console/rest/AuditHistoryRestClient.java       |  72 -------
 .../client/console/rest/LoggerRestClient.java      |  45 +++++
 .../apache/syncope/common/lib/log/AuditEntry.java  | 158 +++++++++++++++
 .../apache/syncope/common/lib/to/AuditEntryTO.java | 141 -------------
 .../common/rest/api/service/AuditService.java      |  54 -----
 .../common/rest/api/service/LoggerService.java     |  15 ++
 .../syncope/core/logic/AbstractAuditAppender.java  |  72 -------
 .../org/apache/syncope/core/logic/AuditLogic.java  |  73 -------
 .../org/apache/syncope/core/logic/LoggerLogic.java |  50 +++--
 .../syncope/core/logic/audit/AuditAppender.java    |  20 +-
 .../core/logic/audit/DefaultAuditAppender.java     |  31 ++-
 .../logic/audit/DefaultRewriteAuditAppender.java   |  38 ++--
 .../core/logic/audit/JdbcAuditAppender.java        | 102 ++++++++++
 .../logic/audit/PassThroughAuditRewritePolicy.java |   1 -
 .../init/ClassPathScanImplementationLookup.java    |   7 +-
 .../syncope/core/logic/init/LoggerLoader.java      | 131 ++++--------
 .../logic/src/main/resources/logic.properties      |   1 +
 .../core/rest/cxf/service/AuditServiceImpl.java    |  52 -----
 .../core/rest/cxf/service/LoggerServiceImpl.java   |  40 +++-
 .../syncope/core/persistence/api/dao/AuditDAO.java |  45 -----
 .../core/persistence/api/dao/LoggerDAO.java        |  20 ++
 .../core/persistence/api/entity/AuditEntry.java    |  40 ----
 ...AuditDAO.java => AbstractJPAJSONLoggerDAO.java} |   2 +-
 ...PAJSONAuditDAO.java => MyJPAJSONLoggerDAO.java} |  10 +-
 ...PAJSONAuditDAO.java => PGJPAJSONLoggerDAO.java} |  14 +-
 .../main/resources/myjson/persistence.properties   |   2 +-
 .../main/resources/pgjsonb/persistence.properties  |   2 +-
 .../core/persistence/jpa/PersistenceContext.java   |   8 +-
 .../jpa/content/XMLContentExporter.java            |  14 +-
 .../core/persistence/jpa/dao/JPAAuditDAO.java      | 163 ---------------
 .../core/persistence/jpa/dao/JPALoggerDAO.java     | 141 ++++++++++++-
 .../persistence/jpa/entity/AbstractEntity.java     |   3 +
 .../persistence/jpa/entity/JPAConnInstance.java    |   1 -
 .../src/main/resources/persistence.properties      |   2 +-
 .../core/provisioning/api/AuditEntryImpl.java      | 219 ---------------------
 .../provisioning/api/data/AuditDataBinder.java     |  27 ---
 .../{RoleDataBinder.java => LoggerDataBinder.java} |  13 +-
 .../provisioning/api/serialization/POJOHelper.java |  12 --
 .../core/provisioning/api/AuditEntryImplTest.java  |  93 ---------
 .../api/PropagationByResourceTest.java             |  13 +-
 .../api/cache/VirAttrCacheValueTest.java           |   6 +-
 .../serialization/AttributeDeserializerTest.java   |  14 +-
 .../api/serialization/AttributeSerializerTest.java |  16 +-
 .../api/serialization/POJOHelperTest.java          |   7 -
 .../provisioning/java/DefaultAuditManager.java     |  85 +++++---
 .../java/data/AuditDataBinderImpl.java             |  66 -------
 .../java/data/LoggerDataBinderImpl.java}           |  27 ++-
 .../java/job/report/AuditReportlet.java            |  18 +-
 .../src/main/resources/persistence.properties.all  |   2 +-
 .../main/resources/persistence.properties.myjson   |   2 +-
 .../main/resources/persistence.properties.pgjsonb  |   2 +-
 .../src/main/resources/persistence.properties      |   2 +-
 .../core/reference/SyslogRewriteAuditAppender.java |  47 ++---
 .../fit/core/reference/TestFileAuditAppender.java  |  30 ++-
 .../reference/TestFileRewriteAuditAppender.java    |  23 +--
 .../fit/core/reference/TestRewritePolicy.java      |   7 +-
 .../resources/elasticsearch/persistence.properties |   2 +-
 .../src/main/resources/logic.properties            |   1 +
 .../org/apache/syncope/fit/AbstractITCase.java     |   4 -
 .../org/apache/syncope/fit/core/AuditITCase.java   |  36 ++--
 .../org/apache/syncope/fit/core/LoggerITCase.java  |   1 -
 pom.xml                                            |   6 +-
 .../systemadministration/dbms.adoc                 |   4 +-
 65 files changed, 872 insertions(+), 1534 deletions(-)
 delete mode 100644 client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditHistoryRestClient.java
 create mode 100644 common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java
 delete mode 100644 common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditEntryTO.java
 delete mode 100644 common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
 delete mode 100644 core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
 delete mode 100644 core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
 create mode 100644 core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
 delete mode 100644 core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java
 delete mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditDAO.java
 delete mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditEntry.java
 rename core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/{AbstractJPAJSONAuditDAO.java => AbstractJPAJSONLoggerDAO.java} (98%)
 rename core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/{MyJPAJSONAuditDAO.java => MyJPAJSONLoggerDAO.java} (79%)
 rename core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/{PGJPAJSONAuditDAO.java => PGJPAJSONLoggerDAO.java} (78%)
 delete mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditDAO.java
 delete mode 100644 core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditEntryImpl.java
 delete mode 100644 core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
 copy core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/{RoleDataBinder.java => LoggerDataBinder.java} (73%)
 delete mode 100644 core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AuditEntryImplTest.java
 delete mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
 copy core/{idm/logic/src/main/java/org/apache/syncope/core/logic/init/IdMImplementationTypeLoader.java => provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java} (51%)


[syncope] 01/02: [SYNCOPE-1517] Making JdbcAuditAppender configurable (but still enabled by default)

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7cd9b5d683b14fec0dbd8095b194e71053f19ee0
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Wed Feb 12 10:44:21 2020 +0100

    [SYNCOPE-1517] Making JdbcAuditAppender configurable (but still enabled by default)
---
 .../client/console/audit/AuditHistoryDetails.java  |  16 +-
 .../console/audit/AuditHistoryDirectoryPanel.java  |  35 ++--
 .../console/rest/AuditHistoryRestClient.java       |  72 -------
 .../client/console/rest/LoggerRestClient.java      |  45 +++++
 .../apache/syncope/common/lib/log/AuditEntry.java  | 158 +++++++++++++++
 .../apache/syncope/common/lib/to/AuditEntryTO.java | 141 -------------
 .../common/rest/api/service/AuditService.java      |  54 -----
 .../common/rest/api/service/LoggerService.java     |  15 ++
 .../syncope/core/logic/AbstractAuditAppender.java  |  72 -------
 .../org/apache/syncope/core/logic/AuditLogic.java  |  73 -------
 .../org/apache/syncope/core/logic/LoggerLogic.java |  50 +++--
 .../syncope/core/logic/audit/AuditAppender.java    |  20 +-
 .../core/logic/audit/DefaultAuditAppender.java     |  31 ++-
 .../logic/audit/DefaultRewriteAuditAppender.java   |  38 ++--
 .../core/logic/audit/JdbcAuditAppender.java        | 102 ++++++++++
 .../logic/audit/PassThroughAuditRewritePolicy.java |   1 -
 .../init/ClassPathScanImplementationLookup.java    |   7 +-
 .../syncope/core/logic/init/LoggerLoader.java      | 131 ++++--------
 .../logic/src/main/resources/logic.properties      |   1 +
 .../core/rest/cxf/service/AuditServiceImpl.java    |  52 -----
 .../core/rest/cxf/service/LoggerServiceImpl.java   |  40 +++-
 .../syncope/core/persistence/api/dao/AuditDAO.java |  45 -----
 .../core/persistence/api/dao/LoggerDAO.java        |  20 ++
 .../core/persistence/api/entity/AuditEntry.java    |  40 ----
 ...AuditDAO.java => AbstractJPAJSONLoggerDAO.java} |   2 +-
 ...PAJSONAuditDAO.java => MyJPAJSONLoggerDAO.java} |  10 +-
 ...PAJSONAuditDAO.java => PGJPAJSONLoggerDAO.java} |  14 +-
 .../main/resources/myjson/persistence.properties   |   2 +-
 .../main/resources/pgjsonb/persistence.properties  |   2 +-
 .../core/persistence/jpa/PersistenceContext.java   |   8 +-
 .../jpa/content/XMLContentExporter.java            |  14 +-
 .../core/persistence/jpa/dao/JPAAuditDAO.java      | 163 ---------------
 .../core/persistence/jpa/dao/JPALoggerDAO.java     | 141 ++++++++++++-
 .../persistence/jpa/entity/AbstractEntity.java     |   3 +
 .../persistence/jpa/entity/JPAConnInstance.java    |   1 -
 .../src/main/resources/persistence.properties      |   2 +-
 .../core/provisioning/api/AuditEntryImpl.java      | 219 ---------------------
 ...{AuditDataBinder.java => LoggerDataBinder.java} |  11 +-
 .../provisioning/api/serialization/POJOHelper.java |  12 --
 .../core/provisioning/api/AuditEntryImplTest.java  |  93 ---------
 .../api/PropagationByResourceTest.java             |  13 +-
 .../api/cache/VirAttrCacheValueTest.java           |   6 +-
 .../serialization/AttributeDeserializerTest.java   |  14 +-
 .../api/serialization/AttributeSerializerTest.java |  16 +-
 .../api/serialization/POJOHelperTest.java          |   7 -
 .../provisioning/java/DefaultAuditManager.java     |  85 +++++---
 .../java/data/AuditDataBinderImpl.java             |  66 -------
 .../java/data/LoggerDataBinderImpl.java}           |  43 ++--
 .../java/job/report/AuditReportlet.java            |  18 +-
 .../src/main/resources/persistence.properties.all  |   2 +-
 .../main/resources/persistence.properties.myjson   |   2 +-
 .../main/resources/persistence.properties.pgjsonb  |   2 +-
 .../src/main/resources/persistence.properties      |   2 +-
 .../core/reference/SyslogRewriteAuditAppender.java |  47 ++---
 .../fit/core/reference/TestFileAuditAppender.java  |  30 ++-
 .../reference/TestFileRewriteAuditAppender.java    |  23 +--
 .../fit/core/reference/TestRewritePolicy.java      |   7 +-
 .../resources/elasticsearch/persistence.properties |   2 +-
 .../src/main/resources/logic.properties            |   1 +
 .../org/apache/syncope/fit/AbstractITCase.java     |   4 -
 .../org/apache/syncope/fit/core/AuditITCase.java   |  36 ++--
 .../org/apache/syncope/fit/core/LoggerITCase.java  |   1 -
 .../systemadministration/dbms.adoc                 |   4 +-
 63 files changed, 871 insertions(+), 1516 deletions(-)

diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
index 8d491df..4b58d90 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
@@ -20,12 +20,13 @@ package org.apache.syncope.client.console.audit;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.Serializable;
 import java.util.Date;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonDiffPanel;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.to.AbstractAnnotatedBean;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.PageReference;
@@ -38,7 +39,7 @@ import org.apache.wicket.model.Model;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class AuditHistoryDetails<T extends EntityTO> extends MultilevelPanel.SecondLevel {
+public abstract class AuditHistoryDetails<T extends Serializable> extends MultilevelPanel.SecondLevel {
 
     private static final long serialVersionUID = -7400543686272100483L;
 
@@ -46,19 +47,16 @@ public abstract class AuditHistoryDetails<T extends EntityTO> extends Multilevel
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
-    private static final String KEY_CURRENT = "current";
-
     public AuditHistoryDetails(
             final MultilevelPanel mlp,
-            final AuditEntryTO selected,
-            final T currentEntity,
+            final AuditEntry selected,
+            final EntityTO currentEntity,
             final String auditRestoreEntitlement,
             final PageReference pageRef) {
 
         super();
 
-        AuditEntryTO current = new AuditEntryTO();
-        current.setKey(KEY_CURRENT);
+        AuditEntry current = new AuditEntry();
         if (currentEntity instanceof AbstractAnnotatedBean) {
             current.setWho(((AbstractAnnotatedBean) currentEntity).getCreator());
             current.setDate(((AbstractAnnotatedBean) currentEntity).getCreationDate());
@@ -112,7 +110,7 @@ public abstract class AuditHistoryDetails<T extends EntityTO> extends Multilevel
 
     protected abstract void restore(String json, AjaxRequestTarget target);
 
-    private Model<String> toJSON(final AuditEntryTO auditEntry, final Class<T> reference) {
+    private Model<String> toJSON(final AuditEntry auditEntry, final Class<T> reference) {
         try {
             String content = auditEntry.getBefore() == null
                     ? MAPPER.readTree(auditEntry.getOutput()).get("entity").toPrettyString()
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
index 790f0b5..7b43498 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.audit;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -26,14 +27,14 @@ import org.apache.syncope.client.console.commons.IdRepoConstants;
 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.rest.AuditHistoryRestClient;
+import org.apache.syncope.client.console.rest.LoggerRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.ui.commons.DirectoryDataProvider;
 import org.apache.syncope.client.ui.commons.panels.ModalPanel;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
@@ -47,8 +48,8 @@ import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.StringResourceModel;
 
-public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends DirectoryPanel<
-        AuditEntryTO, AuditEntryTO, AuditHistoryDirectoryPanel<T>.AuditHistoryProvider, AuditHistoryRestClient>
+public abstract class AuditHistoryDirectoryPanel<T extends Serializable> extends DirectoryPanel<
+        AuditEntry, AuditEntry, AuditHistoryDirectoryPanel<T>.AuditHistoryProvider, LoggerRestClient>
         implements ModalPanel {
 
     private static final long serialVersionUID = -8248734710505211261L;
@@ -65,7 +66,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
 
     private final String category;
 
-    private final T entity;
+    private final EntityTO entity;
 
     private final String auditRestoreEntitlement;
 
@@ -74,7 +75,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
             final MultilevelPanel mlp,
             final AuditElements.EventCategoryType type,
             final String category,
-            final T entity,
+            final EntityTO entity,
             final String auditRestoreEntitlement,
             final PageReference pageRef) {
 
@@ -89,7 +90,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
         this.auditRestoreEntitlement = auditRestoreEntitlement;
         this.pageRef = pageRef;
 
-        this.restClient = new AuditHistoryRestClient();
+        this.restClient = new LoggerRestClient();
         initResultTable();
     }
 
@@ -104,30 +105,30 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
     }
 
     @Override
-    protected List<IColumn<AuditEntryTO, String>> getColumns() {
-        List<IColumn<AuditEntryTO, String>> columns = new ArrayList<>();
+    protected List<IColumn<AuditEntry, String>> getColumns() {
+        List<IColumn<AuditEntry, String>> columns = new ArrayList<>();
         columns.add(new PropertyColumn<>(new StringResourceModel("who", this), "who"));
         columns.add(new DatePropertyColumn<>(new StringResourceModel("date", this), null, "date"));
         return columns;
     }
 
     @Override
-    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<AuditEntryTO, String> resultTableBuilder) {
+    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<AuditEntry, String> resultTableBuilder) {
         resultTableBuilder.setMultiLevelPanel(baseModal, mlp);
     }
 
     protected abstract void restore(String json, AjaxRequestTarget target);
 
     @Override
-    protected ActionsPanel<AuditEntryTO> getActions(final IModel<AuditEntryTO> model) {
-        final ActionsPanel<AuditEntryTO> panel = super.getActions(model);
+    protected ActionsPanel<AuditEntry> getActions(final IModel<AuditEntry> model) {
+        final ActionsPanel<AuditEntry> panel = super.getActions(model);
 
-        panel.add(new ActionLink<AuditEntryTO>() {
+        panel.add(new ActionLink<AuditEntry>() {
 
             private static final long serialVersionUID = -6745431735457245600L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final AuditEntryTO modelObject) {
+            public void onClick(final AjaxRequestTarget target, final AuditEntry modelObject) {
                 AuditHistoryDirectoryPanel.this.getTogglePanel().close(target);
 
                 mlp.next(
@@ -159,7 +160,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
         return List.of();
     }
 
-    protected class AuditHistoryProvider extends DirectoryDataProvider<AuditEntryTO> {
+    protected class AuditHistoryProvider extends DirectoryDataProvider<AuditEntry> {
 
         private static final long serialVersionUID = 415113175628260864L;
 
@@ -174,7 +175,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
         }
 
         @Override
-        public Iterator<AuditEntryTO> iterator(final long first, final long count) {
+        public Iterator<AuditEntry> iterator(final long first, final long count) {
             int page = ((int) first / paginatorRows);
             return restClient.search(
                     entity.getKey(),
@@ -189,7 +190,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends EntityTO> extends Dir
         }
 
         @Override
-        public IModel<AuditEntryTO> model(final AuditEntryTO auditEntryBean) {
+        public IModel<AuditEntry> model(final AuditEntry auditEntryBean) {
             return new CompoundPropertyModel<>(auditEntryBean);
         }
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditHistoryRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditHistoryRestClient.java
deleted file mode 100644
index 8666aa1..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditHistoryRestClient.java
+++ /dev/null
@@ -1,72 +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.syncope.client.console.rest;
-
-import java.util.List;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.rest.api.beans.AuditQuery;
-import org.apache.syncope.common.rest.api.service.AuditService;
-import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
-
-public class AuditHistoryRestClient extends BaseRestClient {
-
-    private static final long serialVersionUID = -381814125643246243L;
-
-    public List<AuditEntryTO> search(
-            final String key,
-            final int page,
-            final int size,
-            final AuditElements.EventCategoryType type,
-            final String category,
-            final List<String> events,
-            final AuditElements.Result result,
-            final SortParam<String> sort) {
-
-        AuditQuery query = new AuditQuery.Builder(key).
-                size(size).
-                page(page).
-                type(type).
-                category(category).
-                events(events).
-                result(result).
-                orderBy(toOrderBy(sort)).
-                build();
-
-        return getService(AuditService.class).search(query).getResult();
-    }
-
-    public int count(
-            final String key,
-            final AuditElements.EventCategoryType type,
-            final String category,
-            final List<String> events,
-            final AuditElements.Result result) {
-
-        AuditQuery query = new AuditQuery.Builder(key).
-                page(1).
-                size(1).
-                type(type).
-                category(category).
-                events(events).
-                result(result).
-                build();
-        return getService(AuditService.class).search(query).getTotalCount();
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java
index c283c02..462b608 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java
@@ -26,15 +26,19 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.log.EventCategory;
 import org.apache.syncope.common.lib.log.LogAppender;
 import org.apache.syncope.common.lib.log.LogStatement;
 import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.rest.api.LoggerWrapper;
+import org.apache.syncope.common.rest.api.beans.AuditQuery;
 import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 
 public class LoggerRestClient extends BaseRestClient {
 
@@ -104,4 +108,45 @@ public class LoggerRestClient extends BaseRestClient {
             return List.of();
         }
     }
+
+    public List<AuditEntry> search(
+            final String key,
+            final int page,
+            final int size,
+            final AuditElements.EventCategoryType type,
+            final String category,
+            final List<String> events,
+            final AuditElements.Result result,
+            final SortParam<String> sort) {
+
+        AuditQuery query = new AuditQuery.Builder(key).
+                size(size).
+                page(page).
+                type(type).
+                category(category).
+                events(events).
+                result(result).
+                orderBy(toOrderBy(sort)).
+                build();
+
+        return getService(LoggerService.class).search(query).getResult();
+    }
+
+    public int count(
+            final String key,
+            final AuditElements.EventCategoryType type,
+            final String category,
+            final List<String> events,
+            final AuditElements.Result result) {
+
+        AuditQuery query = new AuditQuery.Builder(key).
+                page(1).
+                size(1).
+                type(type).
+                category(category).
+                events(events).
+                result(result).
+                build();
+        return getService(LoggerService.class).search(query).getTotalCount();
+    }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java
new file mode 100644
index 0000000..47f5acf
--- /dev/null
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java
@@ -0,0 +1,158 @@
+/*
+ * 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.common.lib.log;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+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;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+
+@XmlRootElement(name = "auditEntry")
+@XmlType
+public class AuditEntry extends BaseBean {
+
+    private static final long serialVersionUID = 1215115961911228005L;
+
+    private String who;
+
+    private Date date;
+
+    private AuditLoggerName logger;
+
+    private String before;
+
+    private final List<String> inputs = new ArrayList<>();
+
+    private String output;
+
+    private String throwable;
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public String getWho() {
+        return who;
+    }
+
+    public void setWho(final String who) {
+        this.who = who;
+    }
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public Date getDate() {
+        return date == null
+                ? null
+                : new Date(date.getTime());
+    }
+
+    public void setDate(final Date date) {
+        this.date = date == null
+                ? null
+                : new Date(date.getTime());
+    }
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public AuditLoggerName getLogger() {
+        return logger;
+    }
+
+    public void setLogger(final AuditLoggerName logger) {
+        this.logger = logger;
+    }
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public String getBefore() {
+        return before;
+    }
+
+    @XmlElementWrapper(name = "inputs")
+    @XmlElement(name = "input")
+    @JsonProperty("inputs")
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public List<String> getInputs() {
+        return inputs;
+    }
+
+    public void setBefore(final String before) {
+        this.before = before;
+    }
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public String getOutput() {
+        return output;
+    }
+
+    public void setOutput(final String output) {
+        this.output = output;
+    }
+
+    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+    public String getThrowable() {
+        return throwable;
+    }
+
+    public void setThrowable(final String throwable) {
+        this.throwable = throwable;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().
+                appendSuper(super.hashCode()).
+                append(who).
+                append(date).
+                append(logger).
+                append(before).
+                append(inputs).
+                append(output).
+                append(throwable).
+                build();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final AuditEntry other = (AuditEntry) obj;
+        return new EqualsBuilder().
+                appendSuper(super.equals(obj)).
+                append(who, other.who).
+                append(date, other.date).
+                append(logger, other.logger).
+                append(before, other.before).
+                append(inputs, other.inputs).
+                append(output, other.output).
+                append(throwable, other.throwable).
+                build();
+    }
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditEntryTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditEntryTO.java
deleted file mode 100644
index 9d183e6..0000000
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditEntryTO.java
+++ /dev/null
@@ -1,141 +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.syncope.common.lib.to;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.BaseBean;
-
-@XmlRootElement(name = "audit")
-@XmlType
-public class AuditEntryTO extends BaseBean implements EntityTO {
-
-    private static final long serialVersionUID = 1215115961911228005L;
-
-    private String who;
-
-    private String subCategory;
-
-    private String event;
-
-    private String result;
-
-    private String before;
-
-    private final List<String> inputs = new ArrayList<>();
-
-    private String output;
-
-    private Date date;
-
-    private String throwable;
-
-    private String key;
-
-    private String loggerName;
-
-    public Date getDate() {
-        return date;
-    }
-
-    public void setDate(final Date date) {
-        this.date = date;
-    }
-
-    public String getThrowable() {
-        return throwable;
-    }
-
-    public void setThrowable(final String throwable) {
-        this.throwable = throwable;
-    }
-
-    public String getOutput() {
-        return output;
-    }
-
-    public void setOutput(final String output) {
-        this.output = output;
-    }
-
-    public String getBefore() {
-        return before;
-    }
-
-    public void setBefore(final String before) {
-        this.before = before;
-    }
-
-    public List<String> getInputs() {
-        return inputs;
-    }
-
-    public String getSubCategory() {
-        return subCategory;
-    }
-
-    public void setSubCategory(final String subCategory) {
-        this.subCategory = subCategory;
-    }
-
-    public String getEvent() {
-        return event;
-    }
-
-    public void setEvent(final String event) {
-        this.event = event;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(final String result) {
-        this.result = result;
-    }
-
-    public String getWho() {
-        return who;
-    }
-
-    public void setWho(final String who) {
-        this.who = who;
-    }
-
-    public String getLoggerName() {
-        return loggerName;
-    }
-
-    public void setLoggerName(final String loggerName) {
-        this.loggerName = loggerName;
-    }
-
-    @Override
-    public String getKey() {
-        return this.key;
-    }
-
-    @Override
-    public void setKey(final String key) {
-        this.key = key;
-    }
-}
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
deleted file mode 100644
index 5035494..0000000
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
+++ /dev/null
@@ -1,54 +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.syncope.common.rest.api.service;
-
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.security.SecurityRequirements;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.rest.api.RESTHeaders;
-import org.apache.syncope.common.rest.api.beans.AuditQuery;
-
-import javax.ws.rs.BeanParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-/**
- * REST operations for audit events.
- */
-@Tag(name = "Audits")
-@SecurityRequirements({
-    @SecurityRequirement(name = "BasicAuthentication"),
-    @SecurityRequirement(name = "Bearer") })
-@Path("audits")
-public interface AuditService {
-
-    /**
-     * Returns a paged list of audit objects matching the given query.
-     *
-     * @param auditQuery query conditions
-     * @return paged list of objects matching the given query
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    PagedResult<AuditEntryTO> search(@BeanParam AuditQuery auditQuery);
-}
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java
index 293aeba..1b494a3 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java
@@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirements;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import java.util.List;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -36,12 +37,15 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.log.EventCategory;
 import org.apache.syncope.common.lib.log.LogAppender;
 import org.apache.syncope.common.lib.log.LogStatement;
 import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.beans.AuditQuery;
 
 /**
  * REST operations for logging and auditing.
@@ -85,6 +89,17 @@ public interface LoggerService extends JAXRSService {
     List<EventCategory> events();
 
     /**
+     * Returns a paged list of audit entries matching the given query.
+     *
+     * @param auditQuery query conditions
+     * @return paged list of audit entries matching the given query
+     */
+    @GET
+    @Path("AUDIT/entries")
+    @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
+    PagedResult<AuditEntry> search(@BeanParam AuditQuery auditQuery);
+
+    /**
      * Returns logger with matching type and name.
      *
      * @param type LoggerType to be selected.
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
deleted file mode 100644
index 0065543..0000000
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
+++ /dev/null
@@ -1,72 +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.syncope.core.logic;
-
-import org.apache.syncope.core.logic.audit.AuditAppender;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-
-public abstract class AbstractAuditAppender implements AuditAppender {
-
-    protected String domainName;
-
-    protected Appender targetAppender;
-
-    protected RewriteAppender rewriteAppender;
-
-    @Override
-    public abstract void init();
-
-    public abstract void initTargetAppender();
-
-    public abstract void initRewriteAppender();
-
-    @Override
-    public abstract RewritePolicy getRewritePolicy();
-
-    @Override
-    public String getDomainName() {
-        return domainName;
-    }
-
-    @Override
-    public void setDomainName(final String domainName) {
-        this.domainName = domainName;
-    }
-
-    @Override
-    public abstract String getTargetAppenderName();
-
-    @Override
-    public boolean isRewriteEnabled() {
-        return rewriteAppender != null;
-    }
-
-    @Override
-    public RewriteAppender getRewriteAppender() {
-        return rewriteAppender;
-    }
-
-    @Override
-    public Appender getTargetAppender() {
-        return targetAppender;
-    }
-
-}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
deleted file mode 100644
index f57eda9..0000000
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
+++ /dev/null
@@ -1,73 +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.syncope.core.logic;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.common.lib.types.IdRepoEntitlement;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.core.persistence.api.dao.AuditDAO;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-import org.apache.syncope.core.provisioning.api.data.AuditDataBinder;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-@Component
-public class AuditLogic extends AbstractTransactionalLogic<AuditEntryTO> {
-
-    @Autowired
-    private AuditDataBinder binder;
-
-    @Autowired
-    private AuditDAO auditDAO;
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_SEARCH + "')")
-    @Transactional(readOnly = true)
-    public Pair<Integer, List<AuditEntryTO>> search(
-            final String entityKey,
-            final int page,
-            final int size,
-            final AuditElements.EventCategoryType type,
-            final String category,
-            final String subcategory,
-            final List<String> events,
-            final AuditElements.Result result,
-            final List<OrderByClause> orderByClauses) {
-
-        Integer count = auditDAO.count(entityKey);
-        List<AuditEntry> matching = auditDAO.findByEntityKey(
-                entityKey, page, size, type, category, subcategory, events, result, orderByClauses);
-        List<AuditEntryTO> searchResults = matching.stream().
-                map(auditEntry -> binder.getAuditTO(entityKey, auditEntry)).
-                collect(Collectors.toList());
-        return Pair.of(count, searchResults);
-    }
-
-    @Override
-    protected AuditEntryTO resolveReference(final Method method, final Object... args)
-            throws UnresolvedReferenceException {
-        throw new UnresolvedReferenceException();
-    }
-}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
index 22c5d37..3b1fe49 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
@@ -26,10 +26,12 @@ import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.log.EventCategory;
@@ -54,6 +56,7 @@ import org.apache.syncope.core.persistence.api.DomainHolder;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
@@ -72,6 +75,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.SystemPropertyUtils;
+import org.apache.syncope.core.provisioning.api.data.LoggerDataBinder;
 
 @Component
 public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
@@ -91,6 +95,9 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
     @Autowired
     private EntityFactory entityFactory;
 
+    @Autowired
+    private LoggerDataBinder binder;
+
     @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_LIST + "') and authentication.details.domain == "
             + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
     @Transactional(readOnly = true)
@@ -115,12 +122,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
     }
 
     private List<LoggerTO> list(final LoggerType type) {
-        return loggerDAO.findAll(type).stream().map(logger -> {
-            LoggerTO loggerTO = new LoggerTO();
-            loggerTO.setKey(logger.getKey());
-            loggerTO.setLevel(logger.getLevel());
-            return loggerTO;
-        }).collect(Collectors.toList());
+        return loggerDAO.findAll(type).stream().map(binder::getLoggerTO).collect(Collectors.toList());
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_LIST + "') and authentication.details.domain == "
@@ -173,12 +175,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
     public LoggerTO readAudit(final String name) {
         return listAudits().stream().
                 filter(logger -> logger.toLoggerName().equals(name)).findFirst().
-                map(logger -> {
-                    LoggerTO loggerTO = new LoggerTO();
-                    loggerTO.setKey(logger.toLoggerName());
-                    loggerTO.setLevel(LoggerLevel.DEBUG);
-                    return loggerTO;
-                }).orElseThrow(() -> new NotFoundException("Audit " + name));
+                map(binder::getLoggerTO).orElseThrow(() -> new NotFoundException("Audit " + name));
     }
 
     private LoggerTO setLevel(final String name, final Level level, final LoggerType expectedType) {
@@ -231,11 +228,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
         logConf.setLevel(level);
         ctx.updateLoggers();
 
-        LoggerTO result = new LoggerTO();
-        result.setKey(syncopeLogger.getKey());
-        result.setLevel(syncopeLogger.getLevel());
-
-        return result;
+        return binder.getLoggerTO(syncopeLogger);
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_SET_LEVEL + "') and authentication.details.domain == "
@@ -264,9 +257,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
             throwInvalidLogger(expectedType);
         }
 
-        LoggerTO loggerToDelete = new LoggerTO();
-        loggerToDelete.setKey(syncopeLogger.getKey());
-        loggerToDelete.setLevel(syncopeLogger.getLevel());
+        LoggerTO loggerToDelete = binder.getLoggerTO(syncopeLogger);
 
         // remove SyncopeLogger from local storage, so that LoggerLoader won't load this next time
         loggerDAO.delete(syncopeLogger);
@@ -405,6 +396,25 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
         return new ArrayList<>(events);
     }
 
+    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_SEARCH + "')")
+    @Transactional(readOnly = true)
+    public Pair<Integer, List<AuditEntry>> search(
+            final String entityKey,
+            final int page,
+            final int size,
+            final AuditElements.EventCategoryType type,
+            final String category,
+            final String subcategory,
+            final List<String> events,
+            final AuditElements.Result result,
+            final List<OrderByClause> orderByClauses) {
+
+        int count = loggerDAO.countAuditEntries(entityKey);
+        List<AuditEntry> matching = loggerDAO.findAuditEntries(
+                entityKey, page, size, type, category, subcategory, events, result, orderByClauses);
+        return Pair.of(count, matching);
+    }
+
     @Override
     protected EntityTO resolveReference(final Method method, final Object... args)
             throws UnresolvedReferenceException {
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
index f6a0716..d81daa6 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
@@ -18,10 +18,10 @@
  */
 package org.apache.syncope.core.logic.audit;
 
+import java.util.Optional;
 import java.util.Set;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 
 /**
@@ -32,21 +32,17 @@ import org.apache.syncope.common.lib.types.AuditLoggerName;
  */
 public interface AuditAppender {
 
-    void init();
+    void init(String domain);
 
-    Set<AuditLoggerName> getEvents();
+    default Set<AuditLoggerName> getEvents() {
+        return Set.of();
+    }
 
     Appender getTargetAppender();
 
-    RewritePolicy getRewritePolicy();
-
     String getTargetAppenderName();
 
-    void setDomainName(String name);
-
-    String getDomainName();
-
-    boolean isRewriteEnabled();
-
-    RewriteAppender getRewriteAppender();
+    default Optional<RewriteAppender> getRewriteAppender() {
+        return Optional.empty();
+    }
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
index 45b28a3..a78f82f 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
@@ -18,36 +18,31 @@
  */
 package org.apache.syncope.core.logic.audit;
 
-import java.util.Set;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.logic.AbstractAuditAppender;
+import org.apache.logging.log4j.core.Appender;
 
 /**
  * Default (abstract) implementation of custom audit appender.
+ *
  * It is bound to an empty collection of events, i.e. it does not create any logger.
- * This class shall be extended by non-rewriting appenders; for rewriting, extend
+ * This class shall be extended by non-rewrite appenders; for rewrite, extend
  * {@link DefaultRewriteAuditAppender} instead.
  */
-public abstract class DefaultAuditAppender extends AbstractAuditAppender {
+public abstract class DefaultAuditAppender implements AuditAppender {
 
-    @Override
-    public void init() {
-        initTargetAppender();
-    }
+    protected String domain;
 
-    @Override
-    public Set<AuditLoggerName> getEvents() {
-        return Set.of();
-    }
+    protected Appender targetAppender;
 
     @Override
-    public void initRewriteAppender() {
+    public void init(final String domain) {
+        this.domain = domain;
+        initTargetAppender();
     }
 
+    protected abstract void initTargetAppender();
+
     @Override
-    public RewritePolicy getRewritePolicy() {
-        return null;
+    public Appender getTargetAppender() {
+        return targetAppender;
     }
-
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
index aa4220e..ed62206 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
@@ -18,46 +18,44 @@
  */
 package org.apache.syncope.core.logic.audit;
 
-import java.util.Set;
+import java.util.Optional;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
 import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
 import org.apache.logging.log4j.core.config.AppenderRef;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.logic.AbstractAuditAppender;
 
 /**
- * Default (abstract) implementation of custom rewriting audit appender; it provides rewrite appender definition and
- * a default "pass-through" policy.
+ * Default (abstract) implementation of rewrite audit appender, allowing the logging event to be manipulated
+ * before it is processed.
+ * It provides rewrite appender definition and a default "pass-through" policy.
  * It is bound to an empty collection of events, i.e. it does not create any logger.
- * This class shall be extended by rewriting appenders; for non-rewriting, extend {@link DefaultAuditAppender} instead.
+ * This class shall be extended by rewrite appenders; for non-rewrite, extend {@link DefaultAuditAppender} instead.
+ *
+ * @see RewriteAppender
  */
-public abstract class DefaultRewriteAuditAppender extends AbstractAuditAppender {
+public abstract class DefaultRewriteAuditAppender extends DefaultAuditAppender {
 
-    @Override
-    public void init() {
-        initTargetAppender();
-        initRewriteAppender();
-    }
+    protected RewriteAppender rewriteAppender;
 
     @Override
-    public void initRewriteAppender() {
-        rewriteAppender = RewriteAppender.createAppender(getTargetAppenderName() + "_rewrite",
+    public void init(final String domain) {
+        super.init(domain);
+
+        rewriteAppender = RewriteAppender.createAppender(
+                getTargetAppenderName() + "_rewrite",
                 "true",
                 new AppenderRef[] { AppenderRef.createAppenderRef(getTargetAppenderName(), Level.DEBUG, null) },
                 ((LoggerContext) LogManager.getContext(false)).getConfiguration(), getRewritePolicy(), null);
     }
 
-    @Override
-    public Set<AuditLoggerName> getEvents() {
-        return Set.of();
+    protected RewritePolicy getRewritePolicy() {
+        return PassThroughAuditRewritePolicy.createPolicy();
     }
 
     @Override
-    public RewritePolicy getRewritePolicy() {
-        return PassThroughAuditRewritePolicy.createPolicy();
+    public Optional<RewriteAppender> getRewriteAppender() {
+        return Optional.of(rewriteAppender);
     }
-
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
new file mode 100644
index 0000000..e96132f
--- /dev/null
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
@@ -0,0 +1,102 @@
+/*
+ * 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.logic.audit;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import javax.sql.DataSource;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.db.ColumnMapping;
+import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource;
+import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
+import org.apache.syncope.core.persistence.api.DomainHolder;
+import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+
+public class JdbcAuditAppender extends DefaultAuditAppender {
+
+    @Autowired
+    protected DomainHolder domainHolder;
+
+    @Override
+    protected void initTargetAppender() {
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+
+        ColumnMapping[] columnMappings = {
+            ColumnMapping.newBuilder().
+            setConfiguration(ctx.getConfiguration()).setName("EVENT_DATE").setType(Timestamp.class).build(),
+            ColumnMapping.newBuilder().
+            setConfiguration(ctx.getConfiguration()).setName("LOGGER_LEVEL").setPattern("%level").build(),
+            ColumnMapping.newBuilder().
+            setConfiguration(ctx.getConfiguration()).setName("LOGGER").setPattern("%logger").build(),
+            ColumnMapping.newBuilder().
+            setConfiguration(ctx.getConfiguration()).
+            setName(LoggerDAO.AUDIT_MESSAGE_COLUMN).setPattern("%message").build(),
+            ColumnMapping.newBuilder().
+            setConfiguration(ctx.getConfiguration()).setName("THROWABLE").setPattern("%ex{full}").build()
+        };
+
+        Appender appender = ctx.getConfiguration().getAppender("audit_for_" + domain);
+        if (appender == null) {
+            appender = JdbcAppender.newBuilder().
+                    setName("audit_for_" + domain).
+                    setIgnoreExceptions(false).
+                    setConnectionSource(new DataSourceConnectionSource(domain, domainHolder.getDomains().get(domain))).
+                    setBufferSize(0).
+                    setTableName(LoggerDAO.AUDIT_TABLE).
+                    setColumnMappings(columnMappings).
+                    build();
+            appender.start();
+            ctx.getConfiguration().addAppender(appender);
+        }
+        targetAppender = appender;
+    }
+
+    @Override
+    public String getTargetAppenderName() {
+        // not used
+        return null;
+    }
+
+    protected static class DataSourceConnectionSource extends AbstractConnectionSource {
+
+        private final String description;
+
+        private final DataSource dataSource;
+
+        DataSourceConnectionSource(final String domain, final DataSource dataSource) {
+            this.description = "dataSource{ domain=" + domain + ", value=" + dataSource + " }";
+            this.dataSource = dataSource;
+        }
+
+        @Override
+        public Connection getConnection() throws SQLException {
+            return DataSourceUtils.getConnection(dataSource);
+        }
+
+        @Override
+        public String toString() {
+            return this.description;
+        }
+    }
+}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
index b3ee968..609c486 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
@@ -39,5 +39,4 @@ public class PassThroughAuditRewritePolicy implements RewritePolicy {
     public static PassThroughAuditRewritePolicy createPolicy() {
         return new PassThroughAuditRewritePolicy();
     }
-
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index a9ecdb0..446a7db 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -34,6 +34,7 @@ import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 import org.apache.syncope.core.logic.audit.AuditAppender;
+import org.apache.syncope.core.logic.audit.JdbcAuditAppender;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
@@ -131,7 +132,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
         scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
             try {
                 Class<?> clazz = ClassUtils.resolveClassName(
-                    Objects.requireNonNull(bd.getBeanClassName()), ClassUtils.getDefaultClassLoader());
+                        Objects.requireNonNull(bd.getBeanClassName()), ClassUtils.getDefaultClassLoader());
                 boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
 
                 if (JWTSSOProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
@@ -231,7 +232,9 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     classNames.get(IdRepoImplementationType.RECIPIENTS_PROVIDER).add(bd.getBeanClassName());
                 }
 
-                if (AuditAppender.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+                if (AuditAppender.class.isAssignableFrom(clazz)
+                        && !JdbcAuditAppender.class.equals(clazz) && !isAbstractClazz) {
+
                     classNames.get(IdRepoImplementationType.AUDIT_APPENDER).add(clazz.getName());
                     auditAppenderClasses.add(clazz);
                 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
index 282d726..45ea48c 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
@@ -18,35 +18,30 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Timestamp;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import javax.sql.DataSource;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.appender.db.ColumnMapping;
-import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource;
-import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
 import org.apache.logging.log4j.core.config.LoggerConfig;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.logic.MemoryAppender;
+import org.apache.syncope.core.logic.audit.JdbcAuditAppender;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.persistence.api.dao.AuditDAO;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.jdbc.datasource.DataSourceUtils;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -58,6 +53,9 @@ public class LoggerLoader implements SyncopeCoreLoader {
     @Autowired
     private ImplementationLookup implementationLookup;
 
+    @Value("${enable.jdbcAuditAppender:true}")
+    private boolean enableJdbcAuditAppender;
+
     private final Map<String, MemoryAppender> memoryAppenders = new HashMap<>();
 
     @Override
@@ -65,70 +63,46 @@ public class LoggerLoader implements SyncopeCoreLoader {
         return 300;
     }
 
-    private static ColumnMapping[] buildColumnMappings(final LoggerContext ctx) {
-        return new ColumnMapping[] {
-            ColumnMapping.newBuilder().
-            setConfiguration(ctx.getConfiguration()).setName("EVENT_DATE").setType(Timestamp.class).build(),
-            ColumnMapping.newBuilder().
-            setConfiguration(ctx.getConfiguration()).setName("LOGGER_LEVEL").setPattern("%level").build(),
-            ColumnMapping.newBuilder().
-            setConfiguration(ctx.getConfiguration()).setName("LOGGER").setPattern("%logger").build(),
-            ColumnMapping.newBuilder().
-            setConfiguration(ctx.getConfiguration()).setName(AuditDAO.MESSAGE_COLUMN).setPattern("%message").build(),
-            ColumnMapping.newBuilder().
-            setConfiguration(ctx.getConfiguration()).setName("THROWABLE").setPattern("%ex{full}").build()
-        };
-    }
-
     @Override
     public void load(final String domain, final DataSource datasource) {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
 
         ctx.getConfiguration().getAppenders().entrySet().stream().
-                filter(entry -> (entry.getValue() instanceof MemoryAppender)).
+                filter(entry -> entry.getValue() instanceof MemoryAppender).
                 forEach(entry -> memoryAppenders.put(entry.getKey(), (MemoryAppender) entry.getValue()));
 
-        // Audit table and DataSource for the given domain
-        Appender appender = ctx.getConfiguration().getAppender("audit_for_" + domain);
-        if (appender == null) {
-            appender = JdbcAppender.newBuilder().
-                    setName("audit_for_" + domain).
-                    setIgnoreExceptions(false).
-                    setConnectionSource(new DataSourceConnectionSource(domain, datasource)).
-                    setBufferSize(0).
-                    setTableName(AuditDAO.TABLE).
-                    setColumnMappings(buildColumnMappings(ctx)).
-                    build();
-            appender.start();
-            ctx.getConfiguration().addAppender(appender);
+        if (enableJdbcAuditAppender) {
+            JdbcAuditAppender jdbcAuditAppender = (JdbcAuditAppender) ApplicationContextProvider.getBeanFactory().
+                    createBean(JdbcAuditAppender.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+            jdbcAuditAppender.init(domain);
 
             LoggerConfig logConf = new LoggerConfig(AuditLoggerName.getAuditLoggerName(domain), null, false);
-            logConf.addAppender(appender, Level.DEBUG, null);
+            logConf.addAppender(jdbcAuditAppender.getTargetAppender(), Level.DEBUG, null);
             logConf.setLevel(Level.DEBUG);
             ctx.getConfiguration().addLogger(logConf.getName(), logConf);
-
-            // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
-            auditAppenders(domain).forEach(auditAppender -> auditAppender.getEvents().stream().
-                    map(event -> AuditLoggerName.getAuditEventLoggerName(domain, event.toLoggerName())).
-                    forEachOrdered(domainAuditLoggerName -> {
-                        LoggerConfig eventLogConf = ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName);
-                        boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName());
-                        if (isRootLogConf) {
-                            eventLogConf = new LoggerConfig(domainAuditLoggerName, null, false);
-                        }
-                        addAppenderToContext(ctx, auditAppender, eventLogConf);
-                        eventLogConf.setLevel(Level.DEBUG);
-                        if (isRootLogConf) {
-                            ctx.getConfiguration().addLogger(domainAuditLoggerName, eventLogConf);
-                        }
-                    }));
-
-            AuthContextUtils.callAsAdmin(domain, () -> {
-                loggerAccessor.synchronizeLog4J(ctx);
-                return null;
-            });
         }
 
+        // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
+        auditAppenders(domain).forEach(auditAppender -> auditAppender.getEvents().stream().
+                map(event -> AuditLoggerName.getAuditEventLoggerName(domain, event.toLoggerName())).
+                forEach(domainAuditLoggerName -> {
+                    LoggerConfig eventLogConf = ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName);
+                    boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName());
+                    if (isRootLogConf) {
+                        eventLogConf = new LoggerConfig(domainAuditLoggerName, null, false);
+                    }
+                    addAppenderToContext(ctx, auditAppender, eventLogConf);
+                    eventLogConf.setLevel(Level.DEBUG);
+                    if (isRootLogConf) {
+                        ctx.getConfiguration().addLogger(domainAuditLoggerName, eventLogConf);
+                    }
+                }));
+
+        AuthContextUtils.callAsAdmin(domain, () -> {
+            loggerAccessor.synchronizeLog4J(ctx);
+            return null;
+        });
+
         ctx.updateLoggers();
     }
 
@@ -145,8 +119,7 @@ public class LoggerLoader implements SyncopeCoreLoader {
             } else {
                 auditAppender = (AuditAppender) ApplicationContextProvider.getBeanFactory().
                         createBean(clazz, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-                auditAppender.setDomainName(domain);
-                auditAppender.init();
+                auditAppender.init(domain);
             }
             return auditAppender;
         }).collect(Collectors.toList());
@@ -163,39 +136,13 @@ public class LoggerLoader implements SyncopeCoreLoader {
         }
         targetAppender.start();
         ctx.getConfiguration().addAppender(targetAppender);
-        if (auditAppender.isRewriteEnabled()) {
-            RewriteAppender rewriteAppender = ctx.getConfiguration().getAppender(auditAppender.
-                    getTargetAppenderName() + "_rewrite");
-            if (rewriteAppender == null) {
-                rewriteAppender = auditAppender.getRewriteAppender();
-            }
-            rewriteAppender.start();
-            ctx.getConfiguration().addAppender(rewriteAppender);
-            eventLogConf.addAppender(rewriteAppender, Level.DEBUG, null);
+
+        Optional<RewriteAppender> rewriteAppender = auditAppender.getRewriteAppender();
+        if (rewriteAppender.isPresent()) {
+            rewriteAppender.get().start();
+            eventLogConf.addAppender(rewriteAppender.get(), Level.DEBUG, null);
         } else {
             eventLogConf.addAppender(targetAppender, Level.DEBUG, null);
         }
     }
-
-    private static class DataSourceConnectionSource extends AbstractConnectionSource {
-
-        private final String description;
-
-        private final DataSource dataSource;
-
-        DataSourceConnectionSource(final String domain, final DataSource dataSource) {
-            this.description = "dataSource{ domain=" + domain + ", value=" + dataSource + " }";
-            this.dataSource = dataSource;
-        }
-
-        @Override
-        public Connection getConnection() throws SQLException {
-            return DataSourceUtils.getConnection(dataSource);
-        }
-
-        @Override
-        public String toString() {
-            return this.description;
-        }
-    }
 }
diff --git a/core/idrepo/logic/src/main/resources/logic.properties b/core/idrepo/logic/src/main/resources/logic.properties
index 8256e4b..3da2e2c 100644
--- a/core/idrepo/logic/src/main/resources/logic.properties
+++ b/core/idrepo/logic/src/main/resources/logic.properties
@@ -18,3 +18,4 @@ version=${syncope.version}
 buildNumber=${buildNumber}
 logicInvocationHandler=org.apache.syncope.core.logic.LogicInvocationHandler
 classPathScanImplementationLookup=org.apache.syncope.core.logic.init.ClassPathScanImplementationLookup
+enable.jdbcAuditAppender=true
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java
deleted file mode 100644
index b646f91..0000000
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java
+++ /dev/null
@@ -1,52 +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.syncope.core.rest.cxf.service;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.rest.api.beans.AuditQuery;
-import org.apache.syncope.common.rest.api.service.AuditService;
-import org.apache.syncope.core.logic.AuditLogic;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-public class AuditServiceImpl extends AbstractServiceImpl implements AuditService {
-
-    @Autowired
-    private AuditLogic logic;
-
-    @Override
-    public PagedResult<AuditEntryTO> search(final AuditQuery auditQuery) {
-        Pair<Integer, List<AuditEntryTO>> result = logic.search(
-                auditQuery.getEntityKey(),
-                auditQuery.getPage(),
-                auditQuery.getSize(),
-                auditQuery.getType(),
-                auditQuery.getCategory(),
-                auditQuery.getSubcategory(),
-                auditQuery.getEvents(),
-                auditQuery.getResult(),
-                getOrderByClauses(auditQuery.getOrderBy()));
-        return buildPagedResult(result.getRight(), auditQuery.getPage(), auditQuery.getSize(), result.getLeft());
-    }
-}
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
index a143403..b8ab5b4 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
@@ -21,13 +21,17 @@ package org.apache.syncope.core.rest.cxf.service;
 import java.text.ParseException;
 import java.util.List;
 import javax.ws.rs.BadRequestException;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.log.EventCategory;
 import org.apache.syncope.common.lib.log.LogAppender;
 import org.apache.syncope.common.lib.log.LogStatement;
 import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.rest.api.LoggerWrapper;
+import org.apache.syncope.common.rest.api.beans.AuditQuery;
 import org.apache.syncope.common.rest.api.service.LoggerService;
 import org.apache.syncope.core.logic.LoggerLogic;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -58,11 +62,11 @@ public class LoggerServiceImpl extends AbstractServiceImpl implements LoggerServ
 
             case AUDIT:
                 try {
-                    logic.disableAudit(AuditLoggerName.fromLoggerName(name));
-                } catch (IllegalArgumentException | ParseException e) {
-                    throw new BadRequestException(e);
-                }
-                break;
+                logic.disableAudit(AuditLoggerName.fromLoggerName(name));
+            } catch (IllegalArgumentException | ParseException e) {
+                throw new BadRequestException(e);
+            }
+            break;
 
             default:
                 throw new BadRequestException();
@@ -107,11 +111,11 @@ public class LoggerServiceImpl extends AbstractServiceImpl implements LoggerServ
 
             case AUDIT:
                 try {
-                    logic.enableAudit(AuditLoggerName.fromLoggerName(logger.getKey()));
-                } catch (Exception e) {
-                    throw new BadRequestException(e);
-                }
-                break;
+                logic.enableAudit(AuditLoggerName.fromLoggerName(logger.getKey()));
+            } catch (Exception e) {
+                throw new BadRequestException(e);
+            }
+            break;
 
             default:
                 throw new BadRequestException();
@@ -122,4 +126,20 @@ public class LoggerServiceImpl extends AbstractServiceImpl implements LoggerServ
     public List<EventCategory> events() {
         return logic.listAuditEvents();
     }
+
+    @Override
+    public PagedResult<AuditEntry> search(final AuditQuery auditQuery) {
+        Pair<Integer, List<AuditEntry>> result = logic.search(
+                auditQuery.getEntityKey(),
+                auditQuery.getPage(),
+                auditQuery.getSize(),
+                auditQuery.getType(),
+                auditQuery.getCategory(),
+                auditQuery.getSubcategory(),
+                auditQuery.getEvents(),
+                auditQuery.getResult(),
+                getOrderByClauses(auditQuery.getOrderBy()));
+
+        return buildPagedResult(result.getRight(), auditQuery.getPage(), auditQuery.getSize(), result.getLeft());
+    }
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditDAO.java
deleted file mode 100644
index 5a78787..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditDAO.java
+++ /dev/null
@@ -1,45 +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.syncope.core.persistence.api.dao;
-
-import java.util.List;
-
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-
-public interface AuditDAO {
-
-    String TABLE = "SYNCOPEAUDIT";
-
-    String MESSAGE_COLUMN = "MESSAGE";
-
-    List<AuditEntry> findByEntityKey(
-            String entityKey,
-            int page,
-            int size,
-            AuditElements.EventCategoryType type,
-            String category,
-            String subcategory,
-            List<String> events,
-            AuditElements.Result result,
-            List<OrderByClause> orderByClauses);
-
-    int count(String key);
-}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java
index 55a5db7..e8cfe5a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java
@@ -19,11 +19,18 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
+import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Logger;
 
 public interface LoggerDAO extends DAO<Logger> {
 
+    String AUDIT_TABLE = "SYNCOPEAUDIT";
+
+    String AUDIT_MESSAGE_COLUMN = "MESSAGE";
+
     Logger find(String key);
 
     List<Logger> findAll(LoggerType type);
@@ -33,4 +40,17 @@ public interface LoggerDAO extends DAO<Logger> {
     void delete(String key);
 
     void delete(Logger logger);
+
+    List<AuditEntry> findAuditEntries(
+            String entityKey,
+            int page,
+            int size,
+            AuditElements.EventCategoryType type,
+            String category,
+            String subcategory,
+            List<String> events,
+            AuditElements.Result result,
+            List<OrderByClause> orderByClauses);
+
+    int countAuditEntries(String entityKey);
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditEntry.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditEntry.java
deleted file mode 100644
index 2b10e43..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditEntry.java
+++ /dev/null
@@ -1,40 +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.syncope.core.persistence.api.entity;
-
-import java.io.Serializable;
-import java.util.Date;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-
-public interface AuditEntry extends Serializable {
-
-    String getWho();
-
-    AuditLoggerName getLogger();
-
-    Object getBefore();
-
-    Object getOutput();
-
-    Object[] getInput();
-
-    String getThrowable();
-
-    Date getDate();
-}
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAuditDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
similarity index 98%
rename from core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAuditDAO.java
rename to core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
index a921db1..3a7c1f3 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONAuditDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
@@ -27,7 +27,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.springframework.util.CollectionUtils;
 
-public abstract class AbstractJPAJSONAuditDAO extends JPAAuditDAO {
+public abstract class AbstractJPAJSONLoggerDAO extends JPALoggerDAO {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java
similarity index 79%
rename from core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditDAO.java
rename to core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java
index 020069b..bbffaed 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java
@@ -23,20 +23,20 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
-public class MyJPAJSONAuditDAO extends AbstractJPAJSONAuditDAO {
+public class MyJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
 
     private static class MyMessageCriteriaBuilder extends JSONMessageCriteriaBuilder {
 
         @Override
         protected String doBuild(final List<ObjectNode> containers) {
-            query.append('(').append(MESSAGE_COLUMN).append(" -> '$.before' LIKE '%").append(entityKey).
-                    append("%' OR ").append(MESSAGE_COLUMN).append(" -> '$.input' LIKE '%").append(entityKey).
-                    append("%' OR ").append(MESSAGE_COLUMN).append(" -> '$.output' LIKE '%").append(entityKey).
+            query.append('(').append(AUDIT_MESSAGE_COLUMN).append(" -> '$.before' LIKE '%").append(entityKey).
+                    append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" -> '$.input' LIKE '%").append(entityKey).
+                    append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" -> '$.output' LIKE '%").append(entityKey).
                     append("%')");
 
             if (!containers.isEmpty()) {
                 query.append(" AND (").
-                        append(containers.stream().map(container -> "JSON_CONTAINS(" + MESSAGE_COLUMN + ", '"
+                        append(containers.stream().map(container -> "JSON_CONTAINS(" + AUDIT_MESSAGE_COLUMN + ", '"
                         + POJOHelper.serialize(container).replace("'", "''")
                         + "')").collect(Collectors.joining(" OR "))).
                         append(')');
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java
similarity index 78%
rename from core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditDAO.java
rename to core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java
index 54ea828..c9ee797 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java
@@ -21,23 +21,23 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.util.List;
 import java.util.stream.Collectors;
-import org.apache.syncope.core.persistence.jpa.dao.AbstractJPAJSONAuditDAO.JSONMessageCriteriaBuilder;
+import org.apache.syncope.core.persistence.jpa.dao.AbstractJPAJSONLoggerDAO.JSONMessageCriteriaBuilder;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
-public class PGJPAJSONAuditDAO extends AbstractJPAJSONAuditDAO {
+public class PGJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
 
     private static class PGMessageCriteriaBuilder extends JSONMessageCriteriaBuilder {
 
         @Override
         protected String doBuild(final List<ObjectNode> containers) {
-            query.append('(').append(MESSAGE_COLUMN).append(" ->> 'before' LIKE '%").append(entityKey).
-                    append("%' OR ").append(MESSAGE_COLUMN).append(" ->> 'input' LIKE '%").append(entityKey).
-                    append("%' OR ").append(MESSAGE_COLUMN).append(" ->> 'output' LIKE '%").append(entityKey).
+            query.append('(').append(AUDIT_MESSAGE_COLUMN).append(" ->> 'before' LIKE '%").append(entityKey).
+                    append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" ->> 'input' LIKE '%").append(entityKey).
+                    append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" ->> 'output' LIKE '%").append(entityKey).
                     append("%')");
 
             if (!containers.isEmpty()) {
                 query.append(" AND (").
-                        append(containers.stream().map(container -> MESSAGE_COLUMN + " @> '"
+                        append(containers.stream().map(container -> AUDIT_MESSAGE_COLUMN + " @> '"
                         + POJOHelper.serialize(container).replace("'", "''")
                         + "'::jsonb").collect(Collectors.joining(" OR "))).
                         append(')');
@@ -49,7 +49,7 @@ public class PGJPAJSONAuditDAO extends AbstractJPAJSONAuditDAO {
 
     @Override
     protected String select() {
-        return MESSAGE_COLUMN + "::text";
+        return AUDIT_MESSAGE_COLUMN + "::text";
     }
 
     @Override
diff --git a/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties b/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
index 1a7d556..a2a38a9 100644
--- a/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
+++ b/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties b/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
index d4a22e9..5bb728a 100644
--- a/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
+++ b/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
index 91bd97a..9d48a90 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
@@ -25,8 +25,8 @@ import javax.persistence.ValidationMode;
 import javax.validation.Validator;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.AuditDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
@@ -182,13 +182,13 @@ public class PersistenceContext implements EnvironmentAware {
         return (AnyObjectDAO) Class.forName(env.getProperty("anyObject.dao")).getConstructor().newInstance();
     }
 
-    @ConditionalOnMissingBean(name = "auditDAO")
+    @ConditionalOnMissingBean(name = "loggerDAO")
     @Bean
-    public AuditDAO auditDAO()
+    public LoggerDAO loggerDAO()
             throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException,
             IllegalArgumentException, InvocationTargetException {
 
-        return (AuditDAO) Class.forName(env.getProperty("audit.dao")).getConstructor().newInstance();
+        return (LoggerDAO) Class.forName(env.getProperty("logger.dao")).getConstructor().newInstance();
     }
 
     @Bean
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
index 8015088..116e88d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
@@ -109,11 +109,11 @@ public class XMLContentExporter implements ContentExporter {
     private static final Logger LOG = LoggerFactory.getLogger(XMLContentExporter.class);
 
     private static final Set<String> TABLE_PREFIXES_TO_BE_EXCLUDED = SetUtils.hashSet(
-        "QRTZ_", "LOGGING", JPAReportExec.TABLE, JPATaskExec.TABLE,
-        JPAUser.TABLE, JPAUPlainAttr.TABLE, JPAUPlainAttrValue.TABLE, JPAUPlainAttrUniqueValue.TABLE,
-        JPAURelationship.TABLE, JPAUMembership.TABLE,
-        JPAAnyObject.TABLE, JPAAPlainAttr.TABLE, JPAAPlainAttrValue.TABLE, JPAAPlainAttrUniqueValue.TABLE,
-        JPAARelationship.TABLE, JPAAMembership.TABLE, JPAAccessToken.TABLE
+            "QRTZ_", "LOGGING", JPAReportExec.TABLE, JPATaskExec.TABLE,
+            JPAUser.TABLE, JPAUPlainAttr.TABLE, JPAUPlainAttrValue.TABLE, JPAUPlainAttrUniqueValue.TABLE,
+            JPAURelationship.TABLE, JPAUMembership.TABLE,
+            JPAAnyObject.TABLE, JPAAPlainAttr.TABLE, JPAAPlainAttrValue.TABLE, JPAAPlainAttrUniqueValue.TABLE,
+            JPAARelationship.TABLE, JPAAMembership.TABLE, JPAAccessToken.TABLE
     );
 
     private static final Map<String, String> TABLES_TO_BE_FILTERED =
@@ -134,7 +134,7 @@ public class XMLContentExporter implements ContentExporter {
     }
 
     private static List<String> sortByForeignKeys(final String dbSchema, final Connection conn,
-                                                  final Set<String> tableNames)
+            final Set<String> tableNames)
             throws SQLException {
 
         Set<MultiParentNode<String>> roots = new HashSet<>();
@@ -548,7 +548,7 @@ public class XMLContentExporter implements ContentExporter {
 
             EntityManagerFactory emf = EntityManagerFactoryUtils.findEntityManagerFactory(
                     ApplicationContextProvider.getBeanFactory(), domain);
-            Set<EntityType<?>> entityTypes = emf == null ? Collections.emptySet() : emf.getMetamodel().getEntities();
+            Set<EntityType<?>> entityTypes = emf == null ? Set.of() : emf.getMetamodel().getEntities();
             BidiMap<String, EntityType<?>> entities = entities(entityTypes);
 
             // then sort tables based on foreign keys and dump
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditDAO.java
deleted file mode 100644
index be47a81..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditDAO.java
+++ /dev/null
@@ -1,163 +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.syncope.core.persistence.jpa.dao;
-
-import java.sql.Clob;
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import javax.persistence.Query;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.core.persistence.api.dao.AuditDAO;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
-import org.apache.syncope.core.provisioning.api.AuditEntryImpl;
-import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
-import org.springframework.transaction.annotation.Transactional;
-
-public class JPAAuditDAO extends AbstractDAO<AbstractEntity> implements AuditDAO {
-
-    protected static class MessageCriteriaBuilder {
-
-        protected final StringBuilder query = new StringBuilder();
-
-        protected MessageCriteriaBuilder entityKey(final String entityKey) {
-            query.append(' ').append(MESSAGE_COLUMN).append(" LIKE '%\"key\":\"").append(entityKey).append("\"%'");
-            return this;
-        }
-
-        public MessageCriteriaBuilder type(final AuditElements.EventCategoryType type) {
-            if (type != null) {
-                query.append(" AND " + MESSAGE_COLUMN + " LIKE '%\"type\":\"").append(type.name()).append("\"%'");
-            }
-            return this;
-        }
-
-        public MessageCriteriaBuilder category(final String category) {
-            if (StringUtils.isNotBlank(category)) {
-                query.append(" AND " + MESSAGE_COLUMN + " LIKE '%\"category\":\"").append(category).append("\"%'");
-            }
-            return this;
-        }
-
-        public MessageCriteriaBuilder subcategory(final String subcategory) {
-            if (StringUtils.isNotBlank(subcategory)) {
-                query.append(" AND " + MESSAGE_COLUMN + " LIKE '%\"subcategory\":\"").
-                        append(subcategory).append("\"%'");
-            }
-            return this;
-        }
-
-        public MessageCriteriaBuilder events(final List<String> events) {
-            if (!events.isEmpty()) {
-                query.append(" AND ( ").
-                        append(events.stream().
-                                map(event -> MESSAGE_COLUMN + " LIKE '%\"event\":\"" + event + "\"%'").
-                                collect(Collectors.joining(" OR "))).
-                        append(" )");
-            }
-            return this;
-        }
-
-        public MessageCriteriaBuilder result(final AuditElements.Result result) {
-            if (result != null) {
-                query.append(" AND ").
-                        append(MESSAGE_COLUMN).append(" LIKE '%\"result\":\"").append(result.name()).append("\"%' ");
-            }
-            return this;
-        }
-
-        public String build() {
-            return query.toString();
-        }
-    }
-
-    protected MessageCriteriaBuilder messageCriteriaBuilder(final String entityKey) {
-        return new MessageCriteriaBuilder().entityKey(entityKey);
-    }
-
-    protected String select() {
-        return MESSAGE_COLUMN;
-    }
-
-    @Transactional(readOnly = true)
-    @Override
-    public List<AuditEntry> findByEntityKey(
-            final String entityKey,
-            final int page,
-            final int itemsPerPage,
-            final AuditElements.EventCategoryType type,
-            final String category,
-            final String subcategory,
-            final List<String> events,
-            final AuditElements.Result result,
-            final List<OrderByClause> orderByClauses) {
-
-        String queryString = "SELECT " + select()
-                + " FROM " + TABLE
-                + " WHERE " + messageCriteriaBuilder(entityKey).
-                        type(type).
-                        category(category).
-                        subcategory(subcategory).
-                        result(result).
-                        events(events).
-                        build();
-        if (!orderByClauses.isEmpty()) {
-            queryString += " ORDER BY " + orderByClauses.stream().
-                    map(orderBy -> orderBy.getField() + ' ' + orderBy.getDirection().name()).
-                    collect(Collectors.joining(","));
-        }
-
-        Query query = entityManager().createNativeQuery(queryString);
-        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
-        if (itemsPerPage >= 0) {
-            query.setMaxResults(itemsPerPage);
-        }
-
-        @SuppressWarnings("unchecked")
-        List<Object> entries = query.getResultList();
-        return entries.stream().map(row -> {
-            String value;
-            if (row instanceof Clob) {
-                Clob clob = (Clob) row;
-                try {
-                    value = clob.getSubString(1, (int) clob.length());
-                } catch (SQLException e) {
-                    LOG.error("Unexpected error reading Audit Entry for entity key {}", entityKey, e);
-                    return null;
-                }
-            } else {
-                value = row.toString();
-            }
-            return POJOHelper.deserialize(value, AuditEntryImpl.class);
-        }).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    @Override
-    public int count(final String key) {
-        String queryString = "SELECT COUNT(0) FROM " + TABLE
-                + " WHERE " + messageCriteriaBuilder(key).build();
-        Query countQuery = entityManager().createNativeQuery(queryString);
-
-        return ((Number) countQuery.getSingleResult()).intValue();
-    }
-}
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java
index 6e4f414..6e85952 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java
@@ -18,18 +18,85 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.sql.Clob;
+import java.sql.SQLException;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import javax.persistence.Query;
 import javax.persistence.TypedQuery;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.persistence.jpa.entity.JPALogger;
-import org.springframework.stereotype.Repository;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.springframework.transaction.annotation.Transactional;
 
-@Repository
 public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
+    protected static class MessageCriteriaBuilder {
+
+        protected final StringBuilder query = new StringBuilder();
+
+        protected MessageCriteriaBuilder entityKey(final String entityKey) {
+            query.append(' ').append(AUDIT_MESSAGE_COLUMN).
+                    append(" LIKE '%key%").append(entityKey).append("%'");
+            return this;
+        }
+
+        public MessageCriteriaBuilder type(final AuditElements.EventCategoryType type) {
+            if (type != null) {
+                query.append(" AND ").append(AUDIT_MESSAGE_COLUMN).
+                        append(" LIKE '%\"type\":\"").append(type.name()).append("\"%'");
+            }
+            return this;
+        }
+
+        public MessageCriteriaBuilder category(final String category) {
+            if (StringUtils.isNotBlank(category)) {
+                query.append(" AND ").append(AUDIT_MESSAGE_COLUMN).
+                        append(" LIKE '%\"category\":\"").append(category).append("\"%'");
+            }
+            return this;
+        }
+
+        public MessageCriteriaBuilder subcategory(final String subcategory) {
+            if (StringUtils.isNotBlank(subcategory)) {
+                query.append(" AND ").append(AUDIT_MESSAGE_COLUMN).
+                        append(" LIKE '%\"subcategory\":\"").append(subcategory).append("\"%'");
+            }
+            return this;
+        }
+
+        public MessageCriteriaBuilder events(final List<String> events) {
+            if (!events.isEmpty()) {
+                query.append(" AND ( ").
+                        append(events.stream().
+                                map(event -> AUDIT_MESSAGE_COLUMN + " LIKE '%\"event\":\"" + event + "\"%'").
+                                collect(Collectors.joining(" OR "))).
+                        append(" )");
+            }
+            return this;
+        }
+
+        public MessageCriteriaBuilder result(final AuditElements.Result result) {
+            if (result != null) {
+                query.append(" AND ").append(AUDIT_MESSAGE_COLUMN).
+                        append(" LIKE '%\"result\":\"").append(result.name()).append("\"%' ");
+            }
+            return this;
+        }
+
+        public String build() {
+            return query.toString();
+        }
+    }
+
     @Override
     public Logger find(final String key) {
         return entityManager().find(JPALogger.class, key);
@@ -66,4 +133,74 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         delete(logger);
     }
+
+    protected MessageCriteriaBuilder messageCriteriaBuilder(final String entityKey) {
+        return new MessageCriteriaBuilder().entityKey(entityKey);
+    }
+
+    @Override
+    public int countAuditEntries(final String entityKey) {
+        String queryString = "SELECT COUNT(0) FROM " + AUDIT_TABLE
+                + " WHERE " + messageCriteriaBuilder(entityKey).build();
+        Query countQuery = entityManager().createNativeQuery(queryString);
+
+        return ((Number) countQuery.getSingleResult()).intValue();
+    }
+
+    protected String select() {
+        return AUDIT_MESSAGE_COLUMN;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<AuditEntry> findAuditEntries(
+            final String entityKey,
+            final int page,
+            final int itemsPerPage,
+            final AuditElements.EventCategoryType type,
+            final String category,
+            final String subcategory,
+            final List<String> events,
+            final AuditElements.Result result,
+            final List<OrderByClause> orderByClauses) {
+
+        String queryString = "SELECT " + select()
+                + " FROM " + AUDIT_TABLE
+                + " WHERE " + messageCriteriaBuilder(entityKey).
+                        type(type).
+                        category(category).
+                        subcategory(subcategory).
+                        result(result).
+                        events(events).
+                        build();
+        if (!orderByClauses.isEmpty()) {
+            queryString += " ORDER BY " + orderByClauses.stream().
+                    map(orderBy -> orderBy.getField() + ' ' + orderBy.getDirection().name()).
+                    collect(Collectors.joining(","));
+        }
+
+        Query query = entityManager().createNativeQuery(queryString);
+        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
+        if (itemsPerPage >= 0) {
+            query.setMaxResults(itemsPerPage);
+        }
+
+        @SuppressWarnings("unchecked")
+        List<Object> entries = query.getResultList();
+        return entries.stream().map(row -> {
+            String value;
+            if (row instanceof Clob) {
+                Clob clob = (Clob) row;
+                try {
+                    value = clob.getSubString(1, (int) clob.length());
+                } catch (SQLException e) {
+                    LOG.error("Unexpected error reading Audit Entry for entity key {}", entityKey, e);
+                    return null;
+                }
+            } else {
+                value = row.toString();
+            }
+            return POJOHelper.deserialize(value, AuditEntry.class);
+        }).filter(Objects::nonNull).collect(Collectors.toList());
+    }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
index 1dd570d..a65b3fb 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
@@ -18,12 +18,15 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
 import java.util.Objects;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "key")
 public abstract class AbstractEntity implements Entity {
 
     private static final long serialVersionUID = -9017214159540857901L;
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
index 5affad4..d44e081 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
@@ -246,5 +246,4 @@ public class JPAConnInstance extends AbstractGeneratedKeyEntity implements ConnI
         checkType(poolConf, JPAConnPoolConf.class);
         this.poolConf = (JPAConnPoolConf) poolConf;
     }
-
 }
diff --git a/core/persistence-jpa/src/main/resources/persistence.properties b/core/persistence-jpa/src/main/resources/persistence.properties
index ac6d8a8..b547e65 100644
--- a/core/persistence-jpa/src/main/resources/persistence.properties
+++ b/core/persistence-jpa/src/main/resources/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditEntryImpl.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditEntryImpl.java
deleted file mode 100644
index 3d6b949..0000000
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditEntryImpl.java
+++ /dev/null
@@ -1,219 +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.syncope.core.provisioning.api;
-
-import java.util.Date;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.SerializationUtils;
-import org.apache.syncope.common.lib.request.UserCR;
-import org.apache.syncope.common.lib.request.UserUR;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-
-@SuppressWarnings({ "squid:S1450", "squid:S1948" })
-public class AuditEntryImpl implements AuditEntry {
-
-    private static final long serialVersionUID = -2299082316063743582L;
-
-    private static final String MASKED_VALUE = "<MASKED>";
-
-    private final String who;
-
-    private final AuditLoggerName logger;
-
-    private final Object before;
-
-    private final Object output;
-
-    private final Object[] input;
-
-    private String throwable;
-
-    private Date date;
-
-    @JsonCreator
-    public AuditEntryImpl(
-            @JsonProperty("who") final String who,
-            @JsonProperty("logger") final AuditLoggerName logger,
-            @JsonProperty("before") final Object before,
-            @JsonProperty("output") final Object output,
-            @JsonProperty("input") final Object[] input) {
-
-        super();
-
-        this.who = who;
-        this.logger = logger;
-        this.before = maskSensitive(before);
-        this.output = maskSensitive(output);
-        this.input = ArrayUtils.clone(input);
-        if (this.input != null) {
-            for (int i = 0; i < this.input.length; i++) {
-                this.input[i] = maskSensitive(this.input[i]);
-            }
-        }
-    }
-
-    private static Object maskSensitive(final Object object) {
-        Object masked;
-
-        if (object instanceof UserTO) {
-            masked = SerializationUtils.clone((UserTO) object);
-            if (((UserTO) masked).getPassword() != null) {
-                ((UserTO) masked).setPassword(MASKED_VALUE);
-            }
-            if (((UserTO) masked).getSecurityAnswer() != null) {
-                ((UserTO) masked).setSecurityAnswer(MASKED_VALUE);
-            }
-        } else if (object instanceof UserCR) {
-            masked = SerializationUtils.clone((UserCR) object);
-            if (((UserCR) masked).getPassword() != null) {
-                ((UserCR) masked).setPassword(MASKED_VALUE);
-            }
-            if (((UserCR) masked).getSecurityAnswer() != null) {
-                ((UserCR) masked).setSecurityAnswer(MASKED_VALUE);
-            }
-        } else if (object instanceof UserUR && ((UserUR) object).getPassword() != null) {
-            masked = SerializationUtils.clone((UserUR) object);
-            ((UserUR) masked).getPassword().setValue(MASKED_VALUE);
-        } else {
-            masked = object;
-        }
-
-        return masked;
-    }
-
-    @Override
-    public String getWho() {
-        return who;
-    }
-
-    @Override
-    public AuditLoggerName getLogger() {
-        return logger;
-    }
-
-    @Override
-    public Object getBefore() {
-        return before;
-    }
-
-    @Override
-    public Object getOutput() {
-        return output;
-    }
-
-    @Override
-    public Object[] getInput() {
-        return input;
-    }
-
-    @Override
-    public String getThrowable() {
-        return throwable;
-    }
-
-    public void setThrowable(final String throwable) {
-        this.throwable = throwable;
-    }
-
-    @Override
-    public Date getDate() {
-        return date;
-    }
-
-    public void setDate(final Date date) {
-        this.date = date;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static final class Builder {
-
-        private String who;
-
-        private AuditLoggerName logger;
-
-        private Object before;
-
-        private Object output;
-
-        private Object[] input;
-
-        private String throwable;
-
-        private Date date;
-
-        private String key;
-
-        private Builder() {
-        }
-
-        public Builder date(final Date date) {
-            this.date = date;
-            return this;
-        }
-
-        public Builder throwable(final String throwable) {
-            this.throwable = throwable;
-            return this;
-        }
-
-        public Builder key(final String key) {
-            this.key = key;
-            return this;
-        }
-
-        public Builder who(final String who) {
-            this.who = who;
-            return this;
-        }
-
-        public Builder logger(final AuditLoggerName logger) {
-            this.logger = logger;
-            return this;
-        }
-
-        public Builder before(final Object before) {
-            this.before = before;
-            return this;
-        }
-
-        public Builder output(final Object output) {
-            this.output = output;
-            return this;
-        }
-
-        public Builder input(final Object[] input) {
-            this.input = input;
-            return this;
-        }
-
-        public AuditEntryImpl build() {
-            AuditEntryImpl entry = new AuditEntryImpl(who, logger, before, output, input);
-            entry.setDate(date);
-            entry.setThrowable(throwable);
-            return entry;
-        }
-    }
-}
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java
similarity index 73%
rename from core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
rename to core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java
index 082f71f..1b491ce 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java
@@ -18,10 +18,13 @@
  */
 package org.apache.syncope.core.provisioning.api.data;
 
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
+import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.core.persistence.api.entity.Logger;
 
-public interface AuditDataBinder {
+public interface LoggerDataBinder {
 
-    AuditEntryTO getAuditTO(String key, AuditEntry auditEntry);
+    LoggerTO getLoggerTO(Logger logger);
+
+    LoggerTO getLoggerTO(AuditLoggerName auditLoggerName);
 }
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
index c7b8faa..af99906 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelper.java
@@ -64,18 +64,6 @@ public final class POJOHelper {
         return result;
     }
 
-    public static String serializeWithDefaultPrettyPrinter(final Object object) {
-        String result = null;
-
-        try {
-            result = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
-        } catch (Exception e) {
-            LOG.error("During serialization", e);
-        }
-
-        return result;
-    }
-
     public static <T extends Object> T deserialize(final String serialized, final Class<T> reference) {
         T result = null;
 
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AuditEntryImplTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AuditEntryImplTest.java
deleted file mode 100644
index 42aff67..0000000
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AuditEntryImplTest.java
+++ /dev/null
@@ -1,93 +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.syncope.core.provisioning.api;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.Date;
-import java.util.UUID;
-import org.apache.commons.lang3.SerializationUtils;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.syncope.common.lib.request.UserUR;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.springframework.test.util.ReflectionTestUtils;
-
-public class AuditEntryImplTest extends AbstractTest {
-
-    @Mock
-    private AuditLoggerName logger;
-
-    private final String who = "testUser";
-
-    private final Object before = "before";
-
-    private final String output = "output";
-
-    private final String[] input = { "test1", "test2" };
-
-    private final String throwable = "throwable";
-
-    private final String key = UUID.randomUUID().toString();
-
-    private final Date date = new Date();
-
-    @Test
-    public void AuditEntryImpl() {
-        AuditEntryImpl auditEntryImpl = new AuditEntryImpl(who, logger, before, output, input);
-        AuditEntryImpl auditEntryImpl2 = AuditEntryImpl.builder().
-                who(who).
-                before(before).
-                logger(logger).
-                output(output).
-                input(null).
-                date(date).
-                key(key).
-                throwable(throwable).
-                build();
-
-        assertEquals(auditEntryImpl2.getWho(), auditEntryImpl.getWho());
-        assertEquals(auditEntryImpl2.getLogger(), auditEntryImpl.getLogger());
-        assertNotEquals(auditEntryImpl2.getInput(), auditEntryImpl.getInput().length);
-        assertEquals(auditEntryImpl2.getDate(), auditEntryImpl2.getDate());
-        assertEquals(auditEntryImpl2.getThrowable(), auditEntryImpl2.getThrowable());
-    }
-
-    @Test
-    public void AuditEntryImplWithUserTO(@Mock UserTO userTO) {
-        AuditEntryImpl auditEntryImpl = new AuditEntryImpl(who, logger, before, userTO, input);
-        assertTrue(EqualsBuilder.reflectionEquals(SerializationUtils.clone(userTO), auditEntryImpl.getOutput()));
-
-        ReflectionTestUtils.setField(userTO, "password", "testP4ssw0rd!");
-        ReflectionTestUtils.setField(userTO, "securityAnswer", "42");
-        AuditEntryImpl auditEntryImpl2 = new AuditEntryImpl(who, logger, before, userTO, input);
-        assertFalse(EqualsBuilder.reflectionEquals(SerializationUtils.clone(userTO), auditEntryImpl2.getOutput()));
-    }
-
-    @Test
-    public void AuditEntryImplWithUserPatch(@Mock UserUR userUR) {
-        AuditEntryImpl auditEntryImpl = new AuditEntryImpl(who, logger, userUR, output, input);
-        assertTrue(EqualsBuilder.reflectionEquals(SerializationUtils.clone(userUR), auditEntryImpl.getBefore()));
-    }
-}
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/PropagationByResourceTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/PropagationByResourceTest.java
index 5671b32..65e6228 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/PropagationByResourceTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/PropagationByResourceTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -156,15 +155,15 @@ public class PropagationByResourceTest extends AbstractTest {
 
         ReflectionTestUtils.setField(propagationByResource, "toBeDeleted", matchingList);
         assertEquals(matchingList, propagationByResource.get(ResourceOperation.DELETE));
-        assertEquals(Collections.<String>emptySet(), propagationByResource.get(ResourceOperation.CREATE));
-        assertEquals(Collections.<String>emptySet(), propagationByResource.get(ResourceOperation.UPDATE));
-        assertEquals(Collections.<String>emptySet(), propagationByResource.get(ResourceOperation.NONE));
+        assertEquals(Set.of(), propagationByResource.get(ResourceOperation.CREATE));
+        assertEquals(Set.of(), propagationByResource.get(ResourceOperation.UPDATE));
+        assertEquals(Set.of(), propagationByResource.get(ResourceOperation.NONE));
 
     }
 
     @Test
     public void asMap() {
-        assertEquals(Collections.emptyMap(), propagationByResource.asMap());
+        assertEquals(Map.of(), propagationByResource.asMap());
     }
 
     @Test
@@ -173,8 +172,8 @@ public class PropagationByResourceTest extends AbstractTest {
         keys.add("testKey1");
         keys.add("testKey2");
 
-        propagationByResource.set(ResourceOperation.CREATE, Collections.<String>emptySet());
-        assertEquals(Collections.emptySet(), ReflectionTestUtils.getField(propagationByResource, "toBeCreated"));
+        propagationByResource.set(ResourceOperation.CREATE, Set.of());
+        assertEquals(Set.of(), ReflectionTestUtils.getField(propagationByResource, "toBeCreated"));
         propagationByResource.set(ResourceOperation.CREATE, keys);
         assertEquals(keys, ReflectionTestUtils.getField(propagationByResource, "toBeCreated"));
         propagationByResource.set(ResourceOperation.UPDATE, keys);
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValueTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValueTest.java
index c4ee199..561d53b 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValueTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValueTest.java
@@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.util.Collections;
+import java.util.List;
 import org.apache.syncope.core.provisioning.api.AbstractTest;
 import org.junit.jupiter.api.Test;
 
@@ -32,8 +32,8 @@ public class VirAttrCacheValueTest extends AbstractTest {
     @Test
     public void test() {
         Object nullObj = null;
-        VirAttrCacheValue cacheValue = new VirAttrCacheValue(Collections.singletonList("testValue"));
-        VirAttrCacheValue cacheValue2 = new VirAttrCacheValue(Collections.emptyList());
+        VirAttrCacheValue cacheValue = new VirAttrCacheValue(List.of("testValue"));
+        VirAttrCacheValue cacheValue2 = new VirAttrCacheValue(List.of());
 
         cacheValue.forceExpiring();
         cacheValue2.forceExpiring();
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeDeserializerTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeDeserializerTest.java
index 4d8c578..a9748ce 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeDeserializerTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeDeserializerTest.java
@@ -26,7 +26,9 @@ import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import org.apache.syncope.core.provisioning.api.AbstractTest;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.junit.jupiter.api.BeforeEach;
@@ -62,7 +64,7 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(jp.readValueAsTree()).thenReturn(tree);
         when(tree.get("name")).thenReturn(node2);
         when(tree.get("value")).thenReturn(node);
-        when(node.iterator()).thenReturn(Collections.singletonList(node).iterator());
+        when(node.iterator()).thenReturn(List.of(node).iterator());
     }
 
     @Test
@@ -81,7 +83,7 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(node.asBoolean()).thenReturn(Boolean.TRUE);
         attr = deserializer.deserialize(jp, ct);
         assertEquals(name, attr.getName());
-        assertEquals(Collections.singletonList(Boolean.TRUE.toString()).get(0), attr.getValue().get(0));
+        assertEquals(List.of(Boolean.TRUE.toString()).get(0), attr.getValue().get(0));
     }
 
     @Test
@@ -93,7 +95,7 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(node.asDouble()).thenReturn(number);
         attr = deserializer.deserialize(jp, ct);
         assertEquals(name, attr.getName());
-        assertEquals(Collections.singletonList(number).get(0), attr.getValue().get(0));
+        assertEquals(List.of(number).get(0), attr.getValue().get(0));
     }
 
     @Test
@@ -105,7 +107,7 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(node.asLong()).thenReturn(number);
         attr = deserializer.deserialize(jp, ct);
         assertEquals(name, attr.getName());
-        assertEquals(Collections.singletonList(number.toString()).get(0), attr.getValue().get(0));
+        assertEquals(List.of(number.toString()).get(0), attr.getValue().get(0));
     }
 
     @Test
@@ -116,7 +118,7 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(node.asInt()).thenReturn(number);
         attr = deserializer.deserialize(jp, ct);
         assertEquals(attr.getName(), name);
-        assertEquals(Collections.singletonList(number.toString()).get(0), attr.getValue().get(0));
+        assertEquals(List.of(number.toString()).get(0), attr.getValue().get(0));
     }
 
     @Test
@@ -126,6 +128,6 @@ public class AttributeDeserializerTest extends AbstractTest {
         when(node.asText()).thenReturn(text);
         attr = deserializer.deserialize(jp, ct);
         assertEquals(attr.getName(), name);
-        assertEquals(Collections.singletonList(text).get(0), attr.getValue().get(0));
+        assertEquals(List.of(text).get(0), attr.getValue().get(0));
     }
 }
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeSerializerTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeSerializerTest.java
index 36f25a4..0a62afd 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeSerializerTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/AttributeSerializerTest.java
@@ -31,7 +31,7 @@ import static org.mockito.Mockito.when;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import java.io.IOException;
-import java.util.Collections;
+import java.util.List;
 import org.apache.syncope.core.provisioning.api.AbstractTest;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.common.objects.Attribute;
@@ -50,31 +50,31 @@ public class AttributeSerializerTest extends AbstractTest {
         verify(jgen).writeFieldName("value");
         verify(jgen).writeNull();
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(new GuardedString()));
+        when(source.getValue()).thenAnswer(ic -> List.of(new GuardedString()));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeObject(any(GuardedString.class));
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(9000));
+        when(source.getValue()).thenAnswer(ic -> List.of(9000));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeNumber(anyInt());
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(9000L));
+        when(source.getValue()).thenAnswer(ic -> List.of(9000L));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeNumber(anyLong());
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(9000.1));
+        when(source.getValue()).thenAnswer(ic -> List.of(9000.1));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeNumber(anyDouble());
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(Boolean.TRUE));
+        when(source.getValue()).thenAnswer(ic -> List.of(Boolean.TRUE));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeBoolean(anyBoolean());
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList(new byte[] { 9, 0, 0, 0 }));
+        when(source.getValue()).thenAnswer(ic -> List.of(new byte[] { 9, 0, 0, 0 }));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeString(anyString());
 
-        when(source.getValue()).thenAnswer(ic -> Collections.singletonList("test"));
+        when(source.getValue()).thenAnswer(ic -> List.of("test"));
         serializer.serialize(source, jgen, sp);
         verify(jgen).writeString(eq("test"));
     }
diff --git a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelperTest.java b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelperTest.java
index d94a87e..e3d83dd 100644
--- a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelperTest.java
+++ b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/serialization/POJOHelperTest.java
@@ -36,13 +36,6 @@ public class POJOHelperTest extends AbstractTest {
     }
 
     @Test
-    public void serializeWithDefaultPrettyPrinter() {
-        Object object = 9001;
-
-        assertEquals(String.valueOf(object), POJOHelper.serializeWithDefaultPrettyPrinter(object));
-    }
-
-    @Test
     public void deserializeWithClassReference() {
         String serialized = "false";
 
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
index 374c717..1610019 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
@@ -18,8 +18,14 @@
  */
 package org.apache.syncope.core.provisioning.java;
 
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-import org.apache.syncope.core.provisioning.api.AuditEntryImpl;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.request.UserCR;
+import org.apache.syncope.common.lib.request.UserUR;
+import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.core.provisioning.api.AuditManager;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
@@ -28,6 +34,7 @@ import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent;
+import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,11 +42,40 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-
 @Transactional(readOnly = true)
 public class DefaultAuditManager implements AuditManager {
 
+    private static final String MASKED_VALUE = "<MASKED>";
+
+    private static Object maskSensitive(final Object object) {
+        Object masked;
+
+        if (object instanceof UserTO) {
+            masked = SerializationUtils.clone((UserTO) object);
+            if (((UserTO) masked).getPassword() != null) {
+                ((UserTO) masked).setPassword(MASKED_VALUE);
+            }
+            if (((UserTO) masked).getSecurityAnswer() != null) {
+                ((UserTO) masked).setSecurityAnswer(MASKED_VALUE);
+            }
+        } else if (object instanceof UserCR) {
+            masked = SerializationUtils.clone((UserCR) object);
+            if (((UserCR) masked).getPassword() != null) {
+                ((UserCR) masked).setPassword(MASKED_VALUE);
+            }
+            if (((UserCR) masked).getSecurityAnswer() != null) {
+                ((UserCR) masked).setSecurityAnswer(MASKED_VALUE);
+            }
+        } else if (object instanceof UserUR && ((UserUR) object).getPassword() != null) {
+            masked = SerializationUtils.clone((UserUR) object);
+            ((UserUR) masked).getPassword().setValue(MASKED_VALUE);
+        } else {
+            masked = object;
+        }
+
+        return masked;
+    }
+
     @Autowired
     private LoggerDAO loggerDAO;
 
@@ -51,11 +87,11 @@ public class DefaultAuditManager implements AuditManager {
             final String subcategory,
             final String event) {
 
-        AuditEntry auditEntry = AuditEntryImpl.builder().
-                who(who).
-                logger(new AuditLoggerName(type, category, subcategory, event, Result.SUCCESS)).
-                date(new Date()).
-                build();
+        AuditEntry auditEntry = new AuditEntry();
+        auditEntry.setWho(who);
+        auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, Result.SUCCESS));
+        auditEntry.setDate(new Date());
+
         org.apache.syncope.core.persistence.api.entity.Logger syncopeLogger =
                 loggerDAO.find(auditEntry.getLogger().toLoggerName());
         boolean auditRequested = syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG;
@@ -64,11 +100,8 @@ public class DefaultAuditManager implements AuditManager {
             return true;
         }
 
-        auditEntry = AuditEntryImpl.builder()
-                .who(who)
-                .logger(new AuditLoggerName(type, category, subcategory, event, Result.FAILURE))
-                .date(new Date())
-                .build();
+        auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, Result.FAILURE));
+
         syncopeLogger = loggerDAO.find(auditEntry.getLogger().toLoggerName());
         auditRequested = syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG;
 
@@ -108,14 +141,22 @@ public class DefaultAuditManager implements AuditManager {
             throwable = (Throwable) output;
         }
 
-        AuditEntry auditEntry = AuditEntryImpl.builder().
-                who(who).
-                logger(new AuditLoggerName(type, category, subcategory, event, condition)).
-                before(before).
-                output(throwable == null ? output : throwable.getMessage()).
-                input(input).
-                date(new Date()).
-                build();
+        AuditEntry auditEntry = new AuditEntry();
+        auditEntry.setWho(who);
+        auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, condition));
+        auditEntry.setDate(new Date());
+        auditEntry.setBefore(POJOHelper.serialize((maskSensitive(before))));
+        if (throwable == null) {
+            auditEntry.setOutput(POJOHelper.serialize((maskSensitive(output))));
+        } else {
+            auditEntry.setOutput(throwable.getMessage());
+            auditEntry.setThrowable(ExceptionUtils2.getFullStackTrace(throwable));
+        }
+        if (input != null) {
+            auditEntry.getInputs().addAll(Arrays.stream(input).
+                    map(DefaultAuditManager::maskSensitive).map(POJOHelper::serialize).
+                    collect(Collectors.toList()));
+        }
 
         org.apache.syncope.core.persistence.api.entity.Logger syncopeLogger =
                 loggerDAO.find(auditEntry.getLogger().toLoggerName());
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
deleted file mode 100644
index 4937503..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
+++ /dev/null
@@ -1,66 +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.syncope.core.provisioning.java.data;
-
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-import org.apache.syncope.core.provisioning.api.data.AuditDataBinder;
-import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
-import org.springframework.stereotype.Component;
-
-@Component
-public class AuditDataBinderImpl implements AuditDataBinder {
-
-    @Override
-    public AuditEntryTO getAuditTO(final String key, final AuditEntry auditEntry) {
-        AuditEntryTO auditEntryTO = new AuditEntryTO();
-        auditEntryTO.setKey(key);
-        auditEntryTO.setWho(auditEntry.getWho());
-        auditEntryTO.setDate(auditEntry.getDate());
-        auditEntryTO.setThrowable(auditEntry.getThrowable());
-        auditEntryTO.setLoggerName(auditEntry.getLogger().toLoggerName());
-
-        auditEntryTO.setSubCategory(auditEntry.getLogger().getSubcategory());
-        auditEntryTO.setEvent(auditEntry.getLogger().getEvent());
-
-        if (auditEntry.getLogger().getResult() != null) {
-            auditEntryTO.setResult(auditEntry.getLogger().getResult().name());
-        }
-
-        if (auditEntry.getBefore() != null) {
-            auditEntryTO.setBefore(POJOHelper.serializeWithDefaultPrettyPrinter(auditEntry.getBefore()));
-        }
-
-        if (auditEntry.getInput() != null) {
-            auditEntryTO.getInputs().addAll(Arrays.stream(auditEntry.getInput()).
-                    filter(Objects::nonNull).
-                    map(POJOHelper::serializeWithDefaultPrettyPrinter).
-                    collect(Collectors.toList()));
-        }
-
-        if (auditEntry.getOutput() != null) {
-            auditEntryTO.setOutput(POJOHelper.serializeWithDefaultPrettyPrinter(auditEntry.getOutput()));
-        }
-
-        return auditEntryTO;
-    }
-}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java
similarity index 51%
copy from core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
copy to core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java
index 45b28a3..906c92d 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java
@@ -16,38 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.logic.audit;
+package org.apache.syncope.core.provisioning.java.data;
 
-import java.util.Set;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
+import org.apache.syncope.common.lib.log.LoggerTO;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.logic.AbstractAuditAppender;
+import org.apache.syncope.common.lib.types.LoggerLevel;
+import org.apache.syncope.core.persistence.api.entity.Logger;
+import org.springframework.stereotype.Component;
+import org.apache.syncope.core.provisioning.api.data.LoggerDataBinder;
 
-/**
- * Default (abstract) implementation of custom audit appender.
- * It is bound to an empty collection of events, i.e. it does not create any logger.
- * This class shall be extended by non-rewriting appenders; for rewriting, extend
- * {@link DefaultRewriteAuditAppender} instead.
- */
-public abstract class DefaultAuditAppender extends AbstractAuditAppender {
-
-    @Override
-    public void init() {
-        initTargetAppender();
-    }
+@Component
+public class LoggerDataBinderImpl implements LoggerDataBinder {
 
     @Override
-    public Set<AuditLoggerName> getEvents() {
-        return Set.of();
+    public LoggerTO getLoggerTO(final Logger logger) {
+        LoggerTO loggerTO = new LoggerTO();
+        loggerTO.setKey(logger.getKey());
+        loggerTO.setLevel(logger.getLevel());
+        return loggerTO;
     }
 
     @Override
-    public void initRewriteAppender() {
+    public LoggerTO getLoggerTO(final AuditLoggerName auditLoggerName) {
+        LoggerTO loggerTO = new LoggerTO();
+        loggerTO.setKey(auditLoggerName.toLoggerName());
+        loggerTO.setLevel(LoggerLevel.DEBUG);
+        return loggerTO;
     }
-
-    @Override
-    public RewritePolicy getRewritePolicy() {
-        return null;
-    }
-
 }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
index a0632d4..7a67647 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
@@ -23,12 +23,11 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.sql.DataSource;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.report.AuditReportletConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.core.persistence.api.DomainHolder;
-import org.apache.syncope.core.persistence.api.dao.AuditDAO;
-import org.apache.syncope.core.persistence.api.entity.AuditEntry;
-import org.apache.syncope.core.provisioning.api.AuditEntryImpl;
+import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
@@ -49,17 +48,17 @@ public class AuditReportlet extends AbstractReportlet {
     private DataSource datasource;
 
     private void doExtractConf(final ContentHandler handler, final AtomicReference<String> status) throws SAXException {
-        status.set("Fetching " + conf.getSize() + " rows from the " + AuditDAO.TABLE + " table");
+        status.set("Fetching " + conf.getSize() + " rows from the " + LoggerDAO.AUDIT_TABLE + " table");
 
         JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
         jdbcTemplate.setMaxRows(conf.getSize());
         List<Map<String, Object>> rows = jdbcTemplate.
-                queryForList("SELECT * FROM " + AuditDAO.TABLE + " ORDER BY EVENT_DATE DESC");
+                queryForList("SELECT * FROM " + LoggerDAO.AUDIT_TABLE + " ORDER BY EVENT_DATE DESC");
 
         handler.startElement("", "", "events", null);
         AttributesImpl atts = new AttributesImpl();
         for (Map<String, Object> row : rows) {
-            AuditEntry auditEntry = POJOHelper.deserialize(row.get("MESSAGE").toString(), AuditEntryImpl.class);
+            AuditEntry auditEntry = POJOHelper.deserialize(row.get("MESSAGE").toString(), AuditEntry.class);
 
             atts.clear();
             if (StringUtils.isNotBlank(auditEntry.getWho())) {
@@ -94,12 +93,11 @@ public class AuditReportlet extends AbstractReportlet {
                 handler.endElement("", "", "before");
             }
 
-            if (auditEntry.getInput() != null) {
+            if (!auditEntry.getInputs().isEmpty()) {
                 handler.startElement("", "", "inputs", null);
-                for (Object inputObj : auditEntry.getInput()) {
-                    char[] input = POJOHelper.serialize(inputObj).toCharArray();
+                for (String input : auditEntry.getInputs()) {
                     handler.startElement("", "", "input", null);
-                    handler.characters(input, 0, input.length);
+                    handler.characters(input.toCharArray(), 0, input.length());
                     handler.endElement("", "", "input");
                 }
                 handler.endElement("", "", "inputs");
diff --git a/docker/core/src/main/resources/persistence.properties.all b/docker/core/src/main/resources/persistence.properties.all
index 583c689..4808aa0 100644
--- a/docker/core/src/main/resources/persistence.properties.all
+++ b/docker/core/src/main/resources/persistence.properties.all
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
 openjpa.RemoteCommitProvider=${OPENJPA_REMOTE_COMMIT}
diff --git a/docker/core/src/main/resources/persistence.properties.myjson b/docker/core/src/main/resources/persistence.properties.myjson
index dc034b6..20b19a8 100644
--- a/docker/core/src/main/resources/persistence.properties.myjson
+++ b/docker/core/src/main/resources/persistence.properties.myjson
@@ -25,5 +25,5 @@ user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
 conf.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONConfDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/docker/core/src/main/resources/persistence.properties.pgjsonb b/docker/core/src/main/resources/persistence.properties.pgjsonb
index fe9250c..238a10b 100644
--- a/docker/core/src/main/resources/persistence.properties.pgjsonb
+++ b/docker/core/src/main/resources/persistence.properties.pgjsonb
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
 openjpa.RemoteCommitProvider=${OPENJPA_REMOTE_COMMIT}
diff --git a/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties b/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
index 82b0b51..6a968d8 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
+++ b/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
index 0f9fa20..6398777 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
@@ -35,46 +35,41 @@ public class SyslogRewriteAuditAppender extends DefaultRewriteAuditAppender {
     @Override
     public Set<AuditLoggerName> getEvents() {
         Set<AuditLoggerName> events = new HashSet<>();
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ResourceLogic.class.getSimpleName(),
-                        null,
-                        "update",
-                        AuditElements.Result.SUCCESS));
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ConnectorLogic.class.getSimpleName(),
-                        null,
-                        "update",
-                        AuditElements.Result.SUCCESS));
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ResourceLogic.class.getSimpleName(),
-                        null,
-                        "delete",
-                        AuditElements.Result.SUCCESS));
+        events.add(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ResourceLogic.class.getSimpleName(),
+                null,
+                "update",
+                AuditElements.Result.SUCCESS));
+        events.add(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ConnectorLogic.class.getSimpleName(),
+                null,
+                "update",
+                AuditElements.Result.SUCCESS));
+        events.add(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ResourceLogic.class.getSimpleName(),
+                null,
+                "delete",
+                AuditElements.Result.SUCCESS));
         return events;
     }
 
     @Override
-    public void initTargetAppender() {
+    protected void initTargetAppender() {
         targetAppender = SyslogAppender.newSyslogAppenderBuilder().
                 setName(getTargetAppenderName()).
                 withHost("localhost").
                 withPort(514).
                 withProtocol(Protocol.UDP).
-                setLayout(PatternLayout.newBuilder().
-                        withPattern("%d{ISO8601} %-5level %logger - %msg%n").
-                        build()).
+                setLayout(PatternLayout.newBuilder().withPattern("%d{ISO8601} %-5level %logger - %msg%n").build()).
                 setFacility(Facility.LOCAL1).
                 build();
     }
 
     @Override
     public String getTargetAppenderName() {
-        return "audit_for_" + domainName + "_syslog";
+        return "audit_for_" + domain + "_syslog";
     }
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
index cc9cd3e..ca508f7 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
@@ -38,25 +38,23 @@ public class TestFileAuditAppender extends DefaultAuditAppender {
     @Override
     public Set<AuditLoggerName> getEvents() {
         Set<AuditLoggerName> events = new HashSet<>();
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ResourceLogic.class.getSimpleName(),
-                        null,
-                        "create",
-                        AuditElements.Result.SUCCESS));
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ConnectorLogic.class.getSimpleName(),
-                        null,
-                        "update",
-                        AuditElements.Result.SUCCESS));
+        events.add(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ResourceLogic.class.getSimpleName(),
+                null,
+                "create",
+                AuditElements.Result.SUCCESS));
+        events.add(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ConnectorLogic.class.getSimpleName(),
+                null,
+                "update",
+                AuditElements.Result.SUCCESS));
         return events;
     }
 
     @Override
-    public void initTargetAppender() {
+    protected void initTargetAppender() {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
         // get log file path from existing file appender
         RollingRandomAccessFileAppender mainFile =
@@ -79,6 +77,6 @@ public class TestFileAuditAppender extends DefaultAuditAppender {
 
     @Override
     public String getTargetAppenderName() {
-        return "audit_for_" + domainName + "_norewrite_file";
+        return "audit_for_" + domain + "_norewrite_file";
     }
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
index 8ce0d99..9741a29 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
@@ -36,19 +36,16 @@ public class TestFileRewriteAuditAppender extends DefaultRewriteAuditAppender {
 
     @Override
     public Set<AuditLoggerName> getEvents() {
-        Set<AuditLoggerName> events = new HashSet<>();
-        events.add(
-                new AuditLoggerName(
-                        AuditElements.EventCategoryType.LOGIC,
-                        ResourceLogic.class.getSimpleName(),
-                        null,
-                        "update",
-                        AuditElements.Result.SUCCESS));
-        return events;
+        return Collections.singleton(new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ResourceLogic.class.getSimpleName(),
+                null,
+                "update",
+                AuditElements.Result.SUCCESS));
     }
 
     @Override
-    public void initTargetAppender() {
+    protected void initTargetAppender() {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
 
         // get log file path from existing file appender
@@ -68,11 +65,11 @@ public class TestFileRewriteAuditAppender extends DefaultRewriteAuditAppender {
 
     @Override
     public String getTargetAppenderName() {
-        return "audit_for_" + domainName + "_file";
+        return "audit_for_" + domain + "_file";
     }
 
     @Override
-    public RewritePolicy getRewritePolicy() {
+    protected RewritePolicy getRewritePolicy() {
         return TestRewritePolicy.createPolicy();
     }
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestRewritePolicy.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestRewritePolicy.java
index 641f203..2cb724b 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestRewritePolicy.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestRewritePolicy.java
@@ -25,14 +25,10 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.status.StatusLogger;
 
-@Plugin(name = "TestRewritePolicy", category = Core.CATEGORY_NAME, elementType = "rewritePolicy",
-        printObject = true)
+@Plugin(name = "TestRewritePolicy", category = Core.CATEGORY_NAME, elementType = "rewritePolicy", printObject = true)
 public class TestRewritePolicy implements RewritePolicy {
 
-    protected static final StatusLogger LOGGER = StatusLogger.getLogger();
-
     @Override
     public LogEvent rewrite(final LogEvent event) {
         return new Log4jLogEvent.Builder(event).setMessage(new SimpleMessage("This is a static test message")).build();
@@ -42,5 +38,4 @@ public class TestRewritePolicy implements RewritePolicy {
     public static TestRewritePolicy createPolicy() {
         return new TestRewritePolicy();
     }
-
 }
diff --git a/fit/core-reference/src/main/resources/elasticsearch/persistence.properties b/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
index 82b0b51..6a968d8 100644
--- a/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
+++ b/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/fit/core-reference/src/main/resources/logic.properties b/fit/core-reference/src/main/resources/logic.properties
index 54d7cdb..abab00d 100644
--- a/fit/core-reference/src/main/resources/logic.properties
+++ b/fit/core-reference/src/main/resources/logic.properties
@@ -18,3 +18,4 @@ version=${syncope.version}
 buildNumber=${buildNumber}
 logicInvocationHandler=org.apache.syncope.core.logic.LogicInvocationHandler
 classPathScanImplementationLookup=org.apache.syncope.fit.core.reference.ITImplementationLookup
+enable.jdbcAuditAppender=true
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 d55090e..111690f 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
@@ -85,7 +85,6 @@ import org.apache.syncope.common.rest.api.service.AnyObjectService;
 import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
 import org.apache.syncope.common.rest.api.service.AnyTypeService;
 import org.apache.syncope.common.rest.api.service.ApplicationService;
-import org.apache.syncope.common.rest.api.service.AuditService;
 import org.apache.syncope.common.rest.api.service.CamelRouteService;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
 import org.apache.syncope.common.rest.api.service.DynRealmService;
@@ -287,8 +286,6 @@ public abstract class AbstractITCase {
 
     protected static SCIMConfService scimConfService;
 
-    protected static AuditService auditService;
-
     @BeforeAll
     public static void securitySetup() {
         try (InputStream propStream = Encryptor.class.getResourceAsStream("/security.properties")) {
@@ -358,7 +355,6 @@ public abstract class AbstractITCase {
         oidcClientService = adminClient.getService(OIDCClientService.class);
         oidcProviderService = adminClient.getService(OIDCProviderService.class);
         scimConfService = adminClient.getService(SCIMConfService.class);
-        auditService = adminClient.getService(AuditService.class);
     }
 
     @Autowired
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 866eb0b..7aa36ab 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
@@ -31,8 +31,8 @@ import java.util.Set;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
-import org.apache.syncope.common.lib.to.AuditEntryTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.PagedResult;
@@ -47,8 +47,8 @@ import org.junit.jupiter.api.Test;
 
 public class AuditITCase extends AbstractITCase {
 
-    private static AuditEntryTO query(final AuditQuery query, final int maxWaitSeconds, final boolean failIfEmpty) {
-        List<AuditEntryTO> results = query(query, maxWaitSeconds);
+    private static AuditEntry query(final AuditQuery query, final int maxWaitSeconds, final boolean failIfEmpty) {
+        List<AuditEntry> results = query(query, maxWaitSeconds);
         if (results.isEmpty()) {
             if (failIfEmpty) {
                 fail("Timeout when executing query for key " + query.getEntityKey());
@@ -58,15 +58,15 @@ public class AuditITCase extends AbstractITCase {
         return results.get(0);
     }
 
-    private static List<AuditEntryTO> query(final AuditQuery query, final int maxWaitSeconds) {
+    private static List<AuditEntry> query(final AuditQuery query, final int maxWaitSeconds) {
         int i = 0;
-        List<AuditEntryTO> results = List.of();
+        List<AuditEntry> results = List.of();
         do {
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
             }
-            results = auditService.search(query).getResult();
+            results = loggerService.search(query).getResult();
             i++;
         } while (results.isEmpty() && i < maxWaitSeconds);
         return results;
@@ -78,7 +78,7 @@ public class AuditITCase extends AbstractITCase {
         assertNotNull(userTO.getKey());
 
         AuditQuery query = new AuditQuery.Builder(userTO.getKey()).build();
-        List<AuditEntryTO> entries = query(query, MAX_WAIT_SECONDS);
+        List<AuditEntry> entries = query(query, MAX_WAIT_SECONDS);
         assertEquals(1, entries.size());
 
         PagedResult<UserTO> usersTOs = userService.search(
@@ -100,8 +100,8 @@ public class AuditITCase extends AbstractITCase {
 
         AuditQuery query = new AuditQuery.Builder(userTO.getKey()).orderBy("event_date desc").
                 page(1).size(1).build();
-        AuditEntryTO entry = query(query, MAX_WAIT_SECONDS, true);
-        assertEquals(userTO.getKey(), entry.getKey());
+        AuditEntry entry = query(query, MAX_WAIT_SECONDS, true);
+        assertNotNull(entry);
         userService.delete(userTO.getKey());
     }
 
@@ -119,8 +119,8 @@ public class AuditITCase extends AbstractITCase {
                 event("create").
                 result(AuditElements.Result.SUCCESS).
                 build();
-        AuditEntryTO entry = query(query, MAX_WAIT_SECONDS, true);
-        assertEquals(userTO.getKey(), entry.getKey());
+        AuditEntry entry = query(query, MAX_WAIT_SECONDS, true);
+        assertNotNull(entry);
         userService.delete(userTO.getKey());
     }
 
@@ -131,8 +131,8 @@ public class AuditITCase extends AbstractITCase {
 
         AuditQuery query = new AuditQuery.Builder(groupTO.getKey()).orderBy("event_date desc").
                 page(1).size(1).build();
-        AuditEntryTO entry = query(query, MAX_WAIT_SECONDS, true);
-        assertEquals(groupTO.getKey(), entry.getKey());
+        AuditEntry entry = query(query, MAX_WAIT_SECONDS, true);
+        assertNotNull(entry);
         groupService.delete(groupTO.getKey());
     }
 
@@ -142,7 +142,7 @@ public class AuditITCase extends AbstractITCase {
         assertNotNull(groupTO.getKey());
 
         AuditQuery query = new AuditQuery.Builder(groupTO.getKey()).build();
-        List<AuditEntryTO> entries = query(query, MAX_WAIT_SECONDS);
+        List<AuditEntry> entries = query(query, MAX_WAIT_SECONDS);
         assertEquals(1, entries.size());
 
         PagedResult<GroupTO> groups = groupService.search(
@@ -163,8 +163,8 @@ public class AuditITCase extends AbstractITCase {
         assertNotNull(anyObjectTO.getKey());
         AuditQuery query = new AuditQuery.Builder(anyObjectTO.getKey()).orderBy("event_date desc").
                 page(1).size(1).build();
-        AuditEntryTO entry = query(query, MAX_WAIT_SECONDS, true);
-        assertEquals(anyObjectTO.getKey(), entry.getKey());
+        AuditEntry entry = query(query, MAX_WAIT_SECONDS, true);
+        assertNotNull(entry);
         anyObjectService.delete(anyObjectTO.getKey());
     }
 
@@ -174,7 +174,7 @@ public class AuditITCase extends AbstractITCase {
         assertNotNull(anyObjectTO);
 
         AuditQuery query = new AuditQuery.Builder(anyObjectTO.getKey()).build();
-        List<AuditEntryTO> entries = query(query, MAX_WAIT_SECONDS);
+        List<AuditEntry> entries = query(query, MAX_WAIT_SECONDS);
         assertEquals(1, entries.size());
 
         PagedResult<AnyObjectTO> anyObjects = anyObjectService.search(
@@ -199,7 +199,7 @@ public class AuditITCase extends AbstractITCase {
                 event("update").
                 result(AuditElements.Result.SUCCESS).
                 build();
-        List<AuditEntryTO> entries = query(query, 0);
+        List<AuditEntry> entries = query(query, 0);
         int pre = entries.size();
 
         ConnInstanceTO ldapConn = connectorService.read(connectorKey, null);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
index 4d18370..7857c71 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
@@ -105,7 +105,6 @@ public class LoggerITCase extends AbstractITCase {
     @Test
     public void listAudits() throws ParseException {
         List<LoggerTO> audits = loggerService.list(LoggerType.AUDIT);
-
         assertNotNull(audits);
         assertFalse(audits.isEmpty());
         for (LoggerTO audit : audits) {
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
index c1128ff..6602420 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
@@ -91,7 +91,7 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
 ....
 
 In `provisioning.properties`, replace as follows:
@@ -224,7 +224,7 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditDAO
+logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
 ....
 
 In `provisioning.properties`, replace as follows:


[syncope] 02/02: Upgrading Elasticsearch and asciidoctorj-pdf

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit b865da03b49794c29000b22b43ba0d855274e84b
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Wed Feb 12 12:04:35 2020 +0100

    Upgrading Elasticsearch and asciidoctorj-pdf
---
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pom.xml b/pom.xml
index ca131bd..23ad894 100644
--- a/pom.xml
+++ b/pom.xml
@@ -432,7 +432,7 @@ under the License.
     <slf4j.version>1.7.30</slf4j.version>
     <opensaml.version>3.3.1</opensaml.version>
 
-    <elasticsearch.version>7.5.2</elasticsearch.version>
+    <elasticsearch.version>7.6.0</elasticsearch.version>
 
     <apacheds.version>2.0.0.AM25</apacheds.version>
     <apachedirapi.version>2.0.0.AM2</apachedirapi.version>
@@ -2463,7 +2463,7 @@ under the License.
             <link>https://docs.spring.io/spring-security/site/docs/current/api/</link>
             <link>http://www.flowable.org/docs/javadocs/</link>
             <link>https://build.shibboleth.net/nexus/content/sites/site/java-opensaml/3.3.1/apidocs/</link>
-            <link>https://artifacts.elastic.co/javadoc/org/elasticsearch/elasticsearch/7.5.2/index.html</link>
+            <link>https://artifacts.elastic.co/javadoc/org/elasticsearch/elasticsearch/7.6.0/index.html</link>
             <link>http://docs.swagger.io/swagger-core/v2.1.1/apidocs/</link>
           </links>
         </configuration>
@@ -2532,7 +2532,7 @@ under the License.
               <dependency>
                 <groupId>org.asciidoctor</groupId>
                 <artifactId>asciidoctorj-pdf</artifactId>
-                <version>1.5.0-rc.3</version>
+                <version>1.5.0</version>
               </dependency>
             </dependencies>
             <configuration>