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:19 UTC

[syncope] branch 2_1_X updated (5f70d0b -> f18da0d)

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

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


    from 5f70d0b  Fixing reportet package location
     new 112a34f  Various upgrades
     new f18da0d  [SYNCOPE-1644] Now relying on SpringBeanJobFactory which creates the bean and immediately executes it

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


Summary of changes:
 .../core/provisioning/api/job/JobManager.java      |  4 +
 .../java/job/AutowiringSpringBeanJobFactory.java   | 85 ----------------------
 .../core/provisioning/java/job/JobManagerImpl.java | 78 +++++---------------
 .../java/job/SyncopeSpringBeanJobFactory.java      | 45 ++++++++++++
 .../src/main/resources/provisioningContext.xml     |  2 +-
 .../client/ElasticsearchIndexManager.java          | 47 +++++++++---
 .../jpa/dao/ElasticsearchAnySearchDAO.java         | 42 +++++------
 .../jpa/dao/ElasticsearchAnySearchDAOTest.java     | 15 +++-
 .../java/job/ElasticsearchReindex.java             | 33 +++++----
 .../org/apache/syncope/fit/core/GroupITCase.java   |  4 +
 .../apache/syncope/fit/core/PullTaskITCase.java    |  3 +
 pom.xml                                            | 28 +++----
 12 files changed, 173 insertions(+), 213 deletions(-)
 delete mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AutowiringSpringBeanJobFactory.java
 create mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SyncopeSpringBeanJobFactory.java

[syncope] 02/02: [SYNCOPE-1644] Now relying on SpringBeanJobFactory which creates the bean and immediately executes it

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

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

commit f18da0d71fda4892466ea707cf297dc0f789f7ef
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 +
 .../java/job/AutowiringSpringBeanJobFactory.java   | 85 ----------------------
 .../core/provisioning/java/job/JobManagerImpl.java | 78 +++++---------------
 .../java/job/SyncopeSpringBeanJobFactory.java      | 45 ++++++++++++
 .../src/main/resources/provisioningContext.xml     |  2 +-
 5 files changed, 67 insertions(+), 147 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 ddd641f..8b8ab9b 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";
 
     JobKey NOTIFICATION_JOB = new JobKey("notificationJob", Scheduler.DEFAULT_GROUP);
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/JobManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
index 274153e..13a5b21 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
@@ -36,7 +36,6 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
-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.SyncopeLoader;
 import org.apache.syncope.core.persistence.api.DomainsHolder;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -62,9 +60,7 @@ 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.annotation.Autowired;
-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;
@@ -77,6 +73,7 @@ import org.apache.syncope.core.provisioning.java.job.notification.NotificationJo
 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.quartz.Trigger;
 
 public class JobManagerImpl implements JobManager, SyncopeLoader {
 
@@ -144,7 +141,7 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
     }
 
     private 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 {
@@ -157,34 +154,28 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         // 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);
                 }
             }
 
@@ -192,38 +183,10 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         }
     }
 
-    @SuppressWarnings("unchecked")
-    private <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)
             throws SchedulerException {
 
-        TaskJob job = createSpringBean(TaskJob.class);
-        job.setTaskKey(task.getKey());
-
         Implementation jobDelegate = task.getJobDelegate() == null
                 ? task instanceof PullTask
                         ? implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
@@ -241,12 +204,13 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         }
 
         Map<String, Object> jobMap = new HashMap<>();
+        jobMap.put(JobManager.TASK_KEY, task.getKey());
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
         jobMap.put(TaskJob.DELEGATE_IMPLEMENTATION, jobDelegate.getKey());
 
         registerJob(
                 JobNamer.getJobKey(task).getName(),
-                job,
+                TaskJob.class,
                 task.getCronExpression(),
                 startAt,
                 jobMap);
