This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new a316f1648f NIFI-15404 Scheduled Security Maintenance Tasks with
Virtual Threads
a316f1648f is described below
commit a316f1648f46c5b0132a95a57b546d3062b23762
Author: exceptionfactory <[email protected]>
AuthorDate: Mon Dec 29 17:34:32 2025 -0600
NIFI-15404 Scheduled Security Maintenance Tasks with Virtual Threads
- Added Task Scheduler Configuration with Virtual Threads configured
- Replaced separate Thread Pools with shared Task Scheduler
Signed-off-by: Pierre Villard <[email protected]>
This closes #10708.
---
.../configuration/SslContextConfiguration.java | 25 +++++--------
.../configuration/TaskSchedulerConfiguration.java | 43 ++++++++++++++++++++++
.../JwtAuthenticationSecurityConfiguration.java | 24 ++++--------
.../configuration/OidcSecurityConfiguration.java | 20 +++-------
4 files changed, 66 insertions(+), 46 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/SslContextConfiguration.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/SslContextConfiguration.java
index 85a14f5462..8323b53bc3 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/SslContextConfiguration.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/SslContextConfiguration.java
@@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.TaskScheduler;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509ExtendedKeyManager;
@@ -79,11 +79,18 @@ public class SslContextConfiguration {
private NiFiProperties properties;
+ private TaskScheduler taskScheduler;
+
@Autowired
public void setProperties(final NiFiProperties properties) {
this.properties = properties;
}
+ @Autowired
+ public void setTaskScheduler(final TaskScheduler taskScheduler) {
+ this.taskScheduler = taskScheduler;
+ }
+
@Bean
public SSLContext sslContext() {
return FrameworkSslContextHolder.getSslContext();
@@ -123,7 +130,7 @@ public class SslContextConfiguration {
final WatchService watchService = storeWatchService();
command = new WatchServiceMonitorCommand(watchService,
changedPathListener);
- watchServiceScheduler().scheduleAtFixedRate(command,
reloadDuration);
+ taskScheduler.scheduleAtFixedRate(command, reloadDuration);
logger.info("Scheduled Security Store Monitor with Duration
[{}]", reloadDuration);
} else {
throw new IllegalStateException("Key Manager Listener or Trust
Manager Listener not found");
@@ -134,20 +141,6 @@ public class SslContextConfiguration {
return command;
}
- @Bean
- public ThreadPoolTaskScheduler watchServiceScheduler() {
- final ThreadPoolTaskScheduler scheduler;
-
- if (isReloadEnabled()) {
- scheduler = new ThreadPoolTaskScheduler();
- scheduler.setThreadNamePrefix("Security Store Monitor ");
- } else {
- scheduler = null;
- }
-
- return scheduler;
- }
-
@Bean
public WatchService storeWatchService() {
final WatchService watchService;
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/TaskSchedulerConfiguration.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/TaskSchedulerConfiguration.java
new file mode 100644
index 0000000000..31487387e3
--- /dev/null
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/framework/configuration/TaskSchedulerConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ * 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.nifi.framework.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+/**
+ * Task Scheduler Configuration class for Spring Application
+ */
+@Configuration
+public class TaskSchedulerConfiguration {
+ private static final String APPLICATION_THREAD_NAME_PREFIX =
"ApplicationThread-";
+
+ /**
+ * Application Task Scheduler configured with Virtual Threads for
infrequent operations
+ *
+ * @return Task Scheduler
+ */
+ @Bean
+ public TaskScheduler taskScheduler() {
+ final ThreadPoolTaskScheduler taskScheduler = new
ThreadPoolTaskScheduler();
+ taskScheduler.setThreadNamePrefix(APPLICATION_THREAD_NAME_PREFIX);
+ taskScheduler.setVirtualThreads(true);
+ return taskScheduler;
+ }
+}
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
index 8a6c26f998..c9390633b2 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/JwtAuthenticationSecurityConfiguration.java
@@ -39,7 +39,7 @@ import
org.apache.nifi.web.security.jwt.revocation.command.RevocationExpirationC
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.TaskScheduler;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.jwt.JwtDecoder;
@@ -59,6 +59,8 @@ public class JwtAuthenticationSecurityConfiguration {
private final NiFiProperties niFiProperties;
+ private final TaskScheduler taskScheduler;
+
private final Authorizer authorizer;
private final JwtDecoder jwtDecoder;
@@ -74,6 +76,7 @@ public class JwtAuthenticationSecurityConfiguration {
@Autowired
public JwtAuthenticationSecurityConfiguration(
final NiFiProperties niFiProperties,
+ final TaskScheduler taskScheduler,
final Authorizer authorizer,
final JwtDecoder jwtDecoder,
final JwtRevocationService jwtRevocationService,
@@ -81,6 +84,7 @@ public class JwtAuthenticationSecurityConfiguration {
final VerificationKeyService verificationKeyService
) {
this.niFiProperties = niFiProperties;
+ this.taskScheduler = taskScheduler;
this.authorizer = authorizer;
this.jwtDecoder = jwtDecoder;
this.jwtRevocationService = jwtRevocationService;
@@ -192,7 +196,7 @@ public class JwtAuthenticationSecurityConfiguration {
@Bean
public KeyGenerationCommand keyGenerationCommand(final KeyPairGenerator
keyPairGenerator) {
final KeyGenerationCommand command = new
KeyGenerationCommand(jwsSignerProvider(), verificationKeySelector,
keyPairGenerator);
- commandScheduler().scheduleAtFixedRate(command, keyRotationPeriod);
+ taskScheduler.scheduleAtFixedRate(command, keyRotationPeriod);
return command;
}
@@ -204,7 +208,7 @@ public class JwtAuthenticationSecurityConfiguration {
@Bean
public KeyExpirationCommand keyExpirationCommand() {
final KeyExpirationCommand command = new
KeyExpirationCommand(verificationKeyService);
- commandScheduler().scheduleAtFixedRate(command, keyRotationPeriod);
+ taskScheduler.scheduleAtFixedRate(command, keyRotationPeriod);
return command;
}
@@ -216,19 +220,7 @@ public class JwtAuthenticationSecurityConfiguration {
@Bean
public RevocationExpirationCommand revocationExpirationCommand() {
final RevocationExpirationCommand command = new
RevocationExpirationCommand(jwtRevocationService);
- commandScheduler().scheduleAtFixedRate(command, keyRotationPeriod);
+ taskScheduler.scheduleAtFixedRate(command, keyRotationPeriod);
return command;
}
-
- /**
- * Command Scheduler responsible for running commands in background thread
- *
- * @return Thread Pool Task Scheduler with named threads
- */
- @Bean
- public ThreadPoolTaskScheduler commandScheduler() {
- final ThreadPoolTaskScheduler scheduler = new
ThreadPoolTaskScheduler();
-
scheduler.setThreadNamePrefix(JwtAuthenticationSecurityConfiguration.class.getSimpleName());
- return scheduler;
- }
}
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/OidcSecurityConfiguration.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/OidcSecurityConfiguration.java
index 901519e67c..211975650e 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/OidcSecurityConfiguration.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/OidcSecurityConfiguration.java
@@ -47,7 +47,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.TaskScheduler;
import org.springframework.security.authentication.AuthenticationManager;
import
org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import
org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
@@ -95,6 +95,8 @@ public class OidcSecurityConfiguration {
private final NiFiProperties properties;
+ private final TaskScheduler taskScheduler;
+
private final StateManagerProvider stateManagerProvider;
private final PropertyEncryptor propertyEncryptor;
@@ -118,6 +120,7 @@ public class OidcSecurityConfiguration {
@Autowired
public OidcSecurityConfiguration(
final NiFiProperties properties,
+ final TaskScheduler taskScheduler,
final StateManagerProvider stateManagerProvider,
final PropertyEncryptor propertyEncryptor,
final BearerTokenProvider bearerTokenProvider,
@@ -132,6 +135,7 @@ public class OidcSecurityConfiguration {
final LogoutRequestManager logoutRequestManager
) {
this.properties = Objects.requireNonNull(properties, "Properties
required");
+ this.taskScheduler = Objects.requireNonNull(taskScheduler, "Task
Scheduler required");
this.stateManagerProvider =
Objects.requireNonNull(stateManagerProvider, "State Manager Provider required");
this.propertyEncryptor = Objects.requireNonNull(propertyEncryptor,
"Property Encryptor required");
this.bearerTokenProvider = Objects.requireNonNull(bearerTokenProvider,
"Bearer Token Provider required");
@@ -313,22 +317,10 @@ public class OidcSecurityConfiguration {
@Bean
public AuthorizedClientExpirationCommand
authorizedClientExpirationCommand() {
final AuthorizedClientExpirationCommand command = new
AuthorizedClientExpirationCommand(authorizedClientRepository(),
tokenRevocationResponseClient());
- oidcCommandScheduler().scheduleAtFixedRate(command, keyRotationPeriod);
+ taskScheduler.scheduleAtFixedRate(command, keyRotationPeriod);
return command;
}
- /**
- * Command Scheduled for OpenID Connect operations
- *
- * @return Thread Pool Task Executor
- */
- @Bean
- public ThreadPoolTaskScheduler oidcCommandScheduler() {
- final ThreadPoolTaskScheduler scheduler = new
ThreadPoolTaskScheduler();
-
scheduler.setThreadNamePrefix(OidcSecurityConfiguration.class.getSimpleName());
- return scheduler;
- }
-
/**
* Authorized Client Converter for OpenID Connect Tokens supporting
serialization of OpenID Connect Tokens
*