2

In spring boot web application, is it possible to ensure some code is executed before the embedded webserver (tomcat) is listening for incoming requests?

I have some data base migration scripts that need to be run before any request from my REST API is responded by the application. How can I do that? For now, my migration script component uses @EventListener for ContextRefreshedEvent but that is too late. The following line is already logged before:

o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8091 (http) with context path ''

Steffen Harbich
  • 2,639
  • 2
  • 37
  • 71
  • 1
    consider to use flyway for example, it has a very good integration with springboot and it runs all the migration scripts that you need before the server starts https://www.baeldung.com/database-migrations-with-flyway – JArgente Jan 04 '21 at 15:05
  • Using Neo4j, it would be Liquigraph but I am already happy with my migration part which is working fine except that it is run too late. But thanks for the pointer. – Steffen Harbich Jan 05 '21 at 08:16

2 Answers2

1

You can use @PostConstruct method in the bean that you use to connect to the database (repository) and write there the code you need to run the scripts, this code is going to be executed after the bean is created but before the server is running.

Example: https://www.baeldung.com/spring-postconstruct-predestroy

Archmede
  • 1,592
  • 2
  • 20
  • 37
JArgente
  • 2,239
  • 1
  • 9
  • 11
  • How it is garantueed that the server is run after bean constructions? – Steffen Harbich Jan 05 '21 at 08:17
  • I tried with `@PostContstruct` and it's working, thanks. The order is correct. Still wondering if this is a coincidence or garantueed. – Steffen Harbich Jan 05 '21 at 08:22
  • 1
    It must be executed before server starts to process request because as the documentation said this method is executed just after the bean initialization and the server doesnt run until the spring context is created with all beans initializated – JArgente Jan 05 '21 at 08:27
  • I'm sorry, but this doesn't work. When I declare all dependencies I need for migration then the @PostConstruct method is called after tomcat is initialized. – Steffen Harbich Jan 05 '21 at 10:37
  • I'm not totally sure why it is executed after server initialization, anyway for this kind of task, I think the best option is to use flyway or liquidbase, which is designed specifically for this tasks and it ensures to be executed before initialization – JArgente Jan 05 '21 at 10:46
  • Please note that `@PostConstruct` cannot be used if its code relies on event publishing with `@EventListener`s to be called, see [here](https://stackoverflow.com/questions/47271498). – Steffen Harbich Jan 12 '21 at 13:30
1

I used the following approach finally:

@Component
public class MigrationLogic implements SmartInitializingSingleton {

    @Override
    @Transactional
    public void afterSingletonsInstantiated() {
        // run your logic here, declare dependencies with @Autowired
    }

}

The SmartInitializingSingleton executes before the web server is starting up.

Steffen Harbich
  • 2,639
  • 2
  • 37
  • 71