Feb 2, 2021

Loading Local Test Data in Spring Boot

When working on an API, it can be nice to load some data locally on startup. This is especially true when working on a read-only endpoint where no REST API is available to POST any new data. There’s a few different ways to load data in Spring Boot, so this post will walk you through the options and give my preferred approach.

🚀 Your first step is to look at the Spring Boot Docs, where you see that the recommended approach is to use a data.sql file (or import.sql if you have Hibernate ddl-auto manage your tables). So, thinking that’s a good idea, you might write up something like:

merge into MY_OBJECTS values ('e166755b-2b99-43e4-bf64-74ddff84d064', 'abc', '123');
merge into MY_OBJECTS values ('bbe14733-6db7-4f15-ab3a-13fd0e29d397', 'def', '456');
merge into MY_OBJECTS values ('7cebd07b-2334-4c6d-baf9-efe194ae29a5', 'xyz', '789');

⚠️ This works fine for small pieces of data, or for very simple tables, but you’ll notice a few problems that come with this approach:
1) Generated IDs and UUID’s will be complicated
2) Any Spring data validation rules will be missed
3) Enums will not be respected
4) Difficult to reference data from other tables

☕ Then maybe, like me, you miss the Grails way of having a Bootstrap.groovy class that gets magically called at system startup? Grails would run this script file after startup before serving the application, and it was a great place to add test local data.

And this is how I felt for a long time, that Spring Boot just didn’t have an easy way to do something similar. Until I had a Twitter conversation, where it was shown to me about using an ApplicationRunner.java class.

But interestingly when I dove back into the Spring Docs to find more info, there’s really only an obscure reference to ApplicationRunner.java, and even then there isn’t an example of how to use it.

📝 So here’s my take at using ApplicationRunner to bootstrap some SpringBoot data:

This fixes all of my complaints about data.sql from above:
1) The ID is not specified, so UUID will get auto-generated
2) It uses the Repository class to save, along with using an Entity Validations
3) If this class needed to use an Enum we could easily reference it
4) We can do other table operations first, like only insert the data if the table is empty

❗Note a couple of other things:
A) The @Profile annotation specifies to only run this for the local and test profiles. These are fairly common custom profiles to have, but you’ll need to setup your application to use these (or others) if you don’t have them already.
B) I’m using Lombok to auto generate the constructor. You don’t have to use Lombok, if you love typing lots of boilerplate, so you can remove that annotation and write your own constructor.

This certainly isn’t for every application, so just take it as a tool to add to your toolbox. But I’m mostly writing this because I was surprised that the concept was around for many years now and somehow I had just never stumbled upon it, until now!

About the Author

Jeff Sheets profile.

Jeff Sheets

VP - Technology

Jeff has developed Java, Groovy, Grails, and Javascript web apps for industries as varied as Defense, Energy, Weather, Insurance, and Telecom. He is a co-organizer of the Omaha Java Users Group. Jeff has worked on Grails projects since the Grails 1.3.x days, and has experience with production Groovy code as well as Spock tests and Gradle builds. His latest focus has been on AngularJS and Spring Boot applications using JHipster. Jeff also enjoys volunteering at local CoderDojo events to teach programming to our next generation.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
AWS Cloud HSM, Docker and NGINX
There is quite a bit of easily searchable content on the security benefits of leveraging a Hardware Security Module to manage cryptographic keys, so I will leave that to the scope of another article. The […]
Google Professional Machine Learning Engineer Exam 2021
Exam Description A Professional Machine Learning Engineer designs, builds, and productionizes ML models to solve business challenges using Google Cloud technologies and knowledge of proven ML models and techniques. The ML Engineer is proficient in all aspects […]
Designing Kubernetes Controllers
There has been some excellent online discussion lately around Kubernetes controllers, highlighted by an excellent Speakerdeck presentation assembled by Tim Hockin. What I’d like to do in this post is explore some of the implications […]
React Server Components
The React Team recently announced new work they are doing on React Server Components, a new way of rendering React components. The goal is to create smaller bundle sizes, speed up render time, and prevent […]