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 2021/09/28 10:59:26 UTC
[syncope] 03/03: [SYNCOPE-1644] Now relying on SpringBeanJobFactory
which creates the bean and immediately executes it
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 e06159e1a6323a63d337741826860fc3a7a85f0c
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Tue Sep 28 12:21:46 2021 +0200
[SYNCOPE-1644] Now relying on SpringBeanJobFactory which creates the bean and immediately executes it
---
.../core/provisioning/api/job/JobManager.java | 4 +
.../provisioning/java/ProvisioningContext.java | 4 +-
.../java/job/AutowiringSpringBeanJobFactory.java | 85 ----------------------
.../provisioning/java/job/DefaultJobManager.java | 78 +++++---------------
.../java/job/SyncopeSpringBeanJobFactory.java | 45 ++++++++++++
5 files changed, 68 insertions(+), 148 deletions(-)
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 6d8fa28..1402142 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
@@ -30,6 +30,10 @@ import org.quartz.SchedulerException;
@SuppressWarnings("squid:S1214")
public interface JobManager {
+ String TASK_KEY = "task";
+
+ String REPORT_KEY = "report";
+
String DOMAIN_KEY = "domain";
String EXECUTOR_KEY = "executor";
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
index 5030ce0..96ab095 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
@@ -155,10 +155,10 @@ import org.apache.syncope.core.provisioning.java.data.TaskDataBinderImpl;
import org.apache.syncope.core.provisioning.java.data.UserDataBinderImpl;
import org.apache.syncope.core.provisioning.java.data.WAConfigDataBinderImpl;
import org.apache.syncope.core.provisioning.java.data.wa.WAClientAppDataBinderImpl;
-import org.apache.syncope.core.provisioning.java.job.AutowiringSpringBeanJobFactory;
import org.apache.syncope.core.provisioning.java.job.DefaultJobManager;
import org.apache.syncope.core.provisioning.java.job.SchedulerDBInit;
import org.apache.syncope.core.provisioning.java.job.SchedulerShutdown;
+import org.apache.syncope.core.provisioning.java.job.SyncopeSpringBeanJobFactory;
import org.apache.syncope.core.provisioning.java.job.SystemLoadReporterJob;
import org.apache.syncope.core.provisioning.java.job.notification.DefaultNotificationJobDelegate;
import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
@@ -311,7 +311,7 @@ public class ProvisioningContext implements AsyncConfigurer {
scheduler.setOverwriteExistingJobs(true);
scheduler.setDataSource(masterDataSource);
scheduler.setTransactionManager(masterTransactionManager);
- scheduler.setJobFactory(new AutowiringSpringBeanJobFactory());
+ scheduler.setJobFactory(new SyncopeSpringBeanJobFactory());
Properties quartzProperties = new Properties();
quartzProperties.setProperty(
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AutowiringSpringBeanJobFactory.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AutowiringSpringBeanJobFactory.java
deleted file mode 100644
index 109c9c2..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AutowiringSpringBeanJobFactory.java
+++ /dev/null
@@ -1,85 +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.job;
-
-import org.quartz.SchedulerContext;
-import org.quartz.spi.TriggerFiredBundle;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.PropertyAccessorFactory;
-import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.scheduling.quartz.SpringBeanJobFactory;
-
-/**
- * An implementation of SpringBeanJobFactory that retrieves the bean from the Spring context so that autowiring and
- * transactions work.
- */
-public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
-
- private transient AutowireCapableBeanFactory beanFactory;
-
- private String[] ignoredUnknownProperties;
-
- private SchedulerContext schedulerContext;
-
- @Override
- public void setApplicationContext(final ApplicationContext context) {
- beanFactory = context.getAutowireCapableBeanFactory();
- }
-
- @Override
- public void setIgnoredUnknownProperties(final String... ignoredUnknownProperties) {
- String[] defensiveCopy = ignoredUnknownProperties.clone();
- super.setIgnoredUnknownProperties(defensiveCopy);
- this.ignoredUnknownProperties = defensiveCopy;
- }
-
- @Override
- public void setSchedulerContext(final SchedulerContext schedulerContext) {
- super.setSchedulerContext(schedulerContext);
- this.schedulerContext = schedulerContext;
- }
-
- @Override
- protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
- Object job = beanFactory.getBean(bundle.getJobDetail().getKey().getName());
- if (isEligibleForPropertyPopulation(job)) {
- BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
- MutablePropertyValues pvs = new MutablePropertyValues();
- if (this.schedulerContext != null) {
- pvs.addPropertyValues(this.schedulerContext);
- }
- pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap());
- pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());
- if (this.ignoredUnknownProperties != null) {
- for (String propName : this.ignoredUnknownProperties) {
- if (pvs.contains(propName) && !bw.isWritableProperty(propName)) {
- pvs.removePropertyValue(propName);
- }
- }
- bw.setPropertyValues(pvs);
- } else {
- bw.setPropertyValues(pvs, true);
- }
- }
- return job;
- }
-}
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 eb0d230..63c48a5 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
@@ -37,7 +37,6 @@ import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.IdRepoImplementationType;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.core.persistence.api.DomainHolder;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.ReportDAO;
import org.apache.syncope.core.persistence.api.dao.TaskDAO;
import org.apache.syncope.core.persistence.api.entity.Report;
@@ -46,7 +45,6 @@ import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
import org.apache.syncope.core.persistence.api.entity.task.Task;
import org.apache.syncope.core.provisioning.api.job.JobNamer;
import org.apache.syncope.core.spring.security.AuthContextUtils;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -61,8 +59,6 @@ import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.transaction.annotation.Transactional;
import org.apache.syncope.core.provisioning.api.job.JobManager;
@@ -76,6 +72,7 @@ import org.apache.syncope.core.provisioning.java.job.report.ReportJob;
import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
import org.apache.syncope.core.spring.security.SecurityProperties;
+import org.quartz.Trigger;
public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
@@ -157,7 +154,7 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
}
protected void registerJob(
- final String jobName, final Job jobInstance,
+ final String jobName, final Class<? extends Job> jobClass,
final String cronExpression, final Date startAt,
final Map<String, Object> jobMap)
throws SchedulerException {
@@ -170,34 +167,28 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
// 0. unregister job
unregisterJob(jobName);
- // 1. Job bean
- ApplicationContextProvider.getBeanFactory().registerSingleton(jobName, jobInstance);
-
- // 2. JobDetail bean
- JobBuilder jobDetailBuilder = JobBuilder.newJob(jobInstance.getClass()).
+ // 1. JobDetail
+ JobBuilder jobDetailBuilder = JobBuilder.newJob(jobClass).
withIdentity(jobName).
usingJobData(new JobDataMap(jobMap));
- // 3. Trigger
+ // 2. Trigger
if (cronExpression == null && startAt == null) {
// Jobs added with no trigger must be durable
scheduler.getScheduler().addJob(jobDetailBuilder.storeDurably().build(), true);
} else {
- TriggerBuilder<?> triggerBuilder;
+ TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger().
+ withIdentity(JobNamer.getTriggerName(jobName));
if (cronExpression == null) {
- triggerBuilder = TriggerBuilder.newTrigger().
- withIdentity(JobNamer.getTriggerName(jobName)).
- startAt(startAt);
+ triggerBuilder.startAt(startAt);
} else {
- triggerBuilder = TriggerBuilder.newTrigger().
- withIdentity(JobNamer.getTriggerName(jobName)).
- withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
+ triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
if (startAt == null) {
- triggerBuilder = triggerBuilder.startNow();
+ triggerBuilder.startNow();
} else {
- triggerBuilder = triggerBuilder.startAt(startAt);
+ triggerBuilder.startAt(startAt);
}
}
@@ -205,39 +196,11 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
}
}
- @SuppressWarnings("unchecked")
- protected static <T> T createSpringBean(final Class<T> jobClass) {
- T jobInstance = null;
- for (int i = 0; i < 5 && jobInstance == null; i++) {
- LOG.debug("{} attempt to create Spring bean for {}", i, jobClass);
- try {
- jobInstance = (T) ApplicationContextProvider.getBeanFactory().
- createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
- LOG.debug("{} attempt to create Spring bean for {} succeeded", i, jobClass);
- } catch (BeanCreationException e) {
- LOG.error("Could not create Spring bean for {}", jobClass, e);
- try {
- Thread.sleep(1000);
- } catch (final InterruptedException ex) {
- // ignore
- }
- }
- }
- if (jobInstance == null) {
- throw new NotFoundException("Spring bean for " + jobClass);
- }
-
- return jobInstance;
- }
-
@Override
public Map<String, Object> register(final SchedTask task, final Date startAt, final long interruptMaxRetries,
final String executor)
throws SchedulerException {
- TaskJob job = createSpringBean(TaskJob.class);
- job.setTaskKey(task.getKey());
-
Implementation jobDelegate = task.getJobDelegate() == null
? task instanceof PullTask
? implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
@@ -255,11 +218,12 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
}
Map<String, Object> jobMap = createJobMapForExecutionContext(executor);
+ jobMap.put(JobManager.TASK_KEY, task.getKey());
jobMap.put(TaskJob.DELEGATE_IMPLEMENTATION, jobDelegate.getKey());
registerJob(
JobNamer.getJobKey(task).getName(),
- job,
+ TaskJob.class,
task.getCronExpression(),
startAt,
jobMap);
@@ -270,12 +234,10 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
public void register(final Report report, final Date startAt, final long interruptMaxRetries,
final String executor) throws SchedulerException {
- ReportJob job = createSpringBean(ReportJob.class);
- job.setReportKey(report.getKey());
-
Map<String, Object> jobMap = createJobMapForExecutionContext(executor);
+ jobMap.put(JobManager.REPORT_KEY, report.getKey());
- registerJob(JobNamer.getJobKey(report).getName(), job, report.getCronExpression(), startAt, jobMap);
+ registerJob(JobNamer.getJobKey(report).getName(), ReportJob.class, report.getCronExpression(), startAt, jobMap);
}
protected static Map<String, Object> createJobMapForExecutionContext(final String executor) {
@@ -292,10 +254,6 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
} catch (SchedulerException e) {
LOG.error("Could not remove job " + jobName, e);
}
-
- if (ApplicationContextProvider.getBeanFactory().containsSingleton(jobName)) {
- ApplicationContextProvider.getBeanFactory().destroySingleton(jobName);
- }
}
@Override
@@ -396,11 +354,10 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
NotificationJob.class.getSimpleName(), conf.getLeft());
try {
- NotificationJob job = createSpringBean(NotificationJob.class);
Map<String, Object> jobData = createJobMapForExecutionContext(securityProperties.getAdminUser());
registerJob(
NOTIFICATION_JOB.getName(),
- job,
+ NotificationJob.class,
conf.getLeft(),
null,
jobData);
@@ -412,11 +369,10 @@ public class DefaultJobManager implements JobManager, SyncopeCoreLoader {
// 4. SystemLoadReporterJob (fixed schedule, every minute)
LOG.debug("Registering {}", SystemLoadReporterJob.class);
try {
- SystemLoadReporterJob job = createSpringBean(SystemLoadReporterJob.class);
Map<String, Object> jobData = createJobMapForExecutionContext(securityProperties.getAdminUser());
registerJob(
StringUtils.uncapitalize(SystemLoadReporterJob.class.getSimpleName()),
- job,
+ SystemLoadReporterJob.class,
"0 * * * * ?",
null,
jobData);
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeSpringBeanJobFactory.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeSpringBeanJobFactory.java
new file mode 100644
index 0000000..c690f39
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeSpringBeanJobFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.job;
+
+import java.util.Optional;
+import org.apache.syncope.core.provisioning.api.job.JobManager;
+import org.apache.syncope.core.provisioning.java.job.report.ReportJob;
+import org.quartz.spi.TriggerFiredBundle;
+import org.springframework.scheduling.quartz.SpringBeanJobFactory;
+
+public class SyncopeSpringBeanJobFactory extends SpringBeanJobFactory {
+
+ @Override
+ protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
+ Object job = super.createJobInstance(bundle);
+
+ if (bundle.getJobDetail().getJobDataMap() != null) {
+ if (job instanceof ReportJob) {
+ Optional.ofNullable(bundle.getJobDetail().getJobDataMap().getString(JobManager.REPORT_KEY)).
+ ifPresent(((ReportJob) job)::setReportKey);
+ } else if (job instanceof TaskJob) {
+ Optional.ofNullable(bundle.getJobDetail().getJobDataMap().getString(JobManager.TASK_KEY)).
+ ifPresent(((TaskJob) job)::setTaskKey);
+ }
+ }
+
+ return job;
+ }
+}