Reputation: 21384
My Spring Boot application is not a web server, but it's a server using custom protocol (using Camel in this case).
But Spring Boot immediately stops (gracefully) after started. How do I prevent this?
I'd like the app to stop if Ctrl+C or programmatically.
@CompileStatic
@Configuration
class CamelConfig {
@Bean
CamelContextFactoryBean camelContext() {
final camelContextFactory = new CamelContextFactoryBean()
camelContextFactory.id = 'camelContext'
camelContextFactory
}
}
Upvotes: 30
Views: 46392
Reputation: 1901
https://stackoverflow.com/a/54762909/4026629 is a nice idea, but seems unnecessarily verbose, and it can be simplified for most use cases.
Adding this line in one's main application class:
new CountDownLatch(1).await();
e.g.
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(DemoApplication.class, args);
new CountDownLatch(1).await();
}
seems to do the trick.
Upvotes: 0
Reputation: 61
All threads are completed, the program will close automatically.
So, register an empty task with @Scheduled
will create a loop thread to prevent shutdown.
file application.yml
spring:
main:
web-application-type: none
file DemoApplication.java
@SpringBootApplication
@EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
file KeepAlive.java
@Component
public class KeepAlive {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(fixedRate = 1 * 1000 * 60) // 1 minute
public void reportCurrentTime() {
log.info("Keepalive at time {}", dateFormat.format(new Date()));
}
}
Upvotes: 6
Reputation: 342
This is now made even simpler.
Just add camel.springboot.main-run-controller=true
to your application.properties
Upvotes: 5
Reputation: 316
My project is NON WEB Spirng Boot. My elegant solution is create a daemon thread by CommandLineRunner. Then, Application do not shutdown immediately.
@Bean
public CommandLineRunner deQueue() {
return args -> {
Thread daemonThread;
consumer.connect(3);
daemonThread = new Thread(() -> {
try {
consumer.work();
} catch (InterruptedException e) {
logger.info("daemon thread is interrupted", e);
}
});
daemonThread.setDaemon(true);
daemonThread.start();
};
}
Upvotes: 0
Reputation: 21384
I found the solution, using org.springframework.boot.CommandLineRunner
+ Thread.currentThread().join()
, e.g.:
(note: code below is in Groovy, not Java)
package id.ac.itb.lumen.social
import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class LumenSocialApplication implements CommandLineRunner {
private static final log = LoggerFactory.getLogger(LumenSocialApplication.class)
static void main(String[] args) {
SpringApplication.run LumenSocialApplication, args
}
@Override
void run(String... args) throws Exception {
log.info('Joining thread, you can press Ctrl+C to shutdown application')
Thread.currentThread().join()
}
}
Upvotes: 38
Reputation: 5328
To keep the java process alive when not deploying a web application set the webEnvironment property to false like so:
SpringApplication sa = new SpringApplication();
sa.setWebEnvironment(false); //important
ApplicationContext ctx = sa.run(ApplicationMain.class, args);
Upvotes: -3
Reputation: 1643
As of Apache Camel 2.17 there is a cleaner answer. To quote http://camel.apache.org/spring-boot.html:
To keep the main thread blocked so that Camel stays up, either include the spring-boot-starter-web dependency, or add camel.springboot.main-run-controller=true to your application.properties or application.yml file.
You will want the following dependency too:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.17.0</version>
</dependency>
Clearly replace <version>2.17.0</version>
or use the camel BOM to import dependency-management information for consistency.
Upvotes: 23
Reputation: 1143
An example implementation using a CountDownLatch:
@Bean
public CountDownLatch closeLatch() {
return new CountDownLatch(1);
}
public static void main(String... args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(MyApp.class, args);
final CountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
closeLatch.countDown();
}
});
closeLatch.await();
}
Now to stop your application, you can look up the process ID and issue a kill command from the console:
kill <PID>
Upvotes: 18
Reputation: 456
Spring Boot leaves the task of running the application to the protocol around which the application is implemented. See, for example, this guide:
Also required are some housekeeping objects like a
CountDownLatch
to keep the main thread alive...
So the way of running a Camel service, for example, would to be to run Camel as a standalone application from your main Spring Boot application class.
Upvotes: 5
Reputation: 1517
for springboot app to run continously it has to be run in a container, otherwise it is just like any java app all threads are done it finishes, you can add
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
and it will turn it into webapp, if not you are responsible keeping it alive in your implementation
Upvotes: -5