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();