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


The following commit(s) were added to refs/heads/master by this push:
     new 14dd110622 Fixing various quirks found while upgrading 3.0 projects 
(#1121)
14dd110622 is described below

commit 14dd1106220c4f126ee564f341dfcb77c7e7b7c4
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Jul 2 17:41:37 2025 +0200

    Fixing various quirks found while upgrading 3.0 projects (#1121)
---
 .../init/ClassPathScanImplementationLookup.java    |  6 +-
 .../syncope/client/console/pages/BasePage.html     |  2 +-
 .../client/enduser/pages/BaseReauthPage.java       |  6 +-
 .../apache/syncope/common/lib/to/SchedTaskTO.java  | 12 ---
 .../syncope/core/logic/AbstractJobLogic.java       | 76 ++++++++---------
 .../org/apache/syncope/core/logic/GroupLogic.java  |  2 +-
 .../org/apache/syncope/core/logic/ReportLogic.java | 10 +--
 .../org/apache/syncope/core/logic/TaskLogic.java   | 12 +--
 .../persistence/api/entity/task/SchedTask.java     |  5 --
 .../jpa/upgrade/GenerateUpgradeSQL.java            | 37 +++++++--
 .../jpa/dao/AbstractJPAAnySearchDAO.java           |  1 -
 .../jpa/entity/task/JPAPropagationTask.java        |  3 +-
 .../persistence/jpa/entity/task/JPASchedTask.java  | 13 ---
 .../neo4j/entity/task/Neo4jSchedTask.java          | 13 ---
 .../core/provisioning/api/job/JobManager.java      | 10 ++-
 .../provisioning/java/data/TaskDataBinderImpl.java |  1 -
 .../provisioning/java/job/DefaultJobManager.java   | 72 +++++++++++++---
 .../java/job/SyncopeTaskScheduler.java             | 96 ++++++++++++++--------
 .../pushpull/stream/StreamPullJobDelegate.java     |  1 +
 .../java/job/SyncopeTaskSchedulerTest.java         |  2 -
 .../client/ElasticsearchClientFactoryBean.java     |  2 +-
 .../dao/ElasticsearchAuditEventDAO.java            |  2 +-
 .../client/OpenSearchClientFactoryBean.java        |  2 +-
 .../opensearch/dao/OpenSearchAuditEventDAO.java    |  2 +-
 24 files changed, 223 insertions(+), 165 deletions(-)

diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
index a7a04597f7..67ffcd53ee 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
@@ -30,6 +30,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.ArrayUtils;
@@ -188,7 +189,10 @@ public class ClassPathScanImplementationLookup implements 
Serializable {
                 } else if (BasePage.class.isAssignableFrom(clazz)) {
                     if (clazz.isAnnotationPresent(IdMPage.class)) {
                         if (!clazz.getName().endsWith("Topology")
-                                || 
(clazz.getName().equals(props.getPage().get("topology").getName()))) {
+                                || 
Optional.ofNullable(props.getPage().get("topology")).
+                                        map(topologyClazz -> 
clazz.getName().equals(topologyClazz.getName())).
+                                        orElse(false)) {
+
                             idmPages.add((Class<? extends BasePage>) clazz);
                         }
                     } else if (clazz.isAnnotationPresent(AMPage.class)) {
diff --git 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
index 00dad85752..a0cd2c7791 100644
--- 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
+++ 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
@@ -41,7 +41,7 @@ under the License.
 
     <script type="text/javascript" 
src="webjars/bootbox/${bootbox.version}/dist/bootbox.all.min.js"></script>
     <script type="text/javascript" 
src="webjars/jQuery-slimScroll/${jquery-slimscroll.version}/jquery.slimscroll.min.js"></script>
-    <!--    bootstrap5-toogle-->
+    <!-- bootstrap5-toogle -->
     <link 
href="webjars/bootstrap5-toggle/${bootstrap5-toggle.version}/css/bootstrap5-toggle.min.css"
 rel="stylesheet" type="text/css" />
     <script type="text/javascript" 
src="webjars/bootstrap5-toggle/${bootstrap5-toggle.version}/js/bootstrap5-toggle.ecmas.min.js"></script>
     
diff --git 
a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseReauthPage.java
 
b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseReauthPage.java
index 8bc66fd30a..d151839fe9 100644
--- 
a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseReauthPage.java
+++ 
b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/pages/BaseReauthPage.java
@@ -38,13 +38,17 @@ abstract class BaseReauthPage extends BasePage {
             notification.add(Constants.NOTIFICATION_MSG_PARAM, 
getString("reauth.message"));
             notification.add(Constants.NOTIFICATION_LEVEL_PARAM, 
Notification.WARNING);
 
-            throw new 
RestartResponseAtInterceptPageException(ReauthLogin.class, notification);
+            throw new 
RestartResponseAtInterceptPageException(getReauthLoginPage(), notification);
         } else {
             SyncopeEnduserSession.get().clearLastReauth();
             LOG.debug("Re-authentication cleared");
         }
     }
 
+    protected Class<? extends ReauthLogin> getReauthLoginPage() {
+        return ReauthLogin.class;
+    }
+
     protected boolean isReauthExpired() {
         return SyncopeEnduserSession.get().isReauthExpired();
     }
diff --git 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
index cb3e47a658..0813f92d4a 100644
--- 
a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
+++ 
b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/SchedTaskTO.java
@@ -32,8 +32,6 @@ public class SchedTaskTO extends TaskTO implements 
NamedEntityTO {
 
     private static final long serialVersionUID = -5722284116974636425L;
 
-    private OffsetDateTime startAt;
-
     private String cronExpression;
 
     private String jobDelegate;
@@ -57,14 +55,6 @@ public class SchedTaskTO extends TaskTO implements 
NamedEntityTO {
         return getClass().getName();
     }
 
-    public OffsetDateTime getStartAt() {
-        return startAt;
-    }
-
-    public void setStartAt(final OffsetDateTime startAt) {
-        this.startAt = startAt;
-    }
-
     public String getCronExpression() {
         return cronExpression;
     }
@@ -130,7 +120,6 @@ public class SchedTaskTO extends TaskTO implements 
NamedEntityTO {
     public int hashCode() {
         return new HashCodeBuilder().
                 appendSuper(super.hashCode()).
-                append(startAt).
                 append(cronExpression).
                 append(jobDelegate).
                 append(name).
@@ -155,7 +144,6 @@ public class SchedTaskTO extends TaskTO implements 
NamedEntityTO {
         final SchedTaskTO other = (SchedTaskTO) obj;
         return new EqualsBuilder().
                 appendSuper(super.equals(obj)).
-                append(startAt, other.startAt).
                 append(cronExpression, other.cronExpression).
                 append(jobDelegate, other.jobDelegate).
                 append(name, other.name).
diff --git 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
index 0b2b756ed6..e32b9b0c43 100644
--- 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
+++ 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
@@ -60,40 +60,38 @@ abstract class AbstractJobLogic<T extends EntityTO> extends 
AbstractTransactiona
     protected Optional<JobTO> getJobTO(final String jobName, final boolean 
includeCustom) {
         JobTO jobTO = null;
 
-        if (scheduler.contains(AuthContextUtils.getDomain(), jobName)) {
-            Triple<JobType, String, String> reference = getReference(jobName);
-            if (reference != null) {
+        Triple<JobType, String, String> reference = getReference(jobName);
+        if (reference != null) {
+            jobTO = new JobTO();
+            jobTO.setType(reference.getLeft());
+            jobTO.setRefKey(reference.getMiddle());
+            jobTO.setRefDesc(reference.getRight());
+        } else if (includeCustom) {
+            Optional<Class<?>> jobClass = 
scheduler.getJobClass(AuthContextUtils.getDomain(), jobName).
+                    filter(jc -> !TaskJob.class.isAssignableFrom(jc)
+                    && !ReportJob.class.isAssignableFrom(jc)
+                    && !SystemLoadReporterJob.class.isAssignableFrom(jc)
+                    && !NotificationJob.class.isAssignableFrom(jc));
+            if (jobClass.isPresent()) {
                 jobTO = new JobTO();
-                jobTO.setType(reference.getLeft());
-                jobTO.setRefKey(reference.getMiddle());
-                jobTO.setRefDesc(reference.getRight());
-            } else if (includeCustom) {
-                Optional<Class<?>> jobClass = 
scheduler.getJobClass(AuthContextUtils.getDomain(), jobName).
-                        filter(jc -> !TaskJob.class.isAssignableFrom(jc)
-                        && !ReportJob.class.isAssignableFrom(jc)
-                        && !SystemLoadReporterJob.class.isAssignableFrom(jc)
-                        && !NotificationJob.class.isAssignableFrom(jc));
-                if (jobClass.isPresent()) {
-                    jobTO = new JobTO();
-                    jobTO.setType(JobType.CUSTOM);
-                    jobTO.setRefKey(jobName);
-                    jobTO.setRefDesc(jobClass.get().getName());
-                }
+                jobTO.setType(JobType.CUSTOM);
+                jobTO.setRefKey(jobName);
+                jobTO.setRefDesc(jobClass.get().getName());
             }
+        }
 
-            if (jobTO != null) {
-                Optional<OffsetDateTime> nextTrigger = 
scheduler.getNextTrigger(AuthContextUtils.getDomain(), jobName);
-                if (nextTrigger.isPresent()) {
-                    jobTO.setScheduled(true);
-                    jobTO.setStart(nextTrigger.get());
-                } else {
-                    jobTO.setScheduled(false);
-                }
+        if (jobTO != null) {
+            Optional<OffsetDateTime> nextTrigger = 
scheduler.getNextTrigger(AuthContextUtils.getDomain(), jobName);
+            if (nextTrigger.isPresent()) {
+                jobTO.setScheduled(true);
+                jobTO.setStart(nextTrigger.get());
+            } else {
+                jobTO.setScheduled(false);
+            }
 
-                jobTO.setRunning(jobManager.isRunning(jobName));
+            jobTO.setRunning(jobManager.isRunning(jobName));
 
-                
jobTO.setStatus(jobStatusDAO.findById(jobName).map(JobStatus::getStatus).orElse("UNKNOWN"));
-            }
+            
jobTO.setStatus(jobStatusDAO.findById(jobName).map(JobStatus::getStatus).orElse("UNKNOWN"));
         }
 
         return Optional.ofNullable(jobTO);
@@ -109,22 +107,18 @@ abstract class AbstractJobLogic<T extends EntityTO> 
extends AbstractTransactiona
     }
 
     protected void doActionJob(final String jobName, final JobAction action) {
-        if (scheduler.contains(AuthContextUtils.getDomain(), jobName)) {
-            switch (action) {
-                case START ->
-                    scheduler.start(AuthContextUtils.getDomain(), jobName);
+        switch (action) {
+            case START ->
+                scheduler.start(AuthContextUtils.getDomain(), jobName);
 
-                case STOP ->
-                    scheduler.cancel(AuthContextUtils.getDomain(), jobName);
+            case STOP ->
+                scheduler.stop(AuthContextUtils.getDomain(), jobName);
 
-                case DELETE ->
-                    scheduler.delete(AuthContextUtils.getDomain(), jobName);
+            case DELETE ->
+                scheduler.delete(AuthContextUtils.getDomain(), jobName);
 
-                default -> {
-                }
+            default -> {
             }
-        } else {
-            LOG.warn("Could not find job {}", jobName);
         }
     }
 }
diff --git 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index ba8631710d..b67e0e0b3a 100644
--- 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -427,7 +427,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, 
GroupCR, GroupUR> {
         task = taskDAO.save(task);
 
         try {
-            jobManager.register(
+            jobManager.execute(
                     task,
                     OffsetDateTime.now().plusSeconds(1),
                     AuthContextUtils.getUsername(),
diff --git 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
index 363f213bbe..db89032988 100644
--- 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
+++ 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
@@ -96,9 +96,7 @@ public class ReportLogic extends 
AbstractExecutableLogic<ReportTO> {
         try {
             jobManager.register(
                     report,
-                    null,
-                    AuthContextUtils.getUsername(),
-                    false);
+                    AuthContextUtils.getUsername());
         } catch (Exception e) {
             LOG.error("While registering job for report {}", report.getKey(), 
e);
 
@@ -120,9 +118,7 @@ public class ReportLogic extends 
AbstractExecutableLogic<ReportTO> {
         try {
             jobManager.register(
                     report,
-                    null,
-                    AuthContextUtils.getUsername(),
-                    false);
+                    AuthContextUtils.getUsername());
         } catch (Exception e) {
             LOG.error("While registering job for report {}", report.getKey(), 
e);
 
@@ -167,7 +163,7 @@ public class ReportLogic extends 
AbstractExecutableLogic<ReportTO> {
         }
 
         try {
-            jobManager.register(
+            jobManager.execute(
                     report,
                     
Optional.ofNullable(specs.getStartAt()).orElseGet(OffsetDateTime::now),
                     AuthContextUtils.getUsername(),
diff --git 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
index dbfba31b4f..1c6ee6b09d 100644
--- 
a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
+++ 
b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
@@ -153,10 +153,7 @@ public class TaskLogic extends 
AbstractExecutableLogic<TaskTO> {
         try {
             jobManager.register(
                     task,
-                    task.getStartAt(),
-                    AuthContextUtils.getUsername(),
-                    false,
-                    Map.of());
+                    AuthContextUtils.getUsername());
         } catch (Exception e) {
             LOG.error("While registering job for task {}", task.getKey(), e);
 
@@ -190,10 +187,7 @@ public class TaskLogic extends 
AbstractExecutableLogic<TaskTO> {
         try {
             jobManager.register(
                     task,
-                    task.getStartAt(),
-                    AuthContextUtils.getUsername(),
-                    false,
-                    Map.of());
+                    AuthContextUtils.getUsername());
         } catch (Exception e) {
             LOG.error("While registering job for task {}", task.getKey(), e);
 
@@ -346,7 +340,7 @@ public class TaskLogic extends 
AbstractExecutableLogic<TaskTO> {
                 }
 
                 try {
-                    jobManager.register(
+                    jobManager.execute(
                             (SchedTask) task,
                             
Optional.ofNullable(startAt).orElseGet(OffsetDateTime::now),
                             executor,
diff --git 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
index dd48029419..0635efc505 100644
--- 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
+++ 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/SchedTask.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.persistence.api.entity.task;
 
-import java.time.OffsetDateTime;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public interface SchedTask extends Task<SchedTask> {
@@ -35,10 +34,6 @@ public interface SchedTask extends Task<SchedTask> {
 
     Implementation getJobDelegate();
 
-    OffsetDateTime getStartAt();
-
-    void setStartAt(OffsetDateTime startAt);
-
     void setCronExpression(String cronExpression);
 
     String getCronExpression();
diff --git 
a/core/persistence-jpa-upgrader/src/main/java/org/apache/syncope/core/persistence/jpa/upgrade/GenerateUpgradeSQL.java
 
b/core/persistence-jpa-upgrader/src/main/java/org/apache/syncope/core/persistence/jpa/upgrade/GenerateUpgradeSQL.java
index 0f9f7a7a64..1122fe4693 100644
--- 
a/core/persistence-jpa-upgrader/src/main/java/org/apache/syncope/core/persistence/jpa/upgrade/GenerateUpgradeSQL.java
+++ 
b/core/persistence-jpa-upgrader/src/main/java/org/apache/syncope/core/persistence/jpa/upgrade/GenerateUpgradeSQL.java
@@ -171,12 +171,10 @@ public class GenerateUpgradeSQL {
         List<Map<String, Object>> dynMembershipConds = 
jdbcTemplate.queryForList(
                 "SELECT role_id AS id, fiql FROM DynRoleMembership");
 
-        dynMembershipConds.forEach(cond -> {
-            result.append(String.format(
-                    "UPDATE SyncopeRole SET dynMembershipCond='%s' WHERE 
id='%s';\n",
-                    cond.get("fiql").toString(),
-                    cond.get("id").toString()));
-        });
+        dynMembershipConds.forEach(cond -> result.append(String.format(
+                "UPDATE SyncopeRole SET dynMembershipCond='%s' WHERE 
id='%s';\n",
+                cond.get("fiql").toString(),
+                cond.get("id").toString())));
 
         result.append("DROP TABLE DynRoleMembership;\n");
 
@@ -233,6 +231,31 @@ public class GenerateUpgradeSQL {
         return result.toString();
     }
 
+    private String implementations() {
+        StringBuilder result = new StringBuilder();
+
+        result.append("UPDATE Implementation ").
+                append("SET type='INBOUND_ACTIONS' WHERE 
type='PULL_ACTIONS';\n");
+        result.append("UPDATE Implementation ").
+                append("SET type='INBOUND_CORRELATION_RULE' WHERE 
type='PULL_CORRELATION_RULE';\n\n");
+
+        return result.toString();
+    }
+
+    private String audit() {
+        StringBuilder result = new StringBuilder();
+
+        List<Map<String, Object>> auditConf = jdbcTemplate.queryForList(
+                "SELECT id from AuditConf");
+
+        auditConf.forEach(conf -> result.append(String.format(
+                "UPDATE SyncopeRole SET id='%s' WHERE id='%s';\n",
+                conf.get("id").toString().replace("syncope.audit.", ""),
+                conf.get("id").toString())));
+
+        return result.toString();
+    }
+
     public void run(final Writer out) throws IOException, SQLException {
         INIT_SQL_STATEMENTS.forEach(jdbcTemplate::execute);
 
@@ -249,6 +272,8 @@ public class GenerateUpgradeSQL {
             out.append(plainSchemas());
             out.append(roles());
             out.append(relationshipTypes());
+            out.append(implementations());
+            out.append(audit());
 
             out.append(FINAL_SQL_STATEMENTS);
         }
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
index 1932975e8c..c9f23fab57 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAAnySearchDAO.java
@@ -163,7 +163,6 @@ abstract class AbstractJPAAnySearchDAO extends 
AbstractAnySearchDAO {
 
     protected String anyId(final SearchSupport svs) {
         return anyId(defaultSV(svs));
-
     }
 
     protected Optional<AnySearchNode> getQueryForCustomConds(
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
index 6616d67ed6..f0eee0b2e1 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
@@ -22,6 +22,7 @@ import jakarta.persistence.CascadeType;
 import jakarta.persistence.Entity;
 import jakarta.persistence.EnumType;
 import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
 import jakarta.persistence.Lob;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.OneToMany;
@@ -88,7 +89,7 @@ public class JPAPropagationTask extends 
AbstractTask<PropagationTask> implements
     @ManyToOne
     private JPAExternalResource resource;
 
-    @OneToMany(targetEntity = JPAPropagationTaskExec.class,
+    @OneToMany(targetEntity = JPAPropagationTaskExec.class, fetch = 
FetchType.EAGER,
             cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "task")
     private List<TaskExec<PropagationTask>> executions = new ArrayList<>();
 
diff --git 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
index df564d1233..2dc005cb51 100644
--- 
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
+++ 
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
@@ -27,7 +27,6 @@ import jakarta.persistence.OneToMany;
 import jakarta.persistence.OneToOne;
 import jakarta.persistence.Table;
 import jakarta.validation.constraints.NotNull;
-import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
@@ -50,8 +49,6 @@ public class JPASchedTask extends AbstractTask<SchedTask> 
implements SchedTask {
     @OneToOne(optional = false)
     private JPAImplementation jobDelegate;
 
-    private OffsetDateTime startAt;
-
     private String cronExpression;
 
     @Column(unique = true, nullable = false)
@@ -78,16 +75,6 @@ public class JPASchedTask extends AbstractTask<SchedTask> 
implements SchedTask {
         this.jobDelegate = (JPAImplementation) jobDelegate;
     }
 
-    @Override
-    public OffsetDateTime getStartAt() {
-        return startAt;
-    }
-
-    @Override
-    public void setStartAt(final OffsetDateTime startAt) {
-        this.startAt = startAt;
-    }
-
     @Override
     public String getCronExpression() {
         return cronExpression;
diff --git 
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java
 
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java
index f73ebbe4a8..0ab97e5307 100644
--- 
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java
+++ 
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/task/Neo4jSchedTask.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.neo4j.entity.task;
 
 import jakarta.validation.constraints.NotNull;
-import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
@@ -47,8 +46,6 @@ public class Neo4jSchedTask extends AbstractTask<SchedTask> 
implements SchedTask
     @Relationship(type = SCHED_TASK_JOB_DELEGATE_REL, direction = 
Relationship.Direction.OUTGOING)
     private Neo4jImplementation jobDelegate;
 
-    private OffsetDateTime startAt;
-
     private String cronExpression;
 
     @NotNull
@@ -74,16 +71,6 @@ public class Neo4jSchedTask extends AbstractTask<SchedTask> 
implements SchedTask
         this.jobDelegate = (Neo4jImplementation) jobDelegate;
     }
 
-    @Override
-    public OffsetDateTime getStartAt() {
-        return startAt;
-    }
-
-    @Override
-    public void setStartAt(final OffsetDateTime startAt) {
-        this.startAt = startAt;
-    }
-
     @Override
     public String getCronExpression() {
         return cronExpression;
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
index 25323e47fd..79716df613 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/job/JobManager.java
@@ -39,7 +39,7 @@ public interface JobManager {
 
     boolean isRunning(String jobName);
 
-    void register(
+    void execute(
             SchedTask task,
             OffsetDateTime startAt,
             String executor,
@@ -47,11 +47,19 @@ public interface JobManager {
             Map<String, Object> jobData);
 
     void register(
+            SchedTask task,
+            String executor);
+
+    void execute(
             Report report,
             OffsetDateTime startAt,
             String executor,
             boolean dryRun);
 
+    void register(
+            Report report,
+            String executor);
+
     void unregister(Task<?> task);
 
     void unregister(Report report);
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index ca0124b2d8..5864b17575 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -361,7 +361,6 @@ public class TaskDataBinderImpl extends 
AbstractExecutableDatabinder implements
         }
 
         SchedTask task = taskUtils.newTask();
-        task.setStartAt(taskTO.getStartAt());
         task.setCronExpression(taskTO.getCronExpression());
         task.setName(taskTO.getName());
         task.setDescription(taskTO.getDescription());
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
index 42c62ecee7..535fa304df 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/DefaultJobManager.java
@@ -123,9 +123,6 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
             return;
         }
 
-        // 0. unregister job
-        unregisterJob(context.getJobName());
-
         // 1. prepare job
         Job job = 
ApplicationContextProvider.getBeanFactory().createBean(jobClass);
         job.setContext(context);
@@ -145,6 +142,7 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
     protected void register(
             final String domain,
             final SchedTask task,
+            final String cronExpression,
             final OffsetDateTime startAt,
             final String executor,
             final boolean dryRun,
@@ -179,24 +177,47 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
         registerJob(
                 context,
                 TaskJob.class,
-                task.getCronExpression(),
+                cronExpression,
                 startAt);
     }
 
     @Override
-    public void register(
+    public void execute(
             final SchedTask task,
             final OffsetDateTime startAt,
             final String executor,
             final boolean dryRun,
             final Map<String, Object> jobData) {
 
-        register(AuthContextUtils.getDomain(), task, startAt, executor, 
dryRun, jobData);
+        register(
+                AuthContextUtils.getDomain(),
+                task,
+                null,
+                startAt,
+                executor,
+                dryRun,
+                jobData);
+    }
+
+    @Override
+    public void register(
+            final SchedTask task,
+            final String executor) {
+
+        register(
+                AuthContextUtils.getDomain(),
+                task,
+                task.getCronExpression(),
+                null,
+                executor,
+                false,
+                Map.of());
     }
 
     protected void register(
             final String domain,
             final Report report,
+            final String cronExpression,
             final OffsetDateTime startAt,
             final String executor,
             final boolean dryRun) {
@@ -212,22 +233,36 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
         registerJob(
                 context,
                 ReportJob.class,
-                report.getCronExpression(),
+                cronExpression,
                 startAt);
     }
 
     @Override
-    public void register(
+    public void execute(
             final Report report,
             final OffsetDateTime startAt,
             final String executor,
             final boolean dryRun) {
 
-        register(AuthContextUtils.getDomain(), report, startAt, executor, 
dryRun);
+        register(
+                AuthContextUtils.getDomain(),
+                report,
+                null,
+                startAt,
+                executor,
+                dryRun);
+    }
+
+    @Override
+    public void register(
+            final Report report,
+            final String executor) {
+
+        register(AuthContextUtils.getDomain(), report, 
report.getCronExpression(), null, executor, false);
     }
 
     protected void unregisterJob(final String jobName) {
-        scheduler.cancel(AuthContextUtils.getDomain(), jobName);
+        scheduler.stop(AuthContextUtils.getDomain(), jobName);
         scheduler.delete(AuthContextUtils.getDomain(), jobName);
     }
 
@@ -265,7 +300,14 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
                         taskUtilsFactory.getInstance(task).getType(), 
task.getKey(), task.getName());
 
                 try {
-                    register(domain, task, task.getStartAt(), 
securityProperties.getAdminUser(), false, Map.of());
+                    register(
+                            domain,
+                            task,
+                            task.getCronExpression(),
+                            null,
+                            securityProperties.getAdminUser(),
+                            false,
+                            Map.of());
                 } catch (Exception e) {
                     LOG.error("While loading job instance for task {}", 
task.getKey(), e);
                     loadException = true;
@@ -282,7 +324,13 @@ public class DefaultJobManager implements JobManager, 
SyncopeCoreLoader {
                     LOG.debug("Loading job for Report {} {}", report.getKey(), 
report.getName());
 
                     try {
-                        register(domain, report, null, 
securityProperties.getAdminUser(), false);
+                        register(
+                                domain,
+                                report,
+                                report.getCronExpression(),
+                                null,
+                                securityProperties.getAdminUser(),
+                                false);
                     } catch (Exception e) {
                         LOG.error("While loading job instance for report {}", 
report.getName(), e);
                         loadException = true;
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskScheduler.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskScheduler.java
index dbcd1ffe06..804a0323ed 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskScheduler.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskScheduler.java
@@ -27,8 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang3.tuple.MutablePair;
-import org.apache.commons.lang3.tuple.Pair;
+import java.util.function.Function;
 import org.apache.syncope.core.persistence.api.dao.JobStatusDAO;
 import 
org.apache.syncope.core.provisioning.api.job.StoppableSchedTaskJobDelegate;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
@@ -40,6 +39,14 @@ import org.springframework.scheduling.support.CronTrigger;
 
 public class SyncopeTaskScheduler {
 
+    protected record Key(String domain, String job) {
+
+    }
+
+    protected record Value(Job job, Optional<ScheduledFuture<?>> instant, 
Optional<ScheduledFuture<?>> cron) {
+
+    }
+
     public static final String CACHE = "jobCache";
 
     protected static final Logger LOG = 
LoggerFactory.getLogger(SyncopeTaskScheduler.class);
@@ -48,45 +55,53 @@ public class SyncopeTaskScheduler {
 
     protected final JobStatusDAO jobStatusDAO;
 
-    protected final Map<Pair<String, String>, Pair<Job, 
Optional<ScheduledFuture<?>>>> jobs = new ConcurrentHashMap<>();
+    protected final Map<Key, Value> jobs = new ConcurrentHashMap<>();
 
     public SyncopeTaskScheduler(final TaskScheduler scheduler, final 
JobStatusDAO jobStatusDAO) {
         this.scheduler = scheduler;
         this.jobStatusDAO = jobStatusDAO;
     }
 
-    protected void register(final Job job, final Optional<ScheduledFuture<?>> 
future) {
-        jobs.computeIfAbsent(
-                Pair.of(job.getContext().getDomain(), 
job.getContext().getJobName()),
-            k -> MutablePair.of(job, future));
-    }
+    protected void register(final Job job, final ScheduledFuture<?> instant, 
final ScheduledFuture<?> cron) {
+        Key key = new Key(job.getContext().getDomain(), 
job.getContext().getJobName());
 
-    public void register(final Job job) {
-        register(job, Optional.empty());
+        stop(key, instant == null ? List.of(Value::cron) : 
List.of(Value::instant));
+        AuthContextUtils.runAsAdmin(key.domain(), () -> 
jobStatusDAO.unlock(key.job()));
+
+        jobs.merge(
+                key,
+                new Value(job, Optional.ofNullable(instant), 
Optional.ofNullable(cron)),
+                (prev, value) -> new Value(
+                        job,
+                        value.instant().isEmpty() ? prev.instant() : 
value.instant(),
+                        value.cron().isEmpty() ? prev.cron() : value.cron()));
     }
 
-    public void schedule(final Job job, final CronTrigger trigger) {
-        register(job, Optional.of(scheduler.schedule(job, trigger)));
+    public void register(final Job job) {
+        register(job, null, null);
     }
 
     public void schedule(final Job job, final Instant startTime) {
-        register(job, Optional.of(scheduler.schedule(job, startTime)));
+        register(job, scheduler.schedule(job, startTime), null);
     }
 
-    public boolean contains(final String domain, final String jobName) {
-        return jobs.containsKey(Pair.of(domain, jobName));
+    public void schedule(final Job job, final CronTrigger trigger) {
+        register(job, null, scheduler.schedule(job, trigger));
     }
 
     public void start(final String domain, final String jobName) {
-        Optional.ofNullable(jobs.get(Pair.of(domain, jobName))).
-                filter(pair -> 
pair.getRight().map(Future::isDone).orElse(true)).
-                ifPresent(pair -> 
pair.setValue(Optional.of(scheduler.schedule(pair.getLeft(), Instant.now()))));
+        Optional.ofNullable(jobs.get(new Key(domain, jobName))).
+                filter(value -> 
value.instant().map(Future::isDone).orElse(true)).
+                ifPresent(value -> register(
+                value.job(),
+                scheduler.schedule(value.job(), Instant.now()),
+                value.cron().orElse(null)));
     }
 
-    public void cancel(final String domain, final String jobName) {
-        Optional.ofNullable(jobs.get(Pair.of(domain, jobName))).ifPresent(pair 
-> {
+    protected void stop(final Key key, final List<Function<Value, 
Optional<ScheduledFuture<?>>>> suppliers) {
+        Optional.ofNullable(jobs.get(key)).ifPresent(value -> {
             boolean mayInterruptIfRunning;
-            if (pair.getLeft() instanceof TaskJob taskJob
+            if (value.job() instanceof TaskJob taskJob
                     && taskJob.getDelegate() instanceof 
StoppableSchedTaskJobDelegate stoppable) {
 
                 stoppable.stop();
@@ -95,31 +110,46 @@ public class SyncopeTaskScheduler {
                 mayInterruptIfRunning = true;
             }
 
-            pair.getRight().ifPresent(f -> f.cancel(mayInterruptIfRunning));
-            pair.setValue(Optional.empty());
+            suppliers.forEach(s -> s.apply(value).ifPresent(f -> 
f.cancel(mayInterruptIfRunning)));
         });
     }
 
+    public void stop(final String domain, final String jobName) {
+        stop(new Key(domain, jobName), List.of(Value::instant, Value::cron));
+    }
+
     public void delete(final String domain, final String jobName) {
-        jobs.remove(Pair.of(domain, jobName));
+        jobs.remove(new Key(domain, jobName));
         AuthContextUtils.runAsAdmin(domain, () -> 
jobStatusDAO.unlock(jobName));
     }
 
     public Optional<Class<?>> getJobClass(final String domain, final String 
jobName) {
-        return Optional.ofNullable(jobs.get(Pair.of(domain, jobName))).
-                map(pair -> AopUtils.getTargetClass(pair.getLeft()));
+        return Optional.ofNullable(jobs.get(new Key(domain, jobName))).
+                map(value -> AopUtils.getTargetClass(value.job()));
     }
 
     public Optional<OffsetDateTime> getNextTrigger(final String domain, final 
String jobName) {
-        return Optional.ofNullable(jobs.get(Pair.of(domain, jobName))).
-                filter(pair -> pair.getRight().map(f -> 
!f.isDone()).orElse(false)).
-                flatMap(Pair::getRight).
-                map(f -> f.getDelay(TimeUnit.SECONDS)).
-                filter(delay -> delay > 0).
-                map(delay -> OffsetDateTime.now().plusSeconds(delay));
+        Value value = jobs.get(new Key(domain, jobName));
+        if (value == null) {
+            return Optional.empty();
+        }
+
+        ScheduledFuture<?> future = value.cron().filter(f -> 
!f.isDone()).orElse(null);
+        if (future == null) {
+            future = value.instant().filter(f -> !f.isDone()).orElse(null);
+        }
+        if (future == null) {
+            return Optional.empty();
+        }
+
+        long delay = future.getDelay(TimeUnit.SECONDS);
+        if (delay > 0) {
+            return Optional.of(OffsetDateTime.now().plusSeconds(delay));
+        }
+        return Optional.empty();
     }
 
     public List<String> getJobNames(final String domain) {
-        return jobs.keySet().stream().filter(pair -> 
domain.equals(pair.getLeft())).map(Pair::getRight).toList();
+        return jobs.keySet().stream().filter(key -> 
domain.equals(key.domain())).map(Key::job).toList();
     }
 }
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/StreamPullJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/StreamPullJobDelegate.java
index 12b4231212..a515e2fd94 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/StreamPullJobDelegate.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/stream/StreamPullJobDelegate.java
@@ -197,6 +197,7 @@ public class StreamPullJobDelegate extends PullJobDelegate 
implements SyncopeStr
                 action.beforeAll(profile);
             }
 
+            ghandler = buildGroupHandler();
             dispatcher.addHandlerSupplier(provision.getObjectClass(), () -> {
                 SyncopePullResultHandler handler;
                 switch (anyType.getKind()) {
diff --git 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskSchedulerTest.java
 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskSchedulerTest.java
index 2882d5527c..c2bcf3ae09 100644
--- 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskSchedulerTest.java
+++ 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/job/SyncopeTaskSchedulerTest.java
@@ -73,8 +73,6 @@ public class SyncopeTaskSchedulerTest extends AbstractTest {
 
         scheduler.schedule(job, Instant.now().plusSeconds(5));
 
-        assertTrue(scheduler.contains(AuthContextUtils.getDomain(), 
job.getContext().getJobName()));
-
         assertTrue(scheduler.getNextTrigger(AuthContextUtils.getDomain(), 
job.getContext().getJobName()).isPresent());
 
         await().atMost(10, TimeUnit.SECONDS).pollInterval(1, 
TimeUnit.SECONDS).until(() -> VALUE.getValue() == 1);
diff --git 
a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
 
b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
index 9377b0cf9e..4c35e78523 100644
--- 
a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
+++ 
b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchClientFactoryBean.java
@@ -101,7 +101,7 @@ public class ElasticsearchClientFactoryBean implements 
FactoryBean<Elasticsearch
                     String encodedAuth = Base64.getEncoder().
                             encodeToString((username + ":" + 
password).getBytes(StandardCharsets.UTF_8));
                     builder.setDefaultHeaders(
-                            new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + encodedAuth) });
+                            new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth) });
                 } else if (serviceToken != null) {
                     builder.setDefaultHeaders(
                             new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + serviceToken) });
diff --git 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
index e7c3c5f7f9..567fd9971a 100644
--- 
a/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
+++ 
b/ext/elasticsearch/persistence/src/main/java/org/apache/syncope/core/persistence/elasticsearch/dao/ElasticsearchAuditEventDAO.java
@@ -153,7 +153,7 @@ public class ElasticsearchAuditEventDAO implements 
AuditEventDAO {
     protected List<SortOptions> sortBuilders(final Stream<Sort.Order> orderBy) 
{
         return orderBy.map(clause -> new SortOptions.Builder().field(
                 new FieldSort.Builder().
-                        field(clause.getProperty()).
+                        field("id".equals(clause.getProperty()) ? "key" : 
clause.getProperty()).
                         order(clause.getDirection() == Sort.Direction.ASC ? 
SortOrder.Asc : SortOrder.Desc).
                         build()).
                 build()).toList();
diff --git 
a/ext/opensearch/client-opensearch/src/main/java/org/apache/syncope/ext/opensearch/client/OpenSearchClientFactoryBean.java
 
b/ext/opensearch/client-opensearch/src/main/java/org/apache/syncope/ext/opensearch/client/OpenSearchClientFactoryBean.java
index cfdb392a66..d21cbe0f05 100644
--- 
a/ext/opensearch/client-opensearch/src/main/java/org/apache/syncope/ext/opensearch/client/OpenSearchClientFactoryBean.java
+++ 
b/ext/opensearch/client-opensearch/src/main/java/org/apache/syncope/ext/opensearch/client/OpenSearchClientFactoryBean.java
@@ -103,7 +103,7 @@ public class OpenSearchClientFactoryBean implements 
FactoryBean<OpenSearchClient
                     String encodedAuth = Base64.getEncoder().
                             encodeToString((username + ":" + 
password).getBytes(StandardCharsets.UTF_8));
                     builder.setDefaultHeaders(
-                            new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + encodedAuth) });
+                            new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth) });
                 } else if (serviceToken != null) {
                     builder.setDefaultHeaders(
                             new Header[] { new 
BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + serviceToken) });
diff --git 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
index f7021a5507..0b2dfd8e1a 100644
--- 
a/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
+++ 
b/ext/opensearch/persistence/src/main/java/org/apache/syncope/core/persistence/opensearch/dao/OpenSearchAuditEventDAO.java
@@ -152,7 +152,7 @@ public class OpenSearchAuditEventDAO implements 
AuditEventDAO {
     protected List<SortOptions> sortBuilders(final Stream<Sort.Order> orderBy) 
{
         return orderBy.map(clause -> new SortOptions.Builder().field(
                 new FieldSort.Builder().
-                        field(clause.getProperty()).
+                        field("id".equals(clause.getProperty()) ? "key" : 
clause.getProperty()).
                         order(clause.getDirection() == Sort.Direction.ASC ? 
SortOrder.Asc : SortOrder.Desc).
                         build()).
                 build()).toList();


Reply via email to