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/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..8dc7dbc88684
--- /dev/null
+++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/jms/ServiceBusJmsConnectionFactoryClassProvider.java
@@ -0,0 +1,64 @@
+// 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.
+ * 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
+ */
+@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..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
@@ -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,80 @@ 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.
+ * Public constructors are required for reflection-based instantiation.
+ */
+ public 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);
+ }
+ }
}