Spring Boot - Loading Initial Data

Ömer Kurular
3 min readMay 16, 2021

In this post, I am going to talk about loading initial data to our database for later use in our Spring Boot application.

Firstly, let’s look at why we may need initial data.

  • First use case is that after application started, we may be in need of data already created in our database for us. Imagine a situation where you scrape a website and collect a huge amount of data and you are planning to use it in the regular flow of the application. If such a condition occurs, you will need to load the collected data right after your application starts.
  • Another use case can be that we load initial data for test purpose. You prepare a set of test data and load them right after starting application and you can proceed your application to test phase.

We talked about use cases and now we can see how we can achieve this using Spring Boot annotations. We will need a one main annotation and one side annotation for this purpose. So, what are they?

  • @PostConstruct, our main annotation that will be used on methods that is to be run right after application starts.
  • @Profile, our side annotation to decide which classes to put into action according to the phase such as production or testing.

Let’s continue with the following UserInit class. It has autowired instances passwordEncoder and userRepository that will help us achieve the aimed logic but they are not main concerns here.

@Component
@Profile("dev")
public class UserInit {
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final UserRepository userRepository;
@Autowired
public UserInit(BCryptPasswordEncoder bCryptPasswordEncoder, UserRepository userRepository) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.userRepository = userRepository;
}
@PostConstruct
public void createTestUsers() {
if (!userRepository.findByUsername("admin").isPresent()) {
User admin = new User()
.setUsername("admin")
.setPassword(bCryptPasswordEncoder.encode("123"))
.setRoles(Arrays.asList(Role.ADMIN))
.setEmail("admin@gmail.com");
userRepository.save(admin);
}
if (!userRepository.findByUsername("user").isPresent()) {
User user = new User()
.setUsername("user")
.setPassword(bCryptPasswordEncoder.encode("123"))
.setRoles(Arrays.asList(Role.USER))
.setEmail("user@gmail.com");
userRepository.save(user);
}
}
}

In the above class, the first thing we can notice is Profile annotation. As I said before, this annotation will enable/disable this class according to the active profile. Here, we set it to “dev” so that in the dev(development) environment, this class will be taken into account. We can set the active profile in the application.properties file with the following line.

spring.profiles.active=dev

We covered Profile annotation so far and now we can talk about the part with PostConstruct annotation. We basically have one method annotated with @PostConstruct, createTestUsers. In this method, we are creating two different users to use when testing. These methods will be called when the application starts.

We can imagine another situation, let’s say we need to load a set of data from xml file before application started. We achieve it the same way, annotate a method with PostConstruct and then put your logic into it.

@PostConstruct
public void loadFromXml() {
// some code to read xml that is not our focus right now
for (XmlObject xmlObject : XmlFile) {
repository.save(xmlObject);
}
}

You probably want such data loading in production environment so you can annotate the enclosing class with Profile annotation giving proper profile name such as “prod”.

Of course, this is not limited to loading initial data, you can also have some logic to run after application start-up.

In this article, I talked about loading initial data in our application. I hope you enjoy it and find it useful.

--

--

Ömer Kurular

I am Ömer and currently working as a full-time software engineer. I will share my knowledge with you I gained through years of professional and self working.