@@ -257,13 +221,11 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
     public void register(final Report report, final Date startAt, final long interruptMaxRetries)
             throws SchedulerException {
 
-        ReportJob job = createSpringBean(ReportJob.class);
-        job.setReportKey(report.getKey());
-
         Map<String, Object> jobMap = new HashMap<>();
+        jobMap.put(JobManager.REPORT_KEY, report.getKey());
         jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
 
-        registerJob(JobNamer.getJobKey(report).getName(), job, report.getCronExpression(), startAt, jobMap);
+        registerJob(JobNamer.getJobKey(report).getName(), ReportJob.class, report.getCronExpression(), startAt, jobMap);
     }
 
     private void unregisterJob(final String jobName) {
@@ -273,10 +235,6 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         } catch (SchedulerException e) {
             LOG.error("Could not remove job " + jobName, e);
         }
-
-        if (ApplicationContextProvider.getBeanFactory().containsSingleton(jobName)) {
-            ApplicationContextProvider.getBeanFactory().destroySingleton(jobName);
-        }
     }
 
     @Override
@@ -379,10 +337,9 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
                     NotificationJob.class.getSimpleName(), conf.getLeft());
 
             try {
-                NotificationJob job = createSpringBean(NotificationJob.class);
                 registerJob(
                         NOTIFICATION_JOB.getName(),
-                        job,
+                        NotificationJob.class,
                         conf.getLeft(),
                         null,
                         jobMap);
@@ -394,10 +351,9 @@ public class JobManagerImpl implements JobManager, SyncopeLoader {
         // 4. SystemLoadReporterJob (fixed schedule, every minute)
         LOG.debug("Registering {}", SystemLoadReporterJob.class);
         try {
-            SystemLoadReporterJob job = createSpringBean(SystemLoadReporterJob.class);
             registerJob(
                     "systemLoadReporterJob",
-                    job,
+                    SystemLoadReporterJob.class,
                     "0 * * * * ?",
                     null,
                     jobMap);
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;
+    }
+}
diff --git a/core/provisioning-java/src/main/resources/provisioningContext.xml b/core/provisioning-java/src/main/resources/provisioningContext.xml
index b905294..13f4d9f 100644
--- a/core/provisioning-java/src/main/resources/provisioningContext.xml
+++ b/core/provisioning-java/src/main/resources/provisioningContext.xml
@@ -77,7 +77,7 @@ under the License.
     <property name="dataSource" ref="MasterDataSource"/>
     <property name="transactionManager" ref="MasterTransactionManager"/>
     <property name="jobFactory">
-      <bean class="org.apache.syncope.core.provisioning.java.job.AutowiringSpringBeanJobFactory"/>
+      <bean class="org.apache.syncope.core.provisioning.java.job.SyncopeSpringBeanJobFactory"/>
     </property>
     <property name="quartzProperties">
       <props>

[syncope] 01/02: Various upgrades

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

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

commit 112a34feb38080665659f5a93bdf3992512a563c
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Mon Sep 27 11:36:16 2021 +0200

    Various upgrades
---
 .../client/ElasticsearchIndexManager.java          | 47 ++++++++++++++++------
 .../jpa/dao/ElasticsearchAnySearchDAO.java         | 42 +++++++++----------
 .../jpa/dao/ElasticsearchAnySearchDAOTest.java     | 15 ++++++-
 .../java/job/ElasticsearchReindex.java             | 33 ++++++++-------
 .../org/apache/syncope/fit/core/GroupITCase.java   |  4 ++
 .../apache/syncope/fit/core/PullTaskITCase.java    |  3 ++
 pom.xml                                            | 28 ++++++-------
 7 files changed, 106 insertions(+), 66 deletions(-)

diff --git a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchIndexManager.java b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchIndexManager.java
index bcdbb91..b313dca 100644
--- a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchIndexManager.java
+++ b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchIndexManager.java
@@ -19,12 +19,12 @@
 package org.apache.syncope.ext.elasticsearch.client;
 
 import java.io.IOException;
-import java.util.concurrent.ExecutionException;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.provisioning.api.event.AnyCreatedUpdatedEvent;
 import org.apache.syncope.core.provisioning.api.event.AnyDeletedEvent;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.delete.DeleteRequest;
 import org.elasticsearch.action.delete.DeleteResponse;
@@ -44,7 +44,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.event.TransactionalEventListener;
 
 /**
@@ -54,11 +53,17 @@ public class ElasticsearchIndexManager {
 
     private static final Logger LOG = LoggerFactory.getLogger(ElasticsearchIndexManager.class);
 
-    @Autowired
-    private RestHighLevelClient client;
+    protected final RestHighLevelClient client;
 
-    @Autowired
-    private ElasticsearchUtils elasticsearchUtils;
+    protected final ElasticsearchUtils elasticsearchUtils;
+
+    public ElasticsearchIndexManager(
+            final RestHighLevelClient client,
+            final ElasticsearchUtils elasticsearchUtils) {
+
+        this.client = client;
+        this.elasticsearchUtils = elasticsearchUtils;
+    }
 
     public boolean existsIndex(final String domain, final AnyTypeKind kind) throws IOException {
         return client.indices().exists(
@@ -104,19 +109,37 @@ public class ElasticsearchIndexManager {
                 endObject();
     }
 
-    public void createIndex(
+    protected CreateIndexResponse doCreateIndex(
             final String domain,
             final AnyTypeKind kind,
             final XContentBuilder settings,
-            final XContentBuilder mapping)
-            throws InterruptedException, ExecutionException, IOException {
+            final XContentBuilder mapping) throws IOException {
 
-        CreateIndexResponse response = client.indices().create(
+        return client.indices().create(
                 new CreateIndexRequest(ElasticsearchUtils.getContextDomainName(domain, kind)).
                         settings(settings).
                         mapping(mapping), RequestOptions.DEFAULT);
-        LOG.debug("Successfully created {} for {}: {}",
-                ElasticsearchUtils.getContextDomainName(domain, kind), kind.name(), response);
+    }
+
+    public void createIndex(
+            final String domain,
+            final AnyTypeKind kind,
+            final XContentBuilder settings,
+            final XContentBuilder mapping)
+            throws IOException {
+
+        try {
+            CreateIndexResponse response = doCreateIndex(domain, kind, settings, mapping);
+
+            LOG.debug("Successfully created {} for {}: {}",
+                    ElasticsearchUtils.getContextDomainName(domain, kind), kind.name(), response);
+        } catch (ElasticsearchStatusException e) {
+            LOG.debug("Could not create index {} because it already exists",
+                    ElasticsearchUtils.getContextDomainName(domain, kind), e);
+
+            removeIndex(domain, kind);
+            doCreateIndex(domain, kind, settings, mapping);
+        }
     }
 
     public void removeIndex(final String domain, final AnyTypeKind kind) throws IOException {
diff --git a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
index d9fef1d..a5b2d59 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
+++ b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
@@ -63,6 +63,7 @@ import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.client.RequestOptions;
 import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.core.CountRequest;
 import org.elasticsearch.index.query.DisMaxQueryBuilder;
 import org.elasticsearch.index.query.MatchAllQueryBuilder;
 import org.elasticsearch.index.query.MatchNoneQueryBuilder;
@@ -144,13 +145,10 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
                 groupOwners);
     }
 
-    protected SearchRequest searchRequest(
+    protected QueryBuilder getQueryBuilder(
             final Set<String> adminRealms,
             final SearchCond cond,
-            final AnyTypeKind kind,
-            final int from,
-            final int size,
-            final List<SortBuilder<?>> sortBuilders) {
+            final AnyTypeKind kind) {
 
         Triple<Optional<QueryBuilder>, Set<String>, Set<String>> filter = getAdminRealmsFilter(kind, adminRealms);
         QueryBuilder queryBuilder;
@@ -166,22 +164,17 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
             }
         }
 
-        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().
-                query(queryBuilder).
-                from(from).
-                size(size);
-        sortBuilders.forEach(sourceBuilder::sort);
-
-        return new SearchRequest(ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), kind)).
-                searchType(SearchType.QUERY_THEN_FETCH).
-                source(sourceBuilder);
+        return queryBuilder;
     }
 
     @Override
     protected int doCount(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind kind) {
-        SearchRequest request = searchRequest(adminRealms, cond, kind, 0, 0, Collections.emptyList());
+        CountRequest request = new CountRequest(
+                ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), kind)).
+                query(getQueryBuilder(adminRealms, cond, kind));
+
         try {
-            return (int) client.search(request, RequestOptions.DEFAULT).getHits().getTotalHits().value;
+            return (int) client.count(request, RequestOptions.DEFAULT).getCount();
         } catch (IOException e) {
             LOG.error("Search error", e);
             return 0;
@@ -229,13 +222,16 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
             final List<OrderByClause> orderBy,
             final AnyTypeKind kind) {
 
-        SearchRequest request = searchRequest(
-                adminRealms,
-                cond,
-                kind,
-                (itemsPerPage * (page <= 0 ? 0 : page - 1)),
-                (itemsPerPage < 0 ? elasticsearchUtils.getIndexMaxResultWindow() : itemsPerPage),
-                sortBuilders(kind, orderBy));
+        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().
+                query(getQueryBuilder(adminRealms, cond, kind)).
+                from(itemsPerPage * (page <= 0 ? 0 : page - 1)).
+                size(itemsPerPage < 0 ? elasticsearchUtils.getIndexMaxResultWindow() : itemsPerPage);
+        sortBuilders(kind, orderBy).forEach(sourceBuilder::sort);
+
+        SearchRequest request = new SearchRequest(
+                ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), kind)).
+                searchType(SearchType.QUERY_THEN_FETCH).
+                source(sourceBuilder);
 
         SearchHit[] esResult = null;
         try {
diff --git a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
index ca83d90..51a7236 100644
--- a/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
+++ b/ext/elasticsearch/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAOTest.java
@@ -46,10 +46,13 @@ import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.ext.elasticsearch.client.ElasticsearchUtils;
 import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
@@ -153,8 +156,16 @@ public class ElasticsearchAnySearchDAOTest {
             AnyCond anyCond = new AnyCond(AttrCond.Type.ISNOTNULL);
             anyCond.setSchema("id");
 
-            SearchRequest searchRequest = searchDAO.searchRequest(
-                    adminRealms, SearchCond.getLeaf(anyCond), AnyTypeKind.USER, 1, 10, Collections.emptyList());
+            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().
+                    query(searchDAO.getQueryBuilder(adminRealms, SearchCond.getLeaf(anyCond), AnyTypeKind.USER)).
+                    from(1).
+                    size(10);
+            searchDAO.sortBuilders(AnyTypeKind.USER, Collections.emptyList()).forEach(sourceBuilder::sort);
+
+            SearchRequest searchRequest = new SearchRequest(
+                    ElasticsearchUtils.getContextDomainName(AuthContextUtils.getDomain(), AnyTypeKind.USER)).
+                    searchType(SearchType.QUERY_THEN_FETCH).
+                    source(sourceBuilder);
 
             assertEquals(
                     QueryBuilders.boolQuery().
diff --git a/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java b/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
index 3738ada..edc9dbc 100644
--- a/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
+++ b/ext/elasticsearch/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/ElasticsearchReindex.java
@@ -90,21 +90,12 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
             LOG.debug("Start rebuilding indexes");
 
             try {
-                if (indexManager.existsIndex(AuthContextUtils.getDomain(), AnyTypeKind.USER)) {
-                    indexManager.removeIndex(AuthContextUtils.getDomain(), AnyTypeKind.USER);
-                }
                 indexManager.createIndex(
                         AuthContextUtils.getDomain(), AnyTypeKind.USER, userSettings(), userMapping());
 
-                if (indexManager.existsIndex(AuthContextUtils.getDomain(), AnyTypeKind.GROUP)) {
-                    indexManager.removeIndex(AuthContextUtils.getDomain(), AnyTypeKind.GROUP);
-                }
                 indexManager.createIndex(
                         AuthContextUtils.getDomain(), AnyTypeKind.GROUP, groupSettings(), groupMapping());
 
-                if (indexManager.existsIndex(AuthContextUtils.getDomain(), AnyTypeKind.ANY_OBJECT)) {
-                    indexManager.removeIndex(AuthContextUtils.getDomain(), AnyTypeKind.ANY_OBJECT);
-                }
                 indexManager.createIndex(
                         AuthContextUtils.getDomain(), AnyTypeKind.ANY_OBJECT, anyObjectSettings(), anyObjectMapping());
 
@@ -116,8 +107,12 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                                         AuthContextUtils.getDomain(), AnyTypeKind.USER)).
                                 id(user).
                                 source(utils.builder(userDAO.find(user), AuthContextUtils.getDomain()));
-                        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
-                        LOG.debug("Index successfully created for {}: {}", user, response);
+                        try {
+                            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
+                            LOG.debug("Index successfully created for {}: {}", user, response);
+                        } catch (Exception e) {
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.USER, user);
+                        }
                     }
                 }
 
@@ -129,8 +124,12 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                                         AuthContextUtils.getDomain(), AnyTypeKind.GROUP)).
                                 id(group).
                                 source(utils.builder(groupDAO.find(group), AuthContextUtils.getDomain()));
-                        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
-                        LOG.debug("Index successfully created for {}: {}", group, response);
+                        try {
+                            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
+                            LOG.debug("Index successfully created for {}: {}", group, response);
+                        } catch (Exception e) {
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.GROUP, group);
+                        }
                     }
                 }
 
@@ -142,8 +141,12 @@ public class ElasticsearchReindex extends AbstractSchedTaskJobDelegate {
                                         AuthContextUtils.getDomain(), AnyTypeKind.ANY_OBJECT)).
                                 id(anyObject).
                                 source(utils.builder(anyObjectDAO.find(anyObject), AuthContextUtils.getDomain()));
-                        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
-                        LOG.debug("Index successfully created for {}: {}", anyObject, response);
+                        try {
+                            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
+                            LOG.debug("Index successfully created for {}: {}", anyObject, response);
+                        } catch (Exception e) {
+                            LOG.error("Could not create index for {} {}", AnyTypeKind.ANY_OBJECT, anyObject);
+                        }
                     }
                 }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index 7069283..6a7e68d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
 
 import java.io.IOException;
 import java.security.AccessControlException;
@@ -93,6 +94,7 @@ import org.apache.syncope.common.rest.api.service.SyncopeService;
 import org.apache.syncope.core.provisioning.java.job.TaskJob;
 import org.apache.syncope.core.spring.security.Encryptor;
 import org.apache.syncope.fit.AbstractITCase;
+import org.apache.syncope.fit.ElasticsearchDetector;
 import org.junit.jupiter.api.Test;
 
 public class GroupITCase extends AbstractITCase {
@@ -928,6 +930,8 @@ public class GroupITCase extends AbstractITCase {
 
     @Test
     public void provisionMembers() throws InterruptedException {
+        assumeFalse(ElasticsearchDetector.isElasticSearchEnabled(syncopeService));
+
         // 1. create group without resources
         GroupTO groupTO = getBasicSampleTO("forProvision");
         groupTO = createGroup(groupTO).getEntity();
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index 1fded4a..f66f8ba 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -98,6 +98,7 @@ import org.apache.syncope.common.rest.api.service.TaskService;
 import org.apache.syncope.core.provisioning.java.pushpull.DBPasswordPullActions;
 import org.apache.syncope.core.provisioning.java.pushpull.LDAPPasswordPullActions;
 import org.apache.syncope.core.spring.security.Encryptor;
+import org.apache.syncope.fit.ElasticsearchDetector;
 import org.apache.syncope.fit.FlowableDetector;
 import org.apache.syncope.fit.core.reference.TestPullActions;
 import org.identityconnectors.framework.common.objects.Name;
@@ -189,6 +190,8 @@ public class PullTaskITCase extends AbstractTaskITCase {
 
     @Test
     public void fromCSV() throws Exception {
+        assumeFalse(ElasticsearchDetector.isElasticSearchEnabled(syncopeService));
+
         removeTestUsers();
 
         // Attemp to reset CSV content
diff --git a/pom.xml b/pom.xml
index 5bb5355..1825222 100644
--- a/pom.xml
+++ b/pom.xml
@@ -409,7 +409,7 @@ under the License.
 
     <jackson.version>2.11.4</jackson.version>
 
-    <spring.version>5.2.16.RELEASE</spring.version>
+    <spring.version>5.2.17.RELEASE</spring.version>
     <spring-security.version>5.2.12.RELEASE</spring-security.version>
 
     <openjpa.version>3.2.0</openjpa.version>
@@ -431,7 +431,7 @@ under the License.
     <slf4j.version>1.7.32</slf4j.version>
     <opensaml.version>3.3.1</opensaml.version>
 
-    <elasticsearch.version>7.14.0</elasticsearch.version>
+    <elasticsearch.version>7.15.0</elasticsearch.version>
 
     <apacheds.version>2.0.0.AM26</apacheds.version>
     <apachedirapi.version>2.0.0</apachedirapi.version>
@@ -459,7 +459,7 @@ under the License.
     <log.directory>${project.build.directory}/log</log.directory>
 
     <swagger-core.version>2.0.10</swagger-core.version>    
-    <swagger-ui.version>3.51.2</swagger-ui.version>
+    <swagger-ui.version>3.52.1</swagger-ui.version>
     <guava.version>29.0-jre</guava.version>
 
     <jquery.version>3.4.1</jquery.version>
@@ -504,7 +504,7 @@ under the License.
     <maven-invoker.version>3.0.1</maven-invoker.version>
 
     <tycho.version>1.7.0</tycho.version>
-    <netbeans.version>RELEASE124</netbeans.version>
+    <netbeans.version>RELEASE125</netbeans.version>
 
     <antlr4.version>4.9.2</antlr4.version>
 
@@ -2092,7 +2092,7 @@ under the License.
             <dependency>
               <groupId>com.puppycrawl.tools</groupId>
               <artifactId>checkstyle</artifactId>
-              <version>8.45.1</version>
+              <version>9.0</version>
             </dependency>
           </dependencies>
           <configuration>
@@ -2490,20 +2490,20 @@ under the License.
             <link>http://www.slf4j.org/api/</link>
             <link>http://connid.tirasa.net/apidocs/1.5/</link>
             <link>http://cxf.apache.org/javadoc/latest-3.2.x/</link>
-            <link>http://fasterxml.github.io/jackson-core/javadoc/2.10/</link>
-            <link>http://fasterxml.github.io/jackson-databind/javadoc/2.10/</link>
-            <link>http://fasterxml.github.io/jackson-annotations/javadoc/2.10/</link>
-            <link>http://fasterxml.github.io/jackson-dataformats-text/javadoc/yaml/2.10/</link>
-            <link>http://fasterxml.github.io/jackson-dataformats-text/javadoc/csv/2.10/</link>
-            <link>http://www.javadoc.io/doc/org.apache.camel/camel-core/2.24.2/</link>
-            <link>http://www.javadoc.io/doc/org.apache.camel/camel-spring/2.24.2/</link>
+            <link>http://fasterxml.github.io/jackson-core/javadoc/2.11/</link>
+            <link>http://fasterxml.github.io/jackson-databind/javadoc/2.11/</link>
+            <link>http://fasterxml.github.io/jackson-annotations/javadoc/2.11/</link>
+            <link>http://fasterxml.github.io/jackson-dataformats-text/javadoc/yaml/2.11/</link>
+            <link>http://fasterxml.github.io/jackson-dataformats-text/javadoc/csv/2.11/</link>
+            <link>http://www.javadoc.io/doc/org.apache.camel/camel-core/2.25.4/</link>
+            <link>http://www.javadoc.io/doc/org.apache.camel/camel-spring/2.25.4/</link>
             <link>https://ci.apache.org/projects/wicket/apidocs/8.x/</link>
             <link>https://commons.apache.org/proper/commons-lang/javadocs/api-release/</link>
             <link>https://commons.apache.org/proper/commons-io/javadocs/api-2.6/</link>
             <link>https://commons.apache.org/proper/commons-jexl/apidocs/</link>
             <link>https://tika.apache.org/1.25/api/</link>
-            <link>https://docs.spring.io/spring/docs/5.1.x/javadoc-api/</link>
-            <link>https://docs.spring.io/spring-security/site/docs/5.1.x/api/</link>
+            <link>https://docs.spring.io/spring/docs/5.2.x/javadoc-api/</link>
+            <link>https://docs.spring.io/spring-security/site/docs/5.2.x/api/</link>
             <link>http://www.flowable.org/docs/javadocs/</link>
             <link>https://build.shibboleth.net/nexus/content/sites/site/java-opensaml/3.3.1/apidocs/</link>
             <link>http://docs.swagger.io/swagger-core/v2.0.10/apidocs/</link>