0

I have a job application (to be run as an outside cron in EKS, not a cron within this Spring Boot app itself) which needs to terminate. I run it in Eclipse as Application.java -> Run, and when it's done, it does not terminate (similar to a Web app).

But when I do this manually at the end of my run():

@SpringBootApplication
public class MyApplication implements CommandLineRunner {

    @Autowired
    private ApplicationContext appContext;

    @Override
    public void run(String... args) throws Exception {

            // ... Run job, and at the end terminate manually

            SpringApplication.exit(appContext, new ExitCodeGenerator() {

                @Override
                public int getExitCode() {
                    return 0;
                }
                
            });

I get this error:

org.apache.tomcat.util.net.Acceptor.log(175) - Socket accept failed

023-03-24 11:27:29.364 [main] INFO  o.a.coyote.http11.Http11NioProtocol.log(173) - Pausing ProtocolHandler ["http-nio-8081"]
2023-03-24 11:27:29.364 [main] WARN  o.apache.tomcat.util.net.NioEndpoint.log(173) - Failed to unlock acceptor for [http-nio-8081] because the local address was not available
2023-03-24 11:27:29.364 [main] INFO  o.a.catalina.core.StandardService.log(173) - Stopping service [Tomcat]
2023-03-24 11:27:29.364 [http-nio-8081-Acceptor] ERROR org.apache.tomcat.util.net.Acceptor.log(175) - Socket accept failed
java.nio.channels.AsynchronousCloseException: null
    at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:202)
    at java.base/sun.nio.ch.ServerSocketChannelImpl.end(ServerSocketChannelImpl.java:376)
    at java.base/sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:399)
    at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:520)
    at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:79)
    at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:128)
    at java.base/java.lang.Thread.run(Thread.java:833)

Is there a way to remove the Tomcat layer from this Spring Boot job app and have it terminate manually?

gene b.
  • 10,512
  • 21
  • 115
  • 227

2 Answers2

1

It looks like you are using an embedded Tomcat server with your spring application. To avoid this and to run it as a standalone application it would be needed to implement the CommandLineRunner interface so you can run your job as a standalone application. An implementation of such would be :

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext applicationContext) {
        return args -> {
            // Job code
            System.exit(0);
        };
    }
  • So the way I implement CommandLineRunner right now (shown in the OP now) is wrong? `@SpringBootApplication public class MyApplication implements CommandLineRunner {` – gene b. Mar 24 '23 at 15:46
  • I wouldn't say that it is wrong but the traditional way of implementing command line runner is by creating a bean. Either way I think further expertise might be needed, just tried to be of help. – kevin halili Mar 24 '23 at 15:52
1

I found the solution: just remove from Pom.xml the spring-boot-starter-web dependency, per this thread.

    <!--  Removed 
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    -->

This automatically removes the embedded Tomcat. In fact, I don't even need to do SpringApplication.exit() anymore, I got rid of that extra code. Now the job immediately terminates on completion.

gene b.
  • 10,512
  • 21
  • 115
  • 227