Best way to disable #KafkaListeners - spring-boot

My application contains several #KafkaListeners.
When I run the app locally or run some #SpringBootTests (without kafka), I got my log polluted with
[org.apache.kafka.clients.NetworkClient] - [Consumer clientId=consumer-app-1, groupId=app] Bootstrap broker localhost:9092 (id: -1 rack: null) disconnected
For such cases, I would like to disable listeners, as they are useless anyways.
I know I can do it with
#KafkaListener(... autoStartup = "${consumer.auto.start:false}")
but adding this property to all of the consumers feels cumbersome.
Unfortunately, there is no general property like spring.kafka.consumer.group-id that would affect all the consumers.
Is there a better way to achieve the same?
Thanks

If you are not interested in Spring for Apache Kafka activity in some of your Spring Boot tests, just consider to exclude its auto-configuration:
#SpringBootTest
#EnableAutoConfiguration(exclude=KafkaAutoConfiguration.class)
This way the #EnableKafka won't be applied to your application context and no KafkaListenerContainers are going to be registered to start on context refresh.
UPDATE
Another way, for the reason you explained, a respective configuration property, which you can add to application.properties, which could be a test scope-specific, or profile-based. See more info in Spring Boot docs: https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/using-boot-auto-configuration.html#using-boot-disabling-specific-auto-configuration
The property name is spring.autoconfigure.exclude - you have to specify fully-qualified class name. Therefore for your use-case it is:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
See also how to have test-specific application.properties or divided by the profile: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.profiles

Related

How to disable Rabbit health check via Configuration

I would like to disable the rabbit health check in my default RabbitMockConfiguration.
We have a Configuration that is imported via #Import. Unfortunately the Configuration does not prevent the health check from being added to the health indicator as that happens once spring-rabbit is in the classpath.
We have the workaround, that we add a properties file in every service using that Configuration, which disables the property management.health.rabbit.enabled, but for us it would be much nicer to be able to disable that heathcheck on configuration level.
I thought about the tests with #TestPropertySource(properties = ["management.health.rabbit.enabled=false"]), but I could not find an equivalent to use for the a #Configuration, as #PropertySource expects a location for a properties file and does not accept single properties.
Any idea what we can do?
Spring boot version: 2.2.4
Spring amqp version: 2.2.3
Spring Version: 5.2.3
If you want to change the behaviour of the health check, I'd rather override the health check so that it states Rabbit is in mock mode.
To do so, just create a HealthIndicator bean named rabbitHealthIndicator:
#Bean
public HealthIndicator rabbitHealthIndicator() {
return () -> Health.up().withDetail("version", "mock").build();
}
This has the effect of switching the production one and exposes the fact the app is running with a mock.
I guess you should add 'ApplicationListener' and add the implementation to 'src/main/resources/META-INF/spring.factories' to your module with MockReddisConfiguration. This is described in more detail here

In Spring Boot how do you register custom converters that are available when parsing application configuration?

In a Spring Boot application how do you register custom converts to be used when processing application configuration?
I have made a custom convert (org.springframework.core.convert.converter.Converter) so it can be used by the ApplicationConversionService/Binder to parse #ConfiguraitonProperties defined in application.properties and application.yaml configuration files but do not know how to register it.
I have tried the solution here https://stackoverflow.com/a/41205653/45708 but it creates an instance of my converter after the application configuration parameters have been processed.
I ran into this issue myself recently. From what I can tell, the key issue is that binding to configuration properties occurs very early in the Spring startup process, before the Application Context is fully initialized. Therefore the usual methods for registering a converter are not reliable. In fact the ConversionService used for configuration binding appear to be a one-off and not really connected to the ConversionService that is stored in the Application Context.
I was able to get something working but it feels like a hack, as it relies on internal implementation details that may work today but not tomorrow. In any case, this is the code I used:
((ApplicationConversionService) ApplicationConversionService.getSharedInstance()).addConverter(myCustomConverter);
The trick I found was to make sure this gets called as soon as possible at application startup so that it gets called before the configuration binding where it's needed. I put it in a #PostConstruct block inside my main #SpringBootApplication class as this seemed to get invoked early on, at least in my case.

Refresh Spring Boot Auto-Configured Properties

