From c67dffa8d439ada6fcaf86215cf54092455c8877 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 5 Nov 2025 03:27:04 +0000
Subject: [PATCH 1/4] Initial plan
From 862857ee594cd305461587b83e2d6278557a2217 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 5 Nov 2025 03:43:58 +0000
Subject: [PATCH 2/4] Add ServiceBusJmsConnectionFactoryClassProvider interface
for custom factory injection
Co-authored-by: saragluna <31124698+saragluna@users.noreply.github.com>
---
.../CHANGELOG.md | 2 +
...eBusJmsConnectionFactoryConfiguration.java | 9 ++-
...eBusJmsConnectionFactoryClassProvider.java | 24 ++++++
...msConnectionFactoryConfigurationTests.java | 75 +++++++++++++++++++
4 files changed, 109 insertions(+), 1 deletion(-)
create mode 100644 sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md b/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md
index 65d97b19149e..06bf76142485 100644
--- a/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md
@@ -4,6 +4,8 @@
### Features Added
+- Added `ServiceBusJmsConnectionFactoryClassProvider` interface to allow users to specify a custom subclass of `ServiceBusJmsConnectionFactory` to be used in the configuration. This enables injection of custom connection factory implementations with additional functionality beyond the standard Service Bus JMS connection factory.
+
### Breaking Changes
### Bugs Fixed
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfiguration.java
index 53e4b15b4f50..6ad2f979b4fe 100644
--- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfiguration.java
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfiguration.java
@@ -6,6 +6,7 @@
import com.azure.servicebus.jms.ServiceBusJmsConnectionFactory;
import com.azure.spring.cloud.autoconfigure.implementation.jms.properties.AzureServiceBusJmsProperties;
import com.azure.spring.cloud.autoconfigure.jms.AzureServiceBusJmsConnectionFactoryCustomizer;
+import com.azure.spring.cloud.autoconfigure.jms.ServiceBusJmsConnectionFactoryClassProvider;
import jakarta.jms.ConnectionFactory;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.BeansException;
@@ -118,9 +119,15 @@ private void registerJmsPoolConnectionFactory(BeanDefinitionRegistry registry) {
private ServiceBusJmsConnectionFactory createServiceBusJmsConnectionFactory() {
AzureServiceBusJmsProperties serviceBusJmsProperties = beanFactory.getBean(AzureServiceBusJmsProperties.class);
ObjectProvider factoryCustomizers = beanFactory.getBeanProvider(AzureServiceBusJmsConnectionFactoryCustomizer.class);
+ ObjectProvider classProvider = beanFactory.getBeanProvider(ServiceBusJmsConnectionFactoryClassProvider.class);
+
+ Class extends ServiceBusJmsConnectionFactory> factoryClass = classProvider
+ .getIfAvailable(() -> () -> ServiceBusJmsConnectionFactory.class)
+ .getConnectionFactoryClass();
+
return new ServiceBusJmsConnectionFactoryFactory(serviceBusJmsProperties,
factoryCustomizers.orderedStream().collect(Collectors.toList()))
- .createConnectionFactory(ServiceBusJmsConnectionFactory.class);
+ .createConnectionFactory(factoryClass);
}
}
}
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
new file mode 100644
index 000000000000..b125abb5a15c
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.spring.cloud.autoconfigure.jms;
+
+import com.azure.servicebus.jms.ServiceBusJmsConnectionFactory;
+
+/**
+ * A provider for specifying the desired {@link ServiceBusJmsConnectionFactory} class to be used.
+ * Implement this interface and define it as a bean to inject a custom subclass of ServiceBusJmsConnectionFactory.
+ *
+ * @since 6.1.0
+ */
+@FunctionalInterface
+public interface ServiceBusJmsConnectionFactoryClassProvider {
+
+ /**
+ * Get the class of the ServiceBusJmsConnectionFactory to be instantiated.
+ * The class must extend {@link ServiceBusJmsConnectionFactory} and have the required constructors.
+ *
+ * @return The class to be used for creating the ServiceBusJmsConnectionFactory instance.
+ */
+ Class extends ServiceBusJmsConnectionFactory> getConnectionFactoryClass();
+}
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
index 10c9fe284a21..1bf99e2b43e0 100644
--- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
@@ -3,8 +3,12 @@
package com.azure.spring.cloud.autoconfigure.implementation.jms;
+import com.azure.core.credential.TokenCredential;
import com.azure.servicebus.jms.ServiceBusJmsConnectionFactory;
+import com.azure.servicebus.jms.ServiceBusJmsConnectionFactorySettings;
import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties;
+import com.azure.spring.cloud.autoconfigure.jms.ServiceBusJmsConnectionFactoryClassProvider;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
@@ -12,6 +16,7 @@
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jms.connection.CachingConnectionFactory;
@@ -140,9 +145,79 @@ void useCacheConnectionViaAdditionConfigurationFile(String pricingTier) {
});
}
+ @Test
+ void useCustomServiceBusJmsConnectionFactoryClass() {
+ this.contextRunner
+ .withUserConfiguration(CustomConnectionFactoryClassConfiguration.class)
+ .withPropertyValues(
+ "spring.jms.servicebus.pricing-tier=premium",
+ "spring.jms.servicebus.pool.enabled=false",
+ "spring.jms.cache.enabled=false"
+ )
+ .run(context -> {
+ assertThat(context).hasSingleBean(ServiceBusJmsConnectionFactory.class);
+ ServiceBusJmsConnectionFactory factory = context.getBean(ServiceBusJmsConnectionFactory.class);
+ assertThat(factory).isInstanceOf(CustomServiceBusJmsConnectionFactory.class);
+ });
+ }
+
+ @Test
+ void useCustomServiceBusJmsConnectionFactoryClassWithCaching() {
+ this.contextRunner
+ .withUserConfiguration(CustomConnectionFactoryClassConfiguration.class)
+ .withPropertyValues(
+ "spring.jms.servicebus.pricing-tier=premium",
+ "spring.jms.servicebus.pool.enabled=false"
+ )
+ .run(context -> {
+ assertThat(context).hasSingleBean(CachingConnectionFactory.class);
+ CachingConnectionFactory cachingFactory = context.getBean(CachingConnectionFactory.class);
+ assertThat(cachingFactory.getTargetConnectionFactory()).isInstanceOf(CustomServiceBusJmsConnectionFactory.class);
+ });
+ }
+
+ @Test
+ void useCustomServiceBusJmsConnectionFactoryClassWithPooling() {
+ this.contextRunner
+ .withUserConfiguration(CustomConnectionFactoryClassConfiguration.class)
+ .withPropertyValues(
+ "spring.jms.servicebus.pricing-tier=premium"
+ )
+ .run(context -> {
+ assertThat(context).hasSingleBean(JmsPoolConnectionFactory.class);
+ JmsPoolConnectionFactory poolFactory = context.getBean(JmsPoolConnectionFactory.class);
+ assertThat(poolFactory.getConnectionFactory()).isInstanceOf(CustomServiceBusJmsConnectionFactory.class);
+ });
+ }
+
@Configuration
@PropertySource("classpath:servicebus/additional.properties")
static class AdditionalPropertySourceConfiguration {
}
+
+ @Configuration
+ static class CustomConnectionFactoryClassConfiguration {
+ @Bean
+ ServiceBusJmsConnectionFactoryClassProvider serviceBusJmsConnectionFactoryClassProvider() {
+ return () -> CustomServiceBusJmsConnectionFactory.class;
+ }
+ }
+
+ /**
+ * Custom subclass of ServiceBusJmsConnectionFactory for testing.
+ */
+ static class CustomServiceBusJmsConnectionFactory extends ServiceBusJmsConnectionFactory {
+ public CustomServiceBusJmsConnectionFactory() {
+ super();
+ }
+
+ public CustomServiceBusJmsConnectionFactory(String connectionString, ServiceBusJmsConnectionFactorySettings settings) {
+ super(connectionString, settings);
+ }
+
+ public CustomServiceBusJmsConnectionFactory(TokenCredential tokenCredential, String host, ServiceBusJmsConnectionFactorySettings settings) {
+ super(tokenCredential, host, settings);
+ }
+ }
}
From 5c21d440cf641bbcdbf8d3092e03922987076c29 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 5 Nov 2025 03:52:43 +0000
Subject: [PATCH 3/4] Fix checkstyle violations by adding suppression for
RedundantModifier
Co-authored-by: saragluna <31124698+saragluna@users.noreply.github.com>
---
.../checkstyle/track2/checkstyle-suppressions.xml | 3 +++
.../jms/ServiceBusJmsConnectionFactoryConfigurationTests.java | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/eng/lintingconfigs/checkstyle/track2/checkstyle-suppressions.xml b/eng/lintingconfigs/checkstyle/track2/checkstyle-suppressions.xml
index 57efcf6e080d..b9bd10c488ce 100644
--- a/eng/lintingconfigs/checkstyle/track2/checkstyle-suppressions.xml
+++ b/eng/lintingconfigs/checkstyle/track2/checkstyle-suppressions.xml
@@ -43,6 +43,9 @@
+
+
+
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
index 1bf99e2b43e0..b79155da1554 100644
--- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsConnectionFactoryConfigurationTests.java
@@ -206,8 +206,9 @@ ServiceBusJmsConnectionFactoryClassProvider serviceBusJmsConnectionFactoryClassP
/**
* Custom subclass of ServiceBusJmsConnectionFactory for testing.
+ * Public constructors are required for reflection-based instantiation.
*/
- static class CustomServiceBusJmsConnectionFactory extends ServiceBusJmsConnectionFactory {
+ public static class CustomServiceBusJmsConnectionFactory extends ServiceBusJmsConnectionFactory {
public CustomServiceBusJmsConnectionFactory() {
super();
}
From 804b1be816da4aa1c8cb84ec0c83edf31d62c75b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 5 Nov 2025 03:55:26 +0000
Subject: [PATCH 4/4] Add comprehensive JavaDoc documentation with usage
examples
Co-authored-by: saragluna <31124698+saragluna@users.noreply.github.com>
---
...eBusJmsConnectionFactoryClassProvider.java | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
index b125abb5a15c..8dc7dbc88684 100644
--- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
@@ -7,7 +7,47 @@
/**
* A provider for specifying the desired {@link ServiceBusJmsConnectionFactory} class to be used.
+ *
* Implement this interface and define it as a bean to inject a custom subclass of ServiceBusJmsConnectionFactory.
+ * This allows you to use a custom connection factory implementation with additional functionality beyond the
+ * standard Service Bus JMS connection factory.
+ *
+ *
+ * Example usage:
+ *
{@code
+ * @Configuration
+ * public class CustomJmsConfiguration {
+ * @Bean
+ * public ServiceBusJmsConnectionFactoryClassProvider connectionFactoryClassProvider() {
+ * return () -> CustomServiceBusJmsConnectionFactory.class;
+ * }
+ * }
+ *
+ * public class CustomServiceBusJmsConnectionFactory extends ServiceBusJmsConnectionFactory {
+ * public CustomServiceBusJmsConnectionFactory(String connectionString, ServiceBusJmsConnectionFactorySettings settings) {
+ * super(connectionString, settings);
+ * // Add custom initialization
+ * }
+ *
+ * public CustomServiceBusJmsConnectionFactory(TokenCredential tokenCredential, String host, ServiceBusJmsConnectionFactorySettings settings) {
+ * super(tokenCredential, host, settings);
+ * // Add custom initialization
+ * }
+ *
+ * // Add custom methods or override existing ones
+ * }
+ * }
+ *
+ *
+ * Requirements:
+ *
+ * - The custom class must extend {@link ServiceBusJmsConnectionFactory}
+ * - The custom class must have a constructor accepting {@code (String, ServiceBusJmsConnectionFactorySettings)}
+ * for connection string-based authentication
+ * - The custom class must have a constructor accepting {@code (TokenCredential, String, ServiceBusJmsConnectionFactorySettings)}
+ * for passwordless authentication
+ *
+ *
*
* @since 6.1.0
*/