0

I am writing a reporting service to receive messages from Azure Service Bus topic subscriptions. I followed this initial guide - How to use the Spring Boot Starter for Azure Service Bus JMS and simply configured the @JmsListener in my service files to not specify a JmsConnectionFactory so that it would fall back to the default, however this returned the error logs shown below, with jmsConnectionFactory Bean returning a NullPointerException.

I subsequenly looked at Bauldung - Getting Started with Spring JMS and Baeldung - Messaging with JMS for guidance on how to configure the jmsConnectionFactory when the initial implementation wouldn't run but had no luck with any of the suggestions mentioned in the articles above as it was still returning the error logs below.

I then had a dig here on StackOverflow and found this question - Spring Boot - Error creating bean with name 'jmsConnectionFactory', which then pointed to this question - Disabling Spring JMS Auto configuration in Spring Boot Application and this lead me to exclude ServiceBusJMSAutoConfiguration::class in my @SpringBootApplication. This actually worked but I find it a little strange that I should need to exclude this class, and feel as though there is something else I may be doing wrong.

I'm basically looking for any insight on whether what I'm doing is normal practice or if there is a better way to go about this set-up, as I'm not particulary a fan of this - @SpringBootApplication(exclude = [ServiceBusJMSAutoConfiguration::class]). To me it seems like some kind of hack to solving an underlying issue. Any help/opinions on this would be greatly appreciated.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

ReportingServiceApplication.kt

@SpringBootApplication(exclude = [ServiceBusJMSAutoConfiguration::class])
class ReportingServiceApplication

fun main(args: Array<String>) {
    runApplication<ReportingServiceApplication>(*args)
}

Sample Listener - AwardEditEventService.kt

interface AwardEditEventService {
    fun receiveMessage(awardEditEvent: AwardEditEvent)
}

@Service
class AwardEditEventServiceImpl(
    val awardEditEventsRepository: AwardEditEventRepository
) : AwardEditEventService {

    @JmsListener(
        destination = "reporting",
        subscription = "AwardEdits"
    )
    override fun receiveMessage(awardEditEvent: AwardEditEvent) {
        awardEditEventsRepository.save(awardEditEvent)
    }
}

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.3.4.RELEASE"
    id("io.spring.dependency-management") version "1.0.10.RELEASE"
    id("com.diffplug.gradle.spotless") version "4.0.1"
    kotlin("jvm") version "1.3.72"
    kotlin("plugin.spring") version "1.3.72"
    kotlin("plugin.jpa") version "1.3.72"
}

group = "com.test.service"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {

    // Kotlin
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    // Spring Boot
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")

    // Flyway
    implementation("org.flywaydb:flyway-core")

    // App Insights
    implementation("com.microsoft.azure:applicationinsights-spring-boot-starter:2.6.1")
    implementation("com.microsoft.azure:applicationinsights-logging-logback:2.6.1")

    // Azure Service Bus
    implementation("com.microsoft.azure:azure-servicebus-spring-boot-starter:2.2.5")
    implementation("com.microsoft.azure:azure-servicebus-jms-spring-boot-starter:2.2.5")

    // Snowflake
    implementation("net.snowflake:snowflake-jdbc:3.12.12")

    // Postgres (For Local Development)
    runtimeOnly("org.postgresql:postgresql")

    // Test
    testImplementation("com.h2database:h2:1.4.200")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("com.nhaarman:mockito-kotlin:1.6.0")
    testImplementation("org.hamcrest:hamcrest-library:2.2")
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

Here are the logs for the initial error -

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsConnectionFactory' defined in class path resource [com/microsoft/azure/spring/autoconfigure/jms/ServiceBusJMSAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.jms.ConnectionFactory]: Factory method 'jmsConnectionFactory' threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:635) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
    at com.test.service.reporting.ReportingServiceApplicationKt.main(ReportingServiceApplication.kt:13) ~[main/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.jms.ConnectionFactory]: Factory method 'jmsConnectionFactory' threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:650) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    ... 20 common frames omitted
Caused by: java.lang.NullPointerException: null
    at com.microsoft.azure.spring.autoconfigure.jms.ConnectionStringResolver.getServiceBusKey(ConnectionStringResolver.java:30) ~[azure-spring-boot-2.2.5.jar:na]
    at com.microsoft.azure.spring.autoconfigure.jms.ServiceBusJMSAutoConfiguration.jmsConnectionFactory(ServiceBusJMSAutoConfiguration.java:40) ~[azure-spring-boot-2.2.5.jar:na]
    at com.microsoft.azure.spring.autoconfigure.jms.ServiceBusJMSAutoConfiguration$$EnhancerBySpringCGLIB$$9ce4d56.CGLIB$jmsConnectionFactory$3(<generated>) ~[azure-spring-boot-2.2.5.jar:na]
    at com.microsoft.azure.spring.autoconfigure.jms.ServiceBusJMSAutoConfiguration$$EnhancerBySpringCGLIB$$9ce4d56$$FastClassBySpringCGLIB$$99b2393f.invoke(<generated>) ~[azure-spring-boot-2.2.5.jar:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at com.microsoft.azure.spring.autoconfigure.jms.ServiceBusJMSAutoConfiguration$$EnhancerBySpringCGLIB$$9ce4d56.jmsConnectionFactory(<generated>) ~[azure-spring-boot-2.2.5.jar:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    ... 21 common frames omitted

Russell Brady
  • 188
  • 1
  • 13

2 Answers2

0

You need to specify pricing-tier for the service bus as indicated below:

spring:
  jms:
    servicebus:
      connection-string: Endpoint=sb://xxx
      idle-timeout: 30000
      pricing-tier: Standard
Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
0

spring.jms.servicebus.pricing-tier = XXXXX is very important in your configuration. You should replace XXXXX with your pricing-tier.

keemsisi
  • 369
  • 3
  • 6