Can I dynamically refresh properties that are used by Spring Boot's auto configuration setup?
For example, I have the following properties set (via cloud config) to auto configure a dataSource:
spring.datasource.username=user1
spring.datasource.password=test
Now if I change the password prop on the config server, and hit the /refresh endpoint, I can see that the updated prop is retrieved but the DataSource is not refreshed.
I know I can manually configure the DataSource beans and make sure they fall under a RefreshScope, but I was hoping to find a way to mark the auto configured properties as "refreshable". I have some use cases where I'd want to refresh props used by Spring Boot for other beans besides DataSources, and setting up some of those beans manually could be a pain.
I think I spoke too soon, at least as far as my DataSource example goes. A new db connection was being created with the updated props.
Which makes sense especially when looking at the docs here
This didn't re-connect some of my spring.cloud.stream.bindings properties I had, but in that case I can probably solve the issue with #RefreshScope.
There's a configuration property to set in case of the Autoconfigured bean is immutable (don't change the properties after initialized)
You can put a list (set) of classes that you need to be refreshed and you don't have control over the source code, you can put them under the property: spring.cloud.refresh.extra-refreshable
e.g.:
spring
cloud
refresh
extra-refreshable:
- org.springframework.mail.javamail.JavaMailSenderImpl
see: https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#refresh-scope

Spring boot disable Custom HealthIndicator

I've created a custom HealthIndicator which I wants to disable in production until we go live fully.
I'm aware there is a property to disable default health indicators (management.health.defaults.enabled=false), but not for custom HealthIndicators.
Is there any way I can temporarily turn off MyCustomHealthIndicator in application property configuration level?
You can use Spring Boot's mechanism without using custom properties. Start by adding an annotation on your class:
#ConditionalOnEnabledHealthIndicator("your-health")
You can now disable your own health indicator by using the Spring Boot suggested property:
management.health.your-health.enabled=false
It has the same effect, but it allows you to group your enabled and disabled health indicators together.
Your health indicator bean,
#ConditionalOnProperty(value='health.indicator.enabled')
#Bean
class MyHealthIndicator {
}
In your application.properties file,
health.indicator.enabled=true/false
Hope this helps !
#ConditionalOnEnabledHealthIndicator("your-health")
You can now disable your own health indicator by using the Spring Boot suggested property:
management.health.your-health.enabled=false
This works when we re-start the app. should it work without re-start?

Spring.datasource.initialize=false not working

I am working on spring boot and batch application.
Due to batch, the application tries to connect to datasource
with spring-boot:run.
I want to stop that and tried spring.datasource.initialize=false
Along with this also put spring.batch.job.enabled=false
While the second one works fine, it seems the first one is ignored.
Could someone let me know if there is a way to stop db connection on startup?
Thanks in advance
The problem is, that spring/spring-boot loads the whole spring-context when it is "booted". This means, that all defined spring-beans are loaded into the spring-context during this boot-phase. In the case of spring-batch, this also means that the datasource bean is loaded and, if not turned off by "spring.batch.initializer.enabled=false", the spring-batch tables are initialized.
Generally, you cannot prevent this from happening as soon as you have added your spring-batch-starter to your maven dependencies.
Moreover, I don't understand why you want to prevent this from happening. It is just initialisation taking place and, provided that everything is configured correctly, this shouldn't be a problem at all.
Nonetheless, if you really want to stop the datasource from beeing initialized, you could try the following approach. However, I don't know if this will work.
Spring-Batch needs a datasource that is registered under the name "dataSource" in the spring-context. If no spring-bean with that name is found, it creates its own. But if you provide your own implementation/configuration for it, it will use your spring bean.
What you need to do is, to provide a proxy for a datasource that is loaded lazily and then register it under the name "dataSource" in the context:
#Configuration
public class MySetUp {
#Bean
public DataSource dataSource() {
// ... create your "lazy initializing" datasource
}
}
But - and let me stress that - this nothing that I would recommend and I don't see a good reason, why this should be necessary to do.
Furthermore, you mention that you only want load "initial static index page" (I assume, you are talking about html, right?). However, I don't see a "batch" use case, which should display html-pages. It would probably be better to have two different applications in this case.
Probably you could provide some more information about your use case.
As I understand, you don't want to prevent database connection during application startup.
Instead, you want to prevent execution of batch scripts.
Correct me, please, if I got it wrong.
To prevent execution of batch scripts set:
spring.batch.initializer.enabled=false

Resources