Bootstrapping Data in Spring Boot
0 CommentsLast Updated on February 4, 2022 by jt
While developing a Spring Boot Application, sometimes we need to run a piece of code at startup. This code can be anything. You might want to log certain information or run some cron jobs or send some notifications. Or you might even want to start the application with seed data in the database.
In this post, We will take a look at different approaches to bootstrap a Spring Boot application during startup.
Bootstrapping with Spring Boot
Spring Boot offers different ways to execute logic on startup. One of the common ways is to use the CommandLineRunner
Interface.
Using CommandLineRunner
CommandLineRunner
is an interface used to indicate that a bean should run when it is contained within a SpringApplication.
In this example code, I will create a domain object to model meme creaters. I will use the embedded H2
database for the demo.
Maven Dependency
For this demo, you need the following core dependencies in your pom.xml
file.
pom.xml
<dependency> <groupId>org.springframework.boot</groupId> lt;artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency>
The Domain Class
The code of the MemeMaker
domain class is this.
MemeMaker.java
@Entity @Table(name = "memes") @Getter @Setter public class MemeMaker { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int memeId; private String memeMaker; private String memeLevel; private String memeCategory; public MemeMaker() { } public MemeMaker(String memeMaker, String memeLevel, String memeCategory) { this.memeMaker = memeMaker; this.memeLevel = memeLevel; this.memeCategory = memeCategory; } }
The preceding code uses Lombok
to reduce boilerplate code. If you are new to Lombok
, I suggest going through my post on Lombok.
The code of the Repository Interface is this.
MemeRepository
@Repository public interface MemeRepository extends CrudRepository<MemeMaker, Integer> { }
The configuration properties for H2 in-memory database is set in the application.properties
file.
application.properties
spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:memedb
The h2 console is set to true in Line 1 which enables the h2-console view in the browser, and the datasource.url
is set to jdbc:h2:mem:memedb
where memedb
is the set database name.
The code for BootstrapCommandLineRunner
class, that bootstraps the application with seed data, is this.
BootstrapCommandLineRunner.java
@Component public class BootstrapCommandLineRunner implements CommandLineRunner { private MemeRepository memeRepository; @Autowired public BootstrapCommandLineRunner(MemeRepository memeRepository) { this.memeRepository = memeRepository; } @Override public void run(String... args) throws Exception { memeRepository.save(new MemeMaker("Alex","Novice", "Sports")); memeRepository.save(new MemeMaker("John","OG", "Wholesome")); memeRepository.findAll().forEach((meme) -> { }); } }
The preceding code annotates the class with @Component
so that Spring detects it during component scanning. When you start the application, the overriden run()
method will execute.
With the @Autowired
annotation in Line 6, we inject the MemeRepository
bean into the repository field.
The run()
method uses the @Autowired
MemeRepository
to create two Meme
objects and stores them in the H2
database.
Note: A Spring Boot application can have multiple beans implementing CommandLineRunner
. These can be ordered with @Order
annotation.
Bootstrapping with Spring Framework
The Spring Framework provides the ApplicationListener
interface that allows you to tap into various events of the framework. One such event that you can handle to bootstrap data is ContextRefreshedEvent
.
The following code shows how to use the ApplicationListener
interface.
BootstrapApplicationListener.java
@Component public class BootstrapApplicationListener implements ApplicationListener { private MemeRepository memeRepository; @Autowired public BootstrapApplicationListener(MemeRepository memeRepository) { this.memeRepository = memeRepository; } @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { memeRepository.save(new MemeMaker("Bob","Noobie", "Horror")); memeRepository.save(new MemeMaker("Hitman","OG", "Global")); } }
The preceding code overrides the overloaded onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
method of ApplicationListener
. Inside this method, the code uses the autowired repository to create and save two Memes objects.
Console Output
After you login to the H2 database on the URL localhost:8080/h2-console
using the JDBC URL set in application.properties
, you will see the following output.
Summary
In addition to the most common bootstrapping approaches I have shown, there are also other ways to do the same thing. One is using the @PostConstruct
annotation. Another is to use ApplicationRunner
instead of CommandLineRunner
. Although both are different ways to do the same things, they are different based on what the run()
method accepts. The run()
method of CommandLineRunner
accepts raw Strings. On the other hand, ApplicationRunner
accepts an instance of ApplicationArguments
so that you can access the bootstrap arguments passed when initializing the application.
You can find the source code of this post here on Github.
For in-depth knowledge on executing logic on Startup, you can check my Udemy Best Seller Course Spring Framework 5: Beginner to Guru