7
votes

I have a Spring Boot web application packaged as a WAR file and I wish to have the ability to run some tasks (scripts or commands) on-demand. For example:

  • Initialize the database schema
  • Seed the database programmatically
  • Data migration when required for new versions of the application (move files, database operations, etc.)
  • Validate data integrity between stored files and database contents

These "commands" would be much easier to implement if they had access to the same beans (services, DAOs) and models as the web app proper. I expect I have to create a Spring application context somewhere for this to happen. I would also prefer to package these commands with the rest of the application so they are tested alongside it and easy to deploy.

Essentially, I want to know how to achieve something similar to Laravel's artisan commands (PHP).

I have read on running a class inside a WAR here and here. I'm searching for the "Spring way" of packaging and running commands. Do I have to integrate Spring Batch jobs for this? From what I understand, Spring Batch is meant for larger workloads which can be split in multiple batches. Should I bite the bullet and put the commands in a second separate maven module which references the first one?

update

I implemented an ApplicationRunner (thanks Stefan!) to see how they work and found that they run after the Spring application context is refreshed. This means that the whole web application is initialized and active before the runner executes. This includes MVC endpoint mappers and scheduled tasks defined in configurations. While this can definitely be useful, I need to run commands when all that is not active because it can come in conflict with the commands (especially with transient data states during command runs).

update 2

I simply needed to create another executable jar that creates a Spring Boot application using a CommandLineRunner. This can reference all the beans from the web application if I use 3 modules:

  1. The spring "service" beans module
  2. The web application module
  3. The command line runner module
2

2 Answers

4
votes

You can use ApplicationRunner see spring boot application runner. The runners are executed after the app started and you have access to the spring context.

The CommandLineRunner class is used precisely for this. See also How does a Spring Boot console based application work?

0
votes

By using spring data jpa you can easily achieve this

1-By developing your entity classes which represent your database schema and set the property spring.jpa.hibernate.ddl-auto=create, the schema will created for you when you run the application(be careful, because each time you run the schema will be dropped and recreated for you)

2-you can include whatever sql statements in an import.sql which should be placed in resources folder with configuration file(it's a hibernate feature but still works pretty fine with spring).

initialize database with jpa

initialize database with hibernate