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 2022/03/30 18:38:35 UTC
[syncope] branch master updated: [SYNCOPE-1670] Enable for graceful shutdown (#332)
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 553d9c6 [SYNCOPE-1670] Enable for graceful shutdown (#332)
553d9c6 is described below
commit 553d9c6618bf844eba80135c202abd188f207431
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Wed Mar 30 20:38:29 2022 +0200
[SYNCOPE-1670] Enable for graceful shutdown (#332)
---
.../console/src/main/resources/console.properties | 3 +
.../enduser/src/main/resources/enduser.properties | 3 +
.../client/api/startstop/KeymasterStart.java | 3 +-
.../client/api/startstop/KeymasterStop.java | 3 +-
.../syncope/core/logic/IdRepoLogicContext.java | 147 ++++++++++++---------
.../core/rest/cxf/IdRepoRESTCXFContext.java | 25 +++-
.../syncope/core/rest/cxf/RESTProperties.java} | 25 ++--
.../core/persistence/api/SyncopeCoreLoader.java | 13 +-
.../syncope/core/persistence/jpa/MasterDomain.java | 34 +++--
.../core/persistence/jpa/PersistenceContext.java | 6 +-
.../core/persistence/jpa/RuntimeDomainLoader.java | 18 ++-
core/provisioning-api/pom.xml | 31 ++---
.../core/provisioning/java/ExecutorProperties.java | 62 +++++++++
.../provisioning/java/ProvisioningContext.java | 54 ++++----
.../provisioning/java/ProvisioningProperties.java | 43 ++----
.../core/starter/SyncopeCoreApplication.java | 52 +++++---
.../syncope/core/starter/SyncopeCoreStart.java | 10 +-
...{SyncopeCoreStart.java => SyncopeCoreStop.java} | 30 ++---
.../syncope/core/starter/TaskExecutorUnloader.java | 64 +++++++++
core/starter/src/main/resources/core.properties | 3 +
.../core/flowable/support/DomainProcessEngine.java | 2 +-
.../support/DomainProcessEngineFactoryBean.java | 9 +-
.../src/main/resources/core-embedded.properties | 1 +
pom.xml | 34 ++---
sra/src/main/resources/sra.properties | 3 +
wa/starter/src/main/resources/wa.properties | 3 +
26 files changed, 422 insertions(+), 259 deletions(-)
diff --git a/client/idrepo/console/src/main/resources/console.properties b/client/idrepo/console/src/main/resources/console.properties
index 51a37c6..489bdd6 100644
--- a/client/idrepo/console/src/main/resources/console.properties
+++ b/client/idrepo/console/src/main/resources/console.properties
@@ -30,6 +30,9 @@ management.endpoint.health.show-details=ALWAYS
service.discovery.address=http://localhost:8080/syncope-console/
+server.shutdown=graceful
+spring.lifecycle.timeout-per-shutdown-phase=30s
+
wicket.core.csrf.enabled=false
logging.config=classpath:/log4j2.xml
diff --git a/client/idrepo/enduser/src/main/resources/enduser.properties b/client/idrepo/enduser/src/main/resources/enduser.properties
index c9d8cc6..ff0bd6a 100644
--- a/client/idrepo/enduser/src/main/resources/enduser.properties
+++ b/client/idrepo/enduser/src/main/resources/enduser.properties
@@ -30,6 +30,9 @@ management.endpoint.health.show-details=ALWAYS
service.discovery.address=http://localhost:8080/syncope-enduser/
+server.shutdown=graceful
+spring.lifecycle.timeout-per-shutdown-phase=30s
+
wicket.core.csrf.enabled=false
logging.config=classpath:/log4j2.xml
diff --git a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStart.java b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStart.java
index f164865..abbf86d 100644
--- a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStart.java
+++ b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStart.java
@@ -22,8 +22,7 @@ import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
-public class KeymasterStart extends KeymasterStartStop
- implements ApplicationListener<ContextRefreshedEvent> {
+public class KeymasterStart extends KeymasterStartStop implements ApplicationListener<ContextRefreshedEvent> {
public KeymasterStart(final NetworkService.Type networkServiceType) {
super(networkServiceType);
diff --git a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStop.java b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStop.java
index 7851a39..8127056 100644
--- a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStop.java
+++ b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/startstop/KeymasterStop.java
@@ -22,8 +22,7 @@ import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
-public class KeymasterStop extends KeymasterStartStop
- implements ApplicationListener<ContextClosedEvent> {
+public class KeymasterStop extends KeymasterStartStop implements ApplicationListener<ContextClosedEvent> {
public KeymasterStop(final NetworkService.Type networkServiceType) {
super(networkServiceType);
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
index f28af9a..bbb7d88 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java
@@ -106,8 +106,10 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public LogicInvocationHandler logicInvocationHandler(final NotificationManager notificationManager,
- final AuditManager auditManager) {
+ public LogicInvocationHandler logicInvocationHandler(
+ final NotificationManager notificationManager,
+ final AuditManager auditManager) {
+
return new LogicInvocationHandler(notificationManager, auditManager);
}
@@ -125,8 +127,11 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public AuditLoader auditLoader(final AuditAccessor auditAccessor, final ImplementationLookup implementationLookup,
- final LogicProperties logicProperties) {
+ public AuditLoader auditLoader(
+ final AuditAccessor auditAccessor,
+ final ImplementationLookup implementationLookup,
+ final LogicProperties logicProperties) {
+
return new AuditLoader(auditAccessor, implementationLookup, logicProperties);
}
@@ -150,9 +155,11 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public AccessTokenLogic accessTokenLogic(final AccessTokenDataBinder binder,
- final AccessTokenDAO accessTokenDAO,
- final SecurityProperties securityProperties) {
+ public AccessTokenLogic accessTokenLogic(
+ final AccessTokenDataBinder binder,
+ final AccessTokenDAO accessTokenDAO,
+ final SecurityProperties securityProperties) {
+
return new AccessTokenLogic(securityProperties, binder, accessTokenDAO);
}
@@ -179,16 +186,20 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public AnyTypeClassLogic anyTypeClassLogic(final AnyTypeClassDataBinder binder,
- final AnyTypeClassDAO anyTypeClassDAO) {
+ public AnyTypeClassLogic anyTypeClassLogic(
+ final AnyTypeClassDataBinder binder,
+ final AnyTypeClassDAO anyTypeClassDAO) {
+
return new AnyTypeClassLogic(binder, anyTypeClassDAO);
}
@ConditionalOnMissingBean
@Bean
- public AnyTypeLogic anyTypeLogic(final AnyTypeDataBinder binder,
- final AnyTypeDAO anyTypeDAO,
- final AnyObjectDAO anyObjectDAO) {
+ public AnyTypeLogic anyTypeLogic(
+ final AnyTypeDataBinder binder,
+ final AnyTypeDAO anyTypeDAO,
+ final AnyObjectDAO anyObjectDAO) {
+
return new AnyTypeLogic(binder, anyTypeDAO, anyObjectDAO);
}
@@ -222,9 +233,11 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public DelegationLogic delegationLogic(final DelegationDataBinder binder,
- final UserDAO userDAO,
- final DelegationDAO delegationDAO) {
+ public DelegationLogic delegationLogic(
+ final DelegationDataBinder binder,
+ final UserDAO userDAO,
+ final DelegationDAO delegationDAO) {
+
return new DelegationLogic(binder, delegationDAO, userDAO);
}
@@ -239,22 +252,24 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public GroupLogic groupLogic(final GroupProvisioningManager provisioningManager,
- final JobManager jobManager,
- final TemplateUtils templateUtils,
- final EntityFactory entityFactory,
- final RealmDAO realmDAO,
- final AnyTypeDAO anyTypeDAO,
- final UserDAO userDAO,
- final GroupDAO groupDAO,
- final AnySearchDAO anySearchDAO,
- final SchedulerFactoryBean scheduler,
- final TaskDAO taskDAO,
- final ConfParamOps confParamOps,
- final GroupDataBinder groupDataBinder,
- final TaskDataBinder taskDataBinder,
- final ImplementationDAO implementationDAO,
- final SecurityProperties securityProperties) {
+ public GroupLogic groupLogic(
+ final GroupProvisioningManager provisioningManager,
+ final JobManager jobManager,
+ final TemplateUtils templateUtils,
+ final EntityFactory entityFactory,
+ final RealmDAO realmDAO,
+ final AnyTypeDAO anyTypeDAO,
+ final UserDAO userDAO,
+ final GroupDAO groupDAO,
+ final AnySearchDAO anySearchDAO,
+ final SchedulerFactoryBean scheduler,
+ final TaskDAO taskDAO,
+ final ConfParamOps confParamOps,
+ final GroupDataBinder groupDataBinder,
+ final TaskDataBinder taskDataBinder,
+ final ImplementationDAO implementationDAO,
+ final SecurityProperties securityProperties) {
+
return new GroupLogic(
realmDAO,
anyTypeDAO,
@@ -276,15 +291,17 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public ImplementationLogic implementationLogic(final ImplementationDataBinder binder,
- final PlainSchemaDAO plainSchemaDAO,
- final RealmDAO realmDAO,
- final PolicyDAO policyDAO,
- final ReportDAO reportDAO,
- final TaskDAO taskDAO,
- final ExternalResourceDAO externalResourceDAO,
- final ImplementationDAO implementationDAO,
- final NotificationDAO notificationDAO) {
+ public ImplementationLogic implementationLogic(
+ final ImplementationDataBinder binder,
+ final PlainSchemaDAO plainSchemaDAO,
+ final RealmDAO realmDAO,
+ final PolicyDAO policyDAO,
+ final ReportDAO reportDAO,
+ final TaskDAO taskDAO,
+ final ExternalResourceDAO externalResourceDAO,
+ final ImplementationDAO implementationDAO,
+ final NotificationDAO notificationDAO) {
+
return new ImplementationLogic(
binder,
implementationDAO,
@@ -299,18 +316,22 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public MailTemplateLogic mailTemplateLogic(final MailTemplateDAO mailTemplateDAO,
- final EntityFactory entityFactory,
- final NotificationDAO notificationDAO) {
+ public MailTemplateLogic mailTemplateLogic(
+ final MailTemplateDAO mailTemplateDAO,
+ final EntityFactory entityFactory,
+ final NotificationDAO notificationDAO) {
+
return new MailTemplateLogic(mailTemplateDAO, notificationDAO, entityFactory);
}
@ConditionalOnMissingBean
@Bean
- public NotificationLogic notificationLogic(final NotificationDataBinder binder,
- final JobManager jobManager,
- final SchedulerFactoryBean scheduler,
- final NotificationDAO notificationDAO) {
+ public NotificationLogic notificationLogic(
+ final NotificationDataBinder binder,
+ final JobManager jobManager,
+ final SchedulerFactoryBean scheduler,
+ final NotificationDAO notificationDAO) {
+
return new NotificationLogic(jobManager, scheduler, notificationDAO, binder);
}
@@ -326,11 +347,13 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public RealmLogic realmLogic(final RealmDataBinder binder,
- final RealmDAO realmDAO,
- final AnySearchDAO anySearchDAO,
- final PropagationManager propagationManager,
- final PropagationTaskExecutor taskExecutor) {
+ public RealmLogic realmLogic(
+ final RealmDataBinder binder,
+ final RealmDAO realmDAO,
+ final AnySearchDAO anySearchDAO,
+ final PropagationManager propagationManager,
+ final PropagationTaskExecutor taskExecutor) {
+
return new RealmLogic(realmDAO, anySearchDAO, binder, propagationManager, taskExecutor);
}
@@ -359,9 +382,11 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public ReportTemplateLogic reportTemplateLogic(final ReportTemplateDAO reportTemplateDAO,
- final ReportDAO reportDAO,
- final EntityFactory entityFactory) {
+ public ReportTemplateLogic reportTemplateLogic(
+ final ReportTemplateDAO reportTemplateDAO,
+ final ReportDAO reportDAO,
+ final EntityFactory entityFactory) {
+
return new ReportTemplateLogic(reportTemplateDAO, reportDAO, entityFactory);
}
@@ -376,11 +401,13 @@ public class IdRepoLogicContext {
@ConditionalOnMissingBean
@Bean
- public SchemaLogic schemaLogic(final SchemaDataBinder binder,
- final VirSchemaDAO virSchemaDAO,
- final AnyTypeClassDAO anyTypeClassDAO,
- final DerSchemaDAO derSchemaDAO,
- final PlainSchemaDAO plainSchemaDAO) {
+ public SchemaLogic schemaLogic(
+ final SchemaDataBinder binder,
+ final VirSchemaDAO virSchemaDAO,
+ final AnyTypeClassDAO anyTypeClassDAO,
+ final DerSchemaDAO derSchemaDAO,
+ final PlainSchemaDAO plainSchemaDAO) {
+
return new SchemaLogic(plainSchemaDAO, derSchemaDAO, virSchemaDAO, anyTypeClassDAO, binder);
}
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
index 6d28e97..cb7df87 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/IdRepoRESTCXFContext.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ThreadPoolExecutor;
import javax.servlet.ServletRequestListener;
import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Server;
@@ -124,6 +125,7 @@ import org.apache.syncope.core.rest.cxf.service.TaskServiceImpl;
import org.apache.syncope.core.rest.cxf.service.UserSelfServiceImpl;
import org.apache.syncope.core.rest.cxf.service.UserServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -133,17 +135,23 @@ import org.springframework.core.env.Environment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@PropertySource("classpath:errorMessages.properties")
+@EnableConfigurationProperties(RESTProperties.class)
@Configuration(proxyBeanMethods = false)
public class IdRepoRESTCXFContext {
@ConditionalOnMissingBean
@Bean
- public ThreadPoolTaskExecutor batchExecutor() {
- ThreadPoolTaskExecutor batchExecutor = new ThreadPoolTaskExecutor();
- batchExecutor.setCorePoolSize(10);
- batchExecutor.setThreadNamePrefix("Batch-");
- batchExecutor.initialize();
- return batchExecutor;
+ public ThreadPoolTaskExecutor batchExecutor(final RESTProperties props) {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(props.getBatchExecutor().getCorePoolSize());
+ executor.setMaxPoolSize(props.getBatchExecutor().getMaxPoolSize());
+ executor.setQueueCapacity(props.getBatchExecutor().getQueueCapacity());
+ executor.setAwaitTerminationSeconds(props.getBatchExecutor().getAwaitTerminationSeconds());
+ executor.setWaitForTasksToCompleteOnShutdown(true);
+ executor.setThreadNamePrefix("Batch-");
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
+ executor.initialize();
+ return executor;
}
@ConditionalOnMissingBean
@@ -475,8 +483,11 @@ public class IdRepoRESTCXFContext {
@ConditionalOnMissingBean
@Bean
- public UserService userService(final UserDAO userDAO, final UserLogic userLogic,
+ public UserService userService(
+ final UserDAO userDAO,
+ final UserLogic userLogic,
final SearchCondVisitor searchCondVisitor) {
+
return new UserServiceImpl(searchCondVisitor, userDAO, userLogic);
}
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SchedulerShutdown.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RESTProperties.java
similarity index 55%
rename from core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SchedulerShutdown.java
rename to core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RESTProperties.java
index 04e6ddb..78176ee 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SchedulerShutdown.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RESTProperties.java
@@ -16,26 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.syncope.core.provisioning.java.job;
+package org.apache.syncope.core.rest.cxf;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.apache.syncope.core.provisioning.java.ExecutorProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
-/**
- * Clean shutdown for Quartz scheduler.
- */
-public class SchedulerShutdown implements DisposableBean {
-
- private final ApplicationContext ctx;
+@ConfigurationProperties("rest")
+public class RESTProperties {
- public SchedulerShutdown(final ApplicationContext ctx) {
- this.ctx = ctx;
- }
+ private final ExecutorProperties batchExecutor = new ExecutorProperties();
- @Override
- public void destroy() throws Exception {
- SchedulerFactoryBean scheduler = ctx.getBean(SchedulerFactoryBean.class);
- scheduler.getScheduler().shutdown();
+ public ExecutorProperties getBatchExecutor() {
+ return batchExecutor;
}
}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/SyncopeCoreLoader.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/SyncopeCoreLoader.java
index 786d370..9f6f2b3 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/SyncopeCoreLoader.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/SyncopeCoreLoader.java
@@ -25,14 +25,14 @@ import org.springframework.core.Ordered;
public interface SyncopeCoreLoader extends Ordered {
/**
- * Perform generic (not related to any domain) initialization operations.
+ * Perform generic (not related to any domain) init operations.
*/
default void load() {
// nothing to do
}
/**
- * Perform initialization operations on the given domain.
+ * Perform init operations on the given domain.
*
* @param domain domain to initialize
* @param datasource db access for the given domain
@@ -42,11 +42,18 @@ public interface SyncopeCoreLoader extends Ordered {
}
/**
- * Perform closing operations on the given domain.
+ * Perform dispose operations on the given domain.
*
* @param domain domain to unload
*/
default void unload(String domain) {
// nothing to do
}
+
+ /**
+ * Perform generic (not related to any domain) dispose operations.
+ */
+ default void unload() {
+ // nothing to do
+ }
}
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/MasterDomain.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/MasterDomain.java
index 17593f9..e701849 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/MasterDomain.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/MasterDomain.java
@@ -24,7 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
-
import javax.sql.DataSource;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.core.persistence.jpa.spring.CommonEntityManagerFactoryConf;
@@ -69,9 +68,10 @@ public class MasterDomain {
@ConditionalOnMissingBean(name = "MasterDataSourceInitializer")
@Bean(name = "MasterDataSourceInitializer")
public DataSourceInitializer masterDataSourceInitializer(
- final PersistenceProperties props,
- @Qualifier("MasterDataSource")
- final JndiObjectFactoryBean masterDataSource) {
+ final PersistenceProperties props,
+ @Qualifier("MasterDataSource")
+ final JndiObjectFactoryBean masterDataSource) {
+
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.setContinueOnError(true);
databasePopulator.setIgnoreFailedDrops(true);
@@ -89,10 +89,11 @@ public class MasterDomain {
@DependsOn("commonEMFConf")
@Bean(name = "MasterEntityManagerFactory")
public DomainEntityManagerFactoryBean masterEntityManagerFactory(
- final PersistenceProperties props,
- @Qualifier("MasterDataSource")
- final JndiObjectFactoryBean masterDataSource,
- final CommonEntityManagerFactoryConf commonEMFConf) {
+ final PersistenceProperties props,
+ @Qualifier("MasterDataSource")
+ final JndiObjectFactoryBean masterDataSource,
+ final CommonEntityManagerFactoryConf commonEMFConf) {
+
OpenJpaVendorAdapter vendorAdapter = new OpenJpaVendorAdapter();
vendorAdapter.setShowSql(false);
vendorAdapter.setGenerateDdl(true);
@@ -117,20 +118,25 @@ public class MasterDomain {
@ConditionalOnMissingBean(name = "MasterTransactionManager")
@Bean(name = { "MasterTransactionManager", "Master" })
public PlatformTransactionManager transactionManager(
- @Qualifier("MasterEntityManagerFactory")
- final DomainEntityManagerFactoryBean masterEntityManagerFactory) {
+ @Qualifier("MasterEntityManagerFactory")
+ final DomainEntityManagerFactoryBean masterEntityManagerFactory) {
+
return new JpaTransactionManager(Objects.requireNonNull(masterEntityManagerFactory.getObject()));
}
@Bean(name = "MasterContentXML")
- public InputStream masterContentXML(final ResourceLoader resourceLoader,
- final PersistenceProperties props) throws IOException {
+ public InputStream masterContentXML(
+ final ResourceLoader resourceLoader,
+ final PersistenceProperties props) throws IOException {
+
return resourceLoader.getResource(props.getDomain().get(0).getContent()).getInputStream();
}
@Bean(name = "MasterKeymasterConfParamsJSON")
- public InputStream masterKeymasterConfParamsJSON(final ResourceLoader resourceLoader,
- final PersistenceProperties props) throws IOException {
+ public InputStream masterKeymasterConfParamsJSON(
+ final ResourceLoader resourceLoader,
+ final PersistenceProperties props) throws IOException {
+
return resourceLoader.getResource(props.getDomain().get(0).getKeymasterConfParams()).getInputStream();
}
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
index 81edd76..c38af10 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
@@ -136,6 +136,7 @@ import org.apache.syncope.core.persistence.jpa.spring.MultiJarAwarePersistenceUn
import org.apache.syncope.core.spring.security.SecurityProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -237,9 +238,10 @@ public class PersistenceContext {
@Bean
public RuntimeDomainLoader runtimeDomainLoader(
final DomainHolder domainHolder,
- final DomainRegistry domainRegistry) {
+ final DomainRegistry domainRegistry,
+ final ListableBeanFactory beanFactory) {
- return new RuntimeDomainLoader(domainHolder, domainRegistry);
+ return new RuntimeDomainLoader(domainHolder, domainRegistry, beanFactory);
}
@ConditionalOnMissingBean
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java
index 1269a87..bd2f90b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java
@@ -28,6 +28,7 @@ import org.apache.syncope.core.persistence.api.DomainRegistry;
import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
import org.apache.syncope.core.spring.ApplicationContextProvider;
import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.factory.ListableBeanFactory;
public class RuntimeDomainLoader implements DomainWatcher {
@@ -37,9 +38,16 @@ public class RuntimeDomainLoader implements DomainWatcher {
protected final DomainRegistry domainRegistry;
- public RuntimeDomainLoader(final DomainHolder domainHolder, final DomainRegistry domainRegistry) {
+ protected final ListableBeanFactory beanFactory;
+
+ public RuntimeDomainLoader(
+ final DomainHolder domainHolder,
+ final DomainRegistry domainRegistry,
+ final ListableBeanFactory beanFactory) {
+
this.domainHolder = domainHolder;
this.domainRegistry = domainRegistry;
+ this.beanFactory = beanFactory;
}
@Override
@@ -70,14 +78,14 @@ public class RuntimeDomainLoader implements DomainWatcher {
if (domainHolder.getDomains().containsKey(domain)) {
LOG.info("Domain {} unregistration", domain);
- ApplicationContextProvider.getApplicationContext().getBeansOfType(SyncopeCoreLoader.class).values().
- stream().sorted(Comparator.comparing(SyncopeCoreLoader::getOrder).reversed()).
+ beanFactory.getBeansOfType(SyncopeCoreLoader.class).values().stream().
+ sorted(Comparator.comparing(SyncopeCoreLoader::getOrder).reversed()).
forEachOrdered(loader -> {
String loaderName = AopUtils.getTargetClass(loader).getName();
- LOG.debug("[{}] Starting on domain '{}'", loaderName, domain);
+ LOG.debug("[{}] Starting dispose on domain '{}'", loaderName, domain);
loader.unload(domain);
- LOG.debug("[{}] Completed on domain '{}'", loaderName, domain);
+ LOG.debug("[{}] Dispose completed on domain '{}'", loaderName, domain);
});
domainRegistry.unregister(domain);
diff --git a/core/provisioning-api/pom.xml b/core/provisioning-api/pom.xml
index 10cac1e..c412723 100644
--- a/core/provisioning-api/pom.xml
+++ b/core/provisioning-api/pom.xml
@@ -39,37 +39,28 @@ under the License.
<dependencies>
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-jexl3</artifactId>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.module</groupId>
- <artifactId>jackson-module-afterburner</artifactId>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-persistence-api</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-jexl3</artifactId>
</dependency>
<dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
</dependency>
-
<dependency>
- <groupId>org.apache.syncope.core</groupId>
- <artifactId>syncope-core-persistence-api</artifactId>
- <version>${project.version}</version>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-afterburner</artifactId>
</dependency>
<dependency>
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ExecutorProperties.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ExecutorProperties.java
new file mode 100644
index 0000000..d01a5bb
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ExecutorProperties.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+public class ExecutorProperties {
+
+ private int corePoolSize = 5;
+
+ private int maxPoolSize = 25;
+
+ private int queueCapacity = 100;
+
+ private int awaitTerminationSeconds = 5;
+
+ public int getCorePoolSize() {
+ return corePoolSize;
+ }
+
+ public void setCorePoolSize(final int corePoolSize) {
+ this.corePoolSize = corePoolSize;
+ }
+
+ public int getMaxPoolSize() {
+ return maxPoolSize;
+ }
+
+ public void setMaxPoolSize(final int maxPoolSize) {
+ this.maxPoolSize = maxPoolSize;
+ }
+
+ public int getQueueCapacity() {
+ return queueCapacity;
+ }
+
+ public void setQueueCapacity(final int queueCapacity) {
+ this.queueCapacity = queueCapacity;
+ }
+
+ public int getAwaitTerminationSeconds() {
+ return awaitTerminationSeconds;
+ }
+
+ public void setAwaitTerminationSeconds(final int awaitTerminationSeconds) {
+ this.awaitTerminationSeconds = awaitTerminationSeconds;
+ }
+}
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 03613fb..766ddb7 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
@@ -156,7 +156,6 @@ 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.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;
@@ -220,17 +219,18 @@ public class ProvisioningContext {
/**
* Annotated as {@code @Primary} because it will be used by {@code @Async} in {@link AsyncConnectorFacade}.
*
- * @param provisioningProperties configuration properties
- *
+ * @param props configuration properties
* @return executor
*/
@Bean
@Primary
- public ThreadPoolTaskExecutor asyncConnectorFacadeExecutor(final ProvisioningProperties provisioningProperties) {
+ public ThreadPoolTaskExecutor asyncConnectorFacadeExecutor(final ProvisioningProperties props) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(provisioningProperties.getAsyncConnectorFacadeExecutor().getCorePoolSize());
- executor.setMaxPoolSize(provisioningProperties.getAsyncConnectorFacadeExecutor().getMaxPoolSize());
- executor.setQueueCapacity(provisioningProperties.getAsyncConnectorFacadeExecutor().getQueueCapacity());
+ executor.setCorePoolSize(props.getAsyncConnectorFacadeExecutor().getCorePoolSize());
+ executor.setMaxPoolSize(props.getAsyncConnectorFacadeExecutor().getMaxPoolSize());
+ executor.setQueueCapacity(props.getAsyncConnectorFacadeExecutor().getQueueCapacity());
+ executor.setAwaitTerminationSeconds(props.getAsyncConnectorFacadeExecutor().getAwaitTerminationSeconds());
+ executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("AsyncConnectorFacadeExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
@@ -238,7 +238,8 @@ public class ProvisioningContext {
}
@Bean
- public AsyncConfigurer asyncConfigurer(@Qualifier("asyncConnectorFacadeExecutor")
+ public AsyncConfigurer asyncConfigurer(
+ @Qualifier("asyncConnectorFacadeExecutor")
final ThreadPoolTaskExecutor asyncConnectorFacadeExecutor) {
return new AsyncConfigurer() {
@@ -253,16 +254,18 @@ public class ProvisioningContext {
/**
* Used by {@link org.apache.syncope.core.provisioning.java.propagation.PriorityPropagationTaskExecutor}.
*
- * @param provisioningProperties the provisioning properties
+ * @param props the provisioning properties
* @return executor thread pool task executor
*/
@Bean
- public ThreadPoolTaskExecutor propagationTaskExecutorAsyncExecutor(
- final ProvisioningProperties provisioningProperties) {
+ public ThreadPoolTaskExecutor propagationTaskExecutorAsyncExecutor(final ProvisioningProperties props) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(provisioningProperties.getPropagationTaskExecutorAsyncExecutor().getCorePoolSize());
- executor.setMaxPoolSize(provisioningProperties.getPropagationTaskExecutorAsyncExecutor().getMaxPoolSize());
- executor.setQueueCapacity(provisioningProperties.getPropagationTaskExecutorAsyncExecutor().getQueueCapacity());
+ executor.setCorePoolSize(props.getPropagationTaskExecutorAsyncExecutor().getCorePoolSize());
+ executor.setMaxPoolSize(props.getPropagationTaskExecutorAsyncExecutor().getMaxPoolSize());
+ executor.setQueueCapacity(props.getPropagationTaskExecutorAsyncExecutor().getQueueCapacity());
+ executor.setWaitForTasksToCompleteOnShutdown(true);
+ executor.setAwaitTerminationSeconds(
+ props.getPropagationTaskExecutorAsyncExecutor().getAwaitTerminationSeconds());
executor.setThreadNamePrefix("PropagationTaskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
@@ -287,12 +290,11 @@ public class ProvisioningContext {
@DependsOn("quartzDataSourceInit")
@Lazy(false)
@Bean
- public SchedulerFactoryBean scheduler(final ApplicationContext ctx,
- final ProvisioningProperties provisioningProperties) {
+ public SchedulerFactoryBean scheduler(final ApplicationContext ctx, final ProvisioningProperties props) {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setAutoStartup(true);
scheduler.setApplicationContext(ctx);
- scheduler.setWaitForJobsToCompleteOnShutdown(true);
+ scheduler.setWaitForJobsToCompleteOnShutdown(props.getQuartz().isWaitForJobsToCompleteOnShutdown());
scheduler.setOverwriteExistingJobs(true);
scheduler.setDataSource(masterDataSource);
scheduler.setTransactionManager(masterTransactionManager);
@@ -301,16 +303,21 @@ public class ProvisioningContext {
Properties quartzProperties = new Properties();
quartzProperties.setProperty(
"org.quartz.scheduler.idleWaitTime",
- String.valueOf(provisioningProperties.getQuartz().getIdleWaitTime()));
+ String.valueOf(props.getQuartz().getIdleWaitTime()));
quartzProperties.setProperty(
"org.quartz.jobStore.misfireThreshold",
- String.valueOf(provisioningProperties.getQuartz().getMisfireThreshold()));
+ String.valueOf(props.getQuartz().getMisfireThreshold()));
quartzProperties.setProperty(
"org.quartz.jobStore.driverDelegateClass",
- provisioningProperties.getQuartz().getDelegate().getName());
+ props.getQuartz().getDelegate().getName());
+ quartzProperties.setProperty(
+ "org.quartz.jobStore.class",
+ "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+ quartzProperties.setProperty("org.quartz.threadPool.makeThreadsDaemons", "true");
+ quartzProperties.setProperty("org.quartz.scheduler.makeSchedulerThreadDaemon", "true");
quartzProperties.setProperty("org.quartz.jobStore.isClustered", "true");
quartzProperties.setProperty("org.quartz.jobStore.clusterCheckinInterval", "20000");
- quartzProperties.setProperty("org.quartz.scheduler.instanceName", "ClusteredScheduler");
+ quartzProperties.setProperty("org.quartz.scheduler.instanceName", "SyncopeClusteredScheduler");
quartzProperties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
quartzProperties.setProperty("org.quartz.scheduler.jmx.export", "true");
scheduler.setQuartzProperties(quartzProperties);
@@ -318,11 +325,6 @@ public class ProvisioningContext {
return scheduler;
}
- @Bean
- public SchedulerShutdown schedulerShutdown(final ApplicationContext ctx) {
- return new SchedulerShutdown(ctx);
- }
-
@ConditionalOnMissingBean
@Bean
public JobManager jobManager(
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningProperties.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningProperties.java
index 2697866..7375f3d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningProperties.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningProperties.java
@@ -28,39 +28,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("provisioning")
public class ProvisioningProperties {
- public static class ExecutorProperties {
-
- private int corePoolSize = 5;
-
- private int maxPoolSize = 25;
-
- private int queueCapacity = 100;
-
- public int getCorePoolSize() {
- return corePoolSize;
- }
-
- public void setCorePoolSize(final int corePoolSize) {
- this.corePoolSize = corePoolSize;
- }
-
- public int getMaxPoolSize() {
- return maxPoolSize;
- }
-
- public void setMaxPoolSize(final int maxPoolSize) {
- this.maxPoolSize = maxPoolSize;
- }
-
- public int getQueueCapacity() {
- return queueCapacity;
- }
-
- public void setQueueCapacity(final int queueCapacity) {
- this.queueCapacity = queueCapacity;
- }
- }
-
public static class QuartzProperties {
private Class<? extends DriverDelegate> delegate;
@@ -69,6 +36,8 @@ public class ProvisioningProperties {
private boolean disableInstance = false;
+ private boolean waitForJobsToCompleteOnShutdown = true;
+
private int idleWaitTime = 30000;
private int misfireThreshold = 60000;
@@ -97,6 +66,14 @@ public class ProvisioningProperties {
this.disableInstance = disableInstance;
}
+ public boolean isWaitForJobsToCompleteOnShutdown() {
+ return waitForJobsToCompleteOnShutdown;
+ }
+
+ public void setWaitForJobsToCompleteOnShutdown(final boolean waitForJobsToCompleteOnShutdown) {
+ this.waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
+ }
+
public int getIdleWaitTime() {
return idleWaitTime;
}
diff --git a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreApplication.java b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreApplication.java
index 7d35a1e..48f1e46 100644
--- a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreApplication.java
+++ b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreApplication.java
@@ -22,7 +22,6 @@ import java.util.Map;
import org.apache.cxf.spring.boot.autoconfigure.openapi.OpenApiAutoConfiguration;
import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
import org.apache.syncope.common.keymaster.client.api.ServiceOps;
-import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStop;
import org.apache.syncope.common.lib.info.SystemInfo;
import org.apache.syncope.core.logic.LogicProperties;
@@ -66,6 +65,7 @@ import org.apache.syncope.core.starter.actuate.SyncopeCoreInfoContributor;
import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter;
import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter;
import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.mail.MailHealthIndicator;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -76,6 +76,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
+import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@@ -87,14 +88,17 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.EnableTransactionManagement;
-@SpringBootApplication(exclude = {
- ErrorMvcAutoConfiguration.class,
- HttpMessageConvertersAutoConfiguration.class,
- OpenApiAutoConfiguration.class,
- DataSourceAutoConfiguration.class,
- DataSourceTransactionManagerAutoConfiguration.class,
- JdbcTemplateAutoConfiguration.class,
- QuartzAutoConfiguration.class }, proxyBeanMethods = false)
+@SpringBootApplication(
+ exclude = {
+ ErrorMvcAutoConfiguration.class,
+ HttpMessageConvertersAutoConfiguration.class,
+ OpenApiAutoConfiguration.class,
+ DataSourceAutoConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ JdbcTemplateAutoConfiguration.class,
+ QuartzAutoConfiguration.class,
+ TaskExecutionAutoConfiguration.class },
+ proxyBeanMethods = false)
@EnableTransactionManagement
public class SyncopeCoreApplication extends SpringBootServletInitializer {
@@ -111,6 +115,24 @@ public class SyncopeCoreApplication extends SpringBootServletInitializer {
@ConditionalOnMissingBean
@Bean
+ public TaskExecutorUnloader taskExecutorUnloader(final ListableBeanFactory beanFactory) {
+ return new TaskExecutorUnloader(beanFactory);
+ }
+
+ @ConditionalOnMissingBean
+ @Bean
+ public SyncopeCoreStart keymasterStart(final DomainHolder domainHolder) {
+ return new SyncopeCoreStart(domainHolder);
+ }
+
+ @ConditionalOnMissingBean
+ @Bean
+ public KeymasterStop keymasterStop(final DomainHolder domainHolder) {
+ return new SyncopeCoreStop(domainHolder);
+ }
+
+ @ConditionalOnMissingBean
+ @Bean
public SyncopeCoreInfoContributor syncopeCoreInfoContributor(
final SecurityProperties securityProperties,
final PersistenceProperties persistenceProperties,
@@ -218,21 +240,11 @@ public class SyncopeCoreApplication extends SpringBootServletInitializer {
return new EntityCacheEndpoint(entityCacheDAO);
}
- @ConditionalOnMissingBean
- @Bean
- public SyncopeCoreStart keymasterStart(final DomainHolder domainHolder) {
- return new SyncopeCoreStart(domainHolder);
- }
-
- @Bean
- public KeymasterStop keymasterStop() {
- return new KeymasterStop(NetworkService.Type.CORE);
- }
-
@Bean
public SyncopeStarterEventListener syncopeCoreEventListener(
@Qualifier("syncopeCoreInfoContributor")
final SyncopeCoreInfoContributor syncopeCoreInfoContributor) {
+
return new DefaultSyncopeStarterEventListener(syncopeCoreInfoContributor);
}
diff --git a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java
index d913674..5a27238 100644
--- a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java
+++ b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java
@@ -30,7 +30,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
/**
- * Take care of all initializations needed by Syncope Core to run up and safe.
+ * Take care of all inits needed by Syncope Core to run up and safe.
*/
public class SyncopeCoreStart extends KeymasterStart implements Ordered {
@@ -55,17 +55,17 @@ public class SyncopeCoreStart extends KeymasterStart implements Ordered {
forEachOrdered(loader -> {
String loaderName = AopUtils.getTargetClass(loader).getName();
- LOG.debug("[{}] Starting initialization", loaderName);
+ LOG.debug("[{}#{}] Starting init", loaderName, loader.getOrder());
loader.load();
domainHolder.getDomains().forEach((domain, datasource) -> {
- LOG.debug("[{}] Starting on domain '{}'", loaderName, domain);
+ LOG.debug("[{}] Starting init on domain '{}'", loaderName, domain);
loader.load(domain, datasource);
- LOG.debug("[{}] Completed on domain '{}'", loaderName, domain);
+ LOG.debug("[{}] Init completed on domain '{}'", loaderName, domain);
});
- LOG.debug("[{}] Initialization completed", loaderName);
+ LOG.debug("[{}] Init completed", loaderName);
});
super.onApplicationEvent(event);
diff --git a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStop.java
similarity index 71%
copy from core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java
copy to core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStop.java
index d913674..d55afc7 100644
--- a/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStart.java
+++ b/core/starter/src/main/java/org/apache/syncope/core/starter/SyncopeCoreStop.java
@@ -20,25 +20,25 @@ package org.apache.syncope.core.starter;
import java.util.Comparator;
import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
-import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStart;
+import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStop;
import org.apache.syncope.core.persistence.api.DomainHolder;
import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
-import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.Ordered;
/**
- * Take care of all initializations needed by Syncope Core to run up and safe.
+ * Take care of all disposal needed by Syncope Core to shut down gracefully..
*/
-public class SyncopeCoreStart extends KeymasterStart implements Ordered {
+public class SyncopeCoreStop extends KeymasterStop implements Ordered {
- private static final Logger LOG = LoggerFactory.getLogger(SyncopeCoreStart.class);
+ private static final Logger LOG = LoggerFactory.getLogger(SyncopeCoreStop.class);
private final DomainHolder domainHolder;
- public SyncopeCoreStart(final DomainHolder domainHolder) {
+ public SyncopeCoreStop(final DomainHolder domainHolder) {
super(NetworkService.Type.CORE);
this.domainHolder = domainHolder;
}
@@ -49,23 +49,23 @@ public class SyncopeCoreStart extends KeymasterStart implements Ordered {
}
@Override
- public void onApplicationEvent(final ContextRefreshedEvent event) {
+ public void onApplicationEvent(final ContextClosedEvent event) {
event.getApplicationContext().getBeansOfType(SyncopeCoreLoader.class).values().stream().
- sorted(Comparator.comparing(SyncopeCoreLoader::getOrder)).
+ sorted(Comparator.comparing(SyncopeCoreLoader::getOrder).reversed()).
forEachOrdered(loader -> {
String loaderName = AopUtils.getTargetClass(loader).getName();
- LOG.debug("[{}] Starting initialization", loaderName);
-
- loader.load();
+ LOG.debug("[{}#{}] Starting dispose", loaderName, loader.getOrder());
domainHolder.getDomains().forEach((domain, datasource) -> {
- LOG.debug("[{}] Starting on domain '{}'", loaderName, domain);
- loader.load(domain, datasource);
- LOG.debug("[{}] Completed on domain '{}'", loaderName, domain);
+ LOG.debug("[{}] Starting dispose on domain '{}'", loaderName, domain);
+ loader.unload(domain);
+ LOG.debug("[{}] Dispose completed on domain '{}'", loaderName, domain);
});
- LOG.debug("[{}] Initialization completed", loaderName);
+ loader.unload();
+
+ LOG.debug("[{}] Dispose completed", loaderName);
});
super.onApplicationEvent(event);
diff --git a/core/starter/src/main/java/org/apache/syncope/core/starter/TaskExecutorUnloader.java b/core/starter/src/main/java/org/apache/syncope/core/starter/TaskExecutorUnloader.java
new file mode 100644
index 0000000..5363b63
--- /dev/null
+++ b/core/starter/src/main/java/org/apache/syncope/core/starter/TaskExecutorUnloader.java
@@ -0,0 +1,64 @@
+/*
+ * 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.starter;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.scheduling.concurrent.ExecutorConfigurationSupport;
+
+public class TaskExecutorUnloader implements SyncopeCoreLoader {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(TaskExecutorUnloader.class);
+
+ protected final ListableBeanFactory beanFactory;
+
+ protected final Map<String, ExecutorConfigurationSupport> tptes = new HashMap<>();
+
+ public TaskExecutorUnloader(final ListableBeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ @Override
+ public int getOrder() {
+ return Integer.MIN_VALUE;
+ }
+
+ @Override
+ public void load() {
+ tptes.putAll(beanFactory.getBeansOfType(ExecutorConfigurationSupport.class));
+ }
+
+ @Override
+ public void unload() {
+ tptes.forEach((name, tpte) -> {
+ LOG.info("Shutting down ThreadPoolTaskExecutor {}...", name);
+ try {
+ tpte.shutdown();
+
+ LOG.info("Successfully shut down ThreadPoolTaskExecutor {}", name);
+ } catch (Exception e) {
+ LOG.error("While shutting down ThreadPoolTaskExecutor {}", name, e);
+ }
+ });
+ }
+}
diff --git a/core/starter/src/main/resources/core.properties b/core/starter/src/main/resources/core.properties
index b2bb571..bee222e 100644
--- a/core/starter/src/main/resources/core.properties
+++ b/core/starter/src/main/resources/core.properties
@@ -34,6 +34,9 @@ management.endpoint.health.show-details=ALWAYS
service.discovery.address=http://localhost:8080/syncope/rest/
+server.shutdown=graceful
+spring.lifecycle.timeout-per-shutdown-phase=30s
+
###############
# Persistence #
###############
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngine.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngine.java
index 1f08981..5651f9d 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngine.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngine.java
@@ -58,7 +58,7 @@ public class DomainProcessEngine implements ProcessEngine {
@Override
public void close() {
- engines.get(AuthContextUtils.getDomain()).close();
+ engines.values().forEach(ProcessEngine::close);
}
@Override
diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java
index 7324d16..25ae72e 100644
--- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java
+++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/support/DomainProcessEngineFactoryBean.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import javax.annotation.PreDestroy;
import javax.sql.DataSource;
import org.apache.syncope.core.persistence.api.DomainHolder;
import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
@@ -33,7 +34,6 @@ import org.flowable.idm.spring.SpringIdmEngineConfiguration;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.PlatformTransactionManager;
@@ -42,8 +42,7 @@ import org.springframework.transaction.PlatformTransactionManager;
* Spring factory for {@link DomainProcessEngine} which takes the provided {@link SpringProcessEngineConfiguration} as
* template for each of the configured Syncope domains.
*/
-public class DomainProcessEngineFactoryBean
- implements FactoryBean<DomainProcessEngine>, DisposableBean, SyncopeCoreLoader {
+public class DomainProcessEngineFactoryBean implements FactoryBean<DomainProcessEngine>, SyncopeCoreLoader {
private static final Logger LOG = LoggerFactory.getLogger(DomainProcessEngineFactoryBean.class);
@@ -120,8 +119,8 @@ public class DomainProcessEngineFactoryBean
return true;
}
- @Override
- public void destroy() throws Exception {
+ @PreDestroy
+ public void preDestroy() {
if (engine != null) {
engine.close();
}
diff --git a/fit/core-reference/src/main/resources/core-embedded.properties b/fit/core-reference/src/main/resources/core-embedded.properties
index 6ace161..3926b09 100644
--- a/fit/core-reference/src/main/resources/core-embedded.properties
+++ b/fit/core-reference/src/main/resources/core-embedded.properties
@@ -63,6 +63,7 @@ persistence.domain[1].adminCipherAlgorithm=SHA
provisioning.quartz.delegate=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
provisioning.quartz.sql=tables_h2.sql
+provisioning.quartz.waitForJobsToCompleteOnShutdown=false
provisioning.connIdLocation=${connid.location},\
connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}
diff --git a/pom.xml b/pom.xml
index 3294e3c..a33fe6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -418,8 +418,6 @@ under the License.
<jasypt.version>1.9.3</jasypt.version>
- <quartz.version>2.3.2</quartz.version>
-
<cocoon.version>3.0.0-alpha-3</cocoon.version>
<groovy.version>4.0.1</groovy.version>
@@ -920,6 +918,18 @@ under the License.
<dependency>
<groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-quartz</artifactId>
+ <version>${spring-boot.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<exclusions>
<exclusion>
@@ -1159,26 +1169,6 @@ under the License.
</dependency>
<dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>${quartz.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.zaxxer</groupId>
- <artifactId>HikariCP-java7</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.mchange</groupId>
- <artifactId>mchange-commons-java</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
<groupId>org.apache.cocoon.sax</groupId>
<artifactId>cocoon-sax</artifactId>
<version>${cocoon.version}</version>
diff --git a/sra/src/main/resources/sra.properties b/sra/src/main/resources/sra.properties
index 551efc7..1e42d3e 100644
--- a/sra/src/main/resources/sra.properties
+++ b/sra/src/main/resources/sra.properties
@@ -27,6 +27,9 @@ spring.cloud.discovery.client.health-indicator.enabled=false
service.discovery.address=http://localhost:8080/
+server.shutdown=graceful
+spring.lifecycle.timeout-per-shutdown-phase=30s
+
logging.config=classpath:log4j2.xml
sra.anonymousUser=${anonymousUser}
diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties
index e2418d7..bd29731 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -58,6 +58,9 @@ spring.main.lazy-initialization=false
service.discovery.address=http://localhost:8080/syncope-wa/
+server.shutdown=graceful
+spring.lifecycle.timeout-per-shutdown-phase=30s
+
wa.anonymousUser=${anonymousUser}
wa.anonymousKey=${anonymousKey}