How to programmatically shutdown a Spring Application by itself on Tomcat - spring

How can we shutdown or stop a Spring application by itself programmatically?
We have currently using ConfigurableApplicationContext#close(), and yes, it does close the application but not shutdown or stop the application.
From the tomcat manager, the application status still is running, so the client still can connect to the web app and get the front-end resource. Besides, all servlets seems still working and can accept the request.
The below code shows how we do currently.
#Autowired
private ConfigurableApplicationContext configurableApplicationContext;
#Scheduled(cron="0 0/5 * * * ?")
private void validateLicenseExpired()
{
try
{
LicenseUtils.isLicensingPeriodValid();
} catch (LicenseInvalidException lie) {
logger.error("\t The licensing is expired", lie);
configurableApplicationContext.close();
}
}
Any help is appreciated.

If its a boot application the you can use following link to stop the application.
Programmatically shut down Spring Boot application
Otherwise you can programmatically call the shutdown.sh like below to stop the server.
String command = "<path-to-tomcat>shutdown.sh"; // for windows use bat
Process child = Runtime.getRuntime().exec(command);
[Edit]
This thread explains about stoping application like tomcat manager
Start / stop a web application from itself?

Related

How to restart springboot application from code

I have a springboot application with embedded tomcat. And on certain cases it should be restarted from code.
I have read several articles and SO posts regarding this,but yet to find a clean solution.
I am aware that 'context.close' , 'SpringApplication.exit(context)' exist and can be wrapped into something like this:
public static void restart() {
ApplicationArguments args = context.getBean(ApplicationArguments.class);
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(Application.class, args.getSourceArgs());
});
thread.setDaemon(false);
thread.start();
}
source: https://www.baeldung.com/java-restart-spring-boot-app
The problem is that using context.close() just doesn't work in a clean way. The context itself will be restarted though, but bunch of Threads will be left in the background (like Thread[pool-3-thread-1,5,main] Thread[Signal Dispatcher,9,system] Thread[OkHttp TaskRunner,5,main] ..etc).
And for every context restart these will be recreated, so the number of threads adds up gradually by each restart. Resulting in huge Thread mess as time passes.
Note1: A simple application exit by using 'context.close()' also wouldn't work because of these left over Threads. So the context close doesnt even close the application.
Note2: If I use System.exit(SpringApplication.exit(context)) I can kill the app gracefully, but can't restart it.
Note3: I don't want to use neither devtools nor actuator
So the question is how to perform a total restart for a springboot application?
You can use the RestartEndPoint in spring-cloud-context dependency to restart the Spring Boot application programmatically:
#Autowired
private RestartEndpoint restartEndpoint;
...
Thread restartThread = new Thread(() -> restartEndpoint.restart());
restartThread.setDaemon(false);
restartThread.start();

Accessing tomcat management page from Spring tool set 4

I have developed a Camel Rout using Spring. I used the STS4 IDE to develop the same.
When I started the application using Run As-> Spring Boot App, the application starts and also I can see from the logs that the route is started.
My route is a basic app, the exposes a rest endpoint and logs a Hello World
#Override
public void configure() throws Exception {
restConfiguration()
.enableCORS(true)
.apiContextPath("/api-doc")
.apiProperty("api.title", "Test REST API")
.apiProperty("api.version", "v1")
.apiContextRouteId("doc-api")
.component("servlet")
.bindingMode(RestBindingMode.json);
rest("/api/")
.id("api-route")
.consumes("application/json")
.get("/test")
.to("direct:log");
from("direct:log")
.id("log")
.log(LoggingLevel.INFO,"Test successful");
}
What I am expecting is that if I do localhost:8080/api/test, i will see some logs "Test Susccessful" in the Tomcat logs. I am using tomcat 9, Instead what I get WhiteLable error. I thought there is an issue with my code so I tried localhost:8080 and i was expecting the Tomcat Management server to open. Even that is not working.
I am not starting Tomcat separately. What I am doing is Run As-> Spring Boot App and I guess it is calling the embedded tomcat.
Credit for this answer goes to #Bedla. I had to add camel in the URL path http://localhost:8080/camel/api/test

Spring-Boot on AppEngine Standard Detect Shutdown

Using Spring Boot 2.0.0.RELEASE on Google Appengine Standard. Using autoscaling but trying to get some control about creation/destruction of the instances. Need to be able to do some cleanup and would like to log those events.
Any methods in Spring Boot like #Predestroy or ContextClosedEvent don't seem to work on GAE.
According to the documention, it should be possible to detect shutdown of an instance by adding a shutdown hook.
Documentation LifecycleManager.ShutdownHook.
Have tried to put it in several places without success.
Example as a #Bean:
#Bean
public LifecycleManager lifecycleManager() {
LifecycleManager lifecycle_manager = LifecycleManager.getInstance();
lifecycle_manager.setShutdownHook(new ShutdownHook() {
public void shutdown() {
LifecycleManager.getInstance().interruptAllRequests();
log.error("Shutdown " + getClassSimpleName() + ".");
}
});
log.warn("Created shutdown hook.");
return lifecycle_manager;
}
Shutdown hook is properly installed, but doesn't get fired when the instance goes down.
As you can read in the Google Issue Tracker:
Shutdown hooks only work for manual scaled instances on the standard runtime (...).
The shutdown hooks simply don't work on automatic and basic scaling.

Shutdown embedded Jetty in Spring-Boot Application with Apache CXF

In a Spring-Boot Application I register an Apache-CXF SOAP Service like this:
#Bean(destroyMethod = "destroy")
org.apache.cxf.endpoint.Server server(MyService myService) {
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(MyService.class);
svrFactory.setAddress("http://0.0.0.0:4711/MyService");
svrFactory.setServiceBean(myService);
svrFactory.getInInterceptors().add(new LoggingInInterceptor());
svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());
return svrFactory.create();
}
It may happen at other places of my spring configuration, that the context can not be initialized succesfully (Application startup failed) and the application shutdown is initiated.
Unfortunately the sever bean, which is already created, stays alive and prevents the application from shutting down completely. I thought that destroyMethod = "destroy" would do the trick, but that only destroys the webapp/SOAP endpoint (resultig in HTTP ERROR 404) but the embedded jetty is still running.
Do I have any chance to configure the Spring Context in a way that prevents the embedded Jetty from staying alive when the Spring Context initialization failes at some point?

release db connections in standalone application

I am working on a standalone application using Spring/JPA and I am trying to release properly the database resources used.
In a Web application using tomcat for example, we shutdown the server, and this way, we let Tomcat manage the resources.
But as I am in a standalone app, I have to take care about this, I use Runtime.getRuntime().addShutdownHook to "catch" the shutdown event and call ((ClassPathXmlApplicationContext) context).close();, something like this:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
((ClassPathXmlApplicationContext) context).close();
}
It works but with an exception in the stacktrace if a thread was using a connection.
I am wondering if there is another option? Maybe getting a list of open transactions and force them to rollback?
I believe that you would need to implement something like this and inside your destroy method, you would retrieve your datasource and call a close method or something similar. I'm also assuming you have a few things to do when you shutdown your application.
I can't quite help with the right method name as I don't know what you are using for your datasource.

Resources