Spring Kafka Listener shutdown Application - spring

I have an application that creates 3 KafkaListener per configuration in the ConcurrentKafkaListenerContainerFactory if any of these Listeners throws a specific Exception. I would like to shutdown the entire spring application.
Since these errors are non recoverable and need manual intervention.
How would i go about doin this?
Do i just inject the ApplicationContext into the Listener and close the application from there?
Or is there a more appropriate way of handling this?

That's one way, or you could just call System.exit(1).

Related

spring-boot graceful shutdown

Is there a way in spring boot to control the graceful shutdown of the app.
I know that you can have #PreDestroy methods in beans but how can you control the ordering in which those #PreDestroy methods are called.
You can have multiple beans depending on each other will the shutdown of the context look for this dependency already and call the #PreDestroy methods in the right order or not?
For example what I would like to accomplish is:
1.) stop listening for new requests on rest endpoints
2.) prevent rabbit message listeners to accept new messages
3.) wait for all processing that has started before the shutdown but is not finished yet.
Spring-boot-2-3-0 has added support for graceful shutdown.
you can enable graceful shutdown by setting up server.shutdown=graceful property
To configure the timeout period you can use
spring.lifecycle.timeout-per-shutdown-phase=20s
spring boot documentation
If you can not upgrade to spring boot 2.3 then you can check below project
https://github.com/gesellix/graceful-shutdown-spring-boot

Initializing tables on spring boot startup

I have a spring boot application, in which I need to initialize the tables based on some configuration. I am using managed transactions using #Transactional. My problem is that I do not know when app is ready to make DB transactions.
I created a bean which reads the configuration and updates the tables, but it gets an exception at that point:
Could not obtain transaction-synchronized Session for current thread
I have tried that if I wait sprintboot to start and make the same transactions through HTTP requests, then there is no problem. So it seems to be a timing problem. I have also tried moving the code to #PostConstruct of bean but it does not fix the issue.
How can I know that app is ready for DB transactions? Any help will be much appreciated.
You can listen on some events Spring is publishing.
See here
You properbly need to listen on this even: ContextRefreshedEvent
The simplest and cleanest way of performing the initialization should be by making your bean implement ApplicationListener for ContextRefreshedEvent and then handling the initialization in the onApplicationEvent method. This way, your initialization will run when Spring's whole application context is initialized

How to manually shutdown embedded Tomcat?

I'm trying to implement a graceful shutdown sequence for my Spring Boot application. For that I registered a custom shutdown hook with Runtime and disabled the one provided by Spring (SpringApplication.setRegisterShutdownHook(false)). From this custom shutdown hook I first would like to pause embedded Tomcat or the connectors and some other schedulers after which I manually invoke applicationContext.close() to shutdown the rest of the Spring application.
What is the best way to get access to the embedded Tomcat instance? I was fiddling around with TomcatEmbeddedServletContainerFactory but this does not seem to give me access to default connectors or EmbeddedServletContainer which has a stop method.
You can access the EmbeddedServletContainer from the EmbeddedWebApplicationContext (just inject that) and downcast it.

how can we use addShutdownHook in project?

i saw some code use ShutdownHook like this
Runtime.getRuntime().addShutdownHook(new Thread(){
ConfigurableApplicationContext.stop();
//close spring context;
threadpool.shutdownnow();
//close theadpool
});
is there anything useful to do like this?
i thought
when jvm exit ,maybe thread will be shutdown immediately
and spring context will close tooï¼›
what shall we do next when we need to call System.exit() ?
It really depends on your application and the lifecycle of your objects and those threads you appear to have outside of your context. If you are running the spring container inside a standalone java process, then trapping the shutdown hook like this is one way to do that. Another way is to have it listen on a tcp port and send a command to begin the shutdown process. If you are running in a web container like tomcat, then you should follow the standards on normal webapp shutdown, which Spring supports with Context Listeners.
I would also consider redesigning your app so that the threads are all managed with a bean that lives inside your spring container. For instance using a bean that is configured with directives (attributes) for start/stop methods and then that bean would use an Executor for thread pooling. This way, your shutdown is ONLY shutting down the Spring container, and Spring provides very good support for orderly shutdown of beans. One of those beans is your object holding the threads within the Executor. Its a much cleaner way than trying to integrate Spring beans with external threads.
Hope this helps.

Spring JMS injection causing application not to startup

We have a spring application that publishes and listens to queues on a remote application server. My publisher and listener which are spring based listen within our own application server.
One of the problems we have for our test environments is the other app. server is not up so when our test application goes to start and it tries to inject JmsTemplate with its connectionFactory it blows up because it is not a valid connection and our entire application fails to load. This is causing grief with the other developers in our group that have nothing to do with JMS. All they want to do is run and test their code but the JmsTemplate connectionFactory is down.
Does anyone have any suggestion for enabling spring ignore some bad injections which will allow our application to start properly?
Thanks
I believe this could be achieved by defining separate spring profiles and then passing it as a parameter in your test environments while starting your application. You could mock or ignore any beans then.
Example
import org.springframework.context.annotation.Profile;
#Profile("test")
public class AppConfigTest {
....
....
}
JVM param / System property
-Dspring.profiles.active=test

Resources