Why is my Spring Boot app with SQS Not Showing a JMSHealthIndicator?

Leanne182x

I'm working on a Spring Boot application that takes messages from SQS as described on this post https://aws.amazon.com/blogs/developer/using-amazon-sqs-with-spring-boot-and-spring-jms/

When I access the built in Spring Boot health endpoint at localhost:8081/health I expect to see some information about the JMS broker as the Spring Boot docs say there are auto configured health indicators that are configured "when appropriate" one of which is the JmsHealthIndicator. Instead I just see the status and diskspace {"status":"UP","diskSpace":{"status":"UP","total":31572619264,"free":24611381248,"threshold":10485760}}

Does anyone know why we don't see anything about JMS on the health endpoint? The application works fine reading from SQS but since it's hosted in Kubernetes I want to add a readiness/liveness probe and to include JMS in the check.

For information our JMS config with @EnableJms is as follows

import javax.jms.Session;

import com.amazon.sqs.javamessaging.SQSConnectionFactory;
import com.amazonaws.auth.AWSCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.aws.core.region.RegionProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.destination.DynamicDestinationResolver;

@Configuration
@EnableJms
public class JmsConfig {

private static final Logger LOGGER = LoggerFactory.getLogger(JmsConfig.class);
private static final String LOWER_UPPER_CONCURRENCY = "3-10";

private final SQSConnectionFactory connectionFactory;

public JmsConfig(RegionProvider regionProvider, AWSCredentialsProvider awsCredentialsProvider) {
    this.connectionFactory = SQSConnectionFactory.builder()
            .withRegion(regionProvider.getRegion())
            .withAWSCredentialsProvider(awsCredentialsProvider)
            .build();
    LOGGER.info("Loading JmsConfig");
}

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory =
            new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(this.connectionFactory);
    factory.setDestinationResolver(new DynamicDestinationResolver());
    factory.setConcurrency(LOWER_UPPER_CONCURRENCY);
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}

@Bean
public JmsTemplate defaultJmsTemplate() {
    return new JmsTemplate(this.connectionFactory);
}

}

Then we also have a method annotated with @JmsListener(destination = "${sqs.input.queue}")

Edit: Note that I have already tried adding the following to the application.properties

management.health.defaults.enabled=true
management.health.jms.enabled=true
endpoints.health.sensitive=false

Thanks, Leanne.

Leanne182x

It turns out that exposing the connection factory as a bean now results in a JMS section in the health response.

So by changing the code to this

@Configuration
@EnableJms
public class JmsConfig {

private static final Logger LOGGER = LoggerFactory.getLogger(JmsConfig.class);
private static final String LOWER_UPPER_CONCURRENCY = "3-10";

public JmsConfig() {
    LOGGER.info("Loading JmsConfig");
}

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(SQSConnectionFactory connectionFactory) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setDestinationResolver(new DynamicDestinationResolver());
    factory.setConcurrency(LOWER_UPPER_CONCURRENCY);
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}

@Bean
public SQSConnectionFactory sqsConnectionFactory(RegionProvider regionProvider, AWSCredentialsProvider awsCredentialsProvider) {
    return SQSConnectionFactory.builder()
            .withRegion(regionProvider.getRegion())
            .withAWSCredentialsProvider(awsCredentialsProvider)
            .build();
}

@Bean
public JmsTemplate defaultJmsTemplate(SQSConnectionFactory connectionFactory) {
    return new JmsTemplate(connectionFactory);
}

}

The health endpoint response looks like this

{
"status": "UP",
"jms": {
    "status": "UP",
    "provider": "Amazon"
},
"diskSpace": {
    "status": "UP",
    "total": 249779191808,
    "free": 165159432192,
    "threshold": 10485760
}
}

A colleague had a hunch after seeing the constructor for JmsHealthIndicator that the connection factory wasn't accessible.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related