Last Updated: February 25, 2016
·
6.606K
· gavinbunney

Bootstrapping data with Spring

So you find yourself working on a 'traditional' Java Spring project, and you need some reference data pre-populated into your database.

In Grails this is quite easy - just crack open bootstrap.groovy and start creating new entities.

Fortunately, we can create a similar mechanism using an InitializingBean and a bit of pre-conditional checking.

Bean Class

In our example application, we need a system user and a bunch of country codes added to our database. This can always be expanded to read lists from xml/csv files, but keeping things simple for this example.

Each individual function is responsible for checking if it's data is required to be bootstrapped, or if it always has been.

@Service
public class BootstrapDataPopulator implements InitializingBean {

    private final Logger LOG = LoggerFactory.getLogger(BootstrapDataPopulator.class);

    @Autowired
    UserRepository userRepository;

    @Autowired
    CountryCodeRepository countryCodeRepository;

    @Override
    @Transactional()
    public void afterPropertiesSet() throws Exception {
        LOG.info("Bootstrapping data...");

        createSystemUser();
        createCountryCodes();

        LOG.info("...Bootstrapping completed");
    }

    private void createSystemUser() {
        if (userRepository.getSystemUser() != null) {
            return;
        }

        LOG.info("... creating system user");

        User user = new User();
        user.setUsername(userRepository.getSystemUsername());
        user.setFirstName("System");
        user.setLastName("User");
        userRepository.saveAndFlush(user);
    }

    private void createCountryCodes() {
        if (countryCodeRepository.count() > 0) {
            return;
        }

        LOG.info("... creating Country codes");

        List<CountryCode> codes = new ArrayList<>();
        codes.add(new CountryCode(1, "AU", "Australia"));
        codes.add(new CountryCode(2, "USA", "United States of America"));
        codes.add(new CountryCode(3, "NZ", "New Zealand"));
        countryCodeRepository.save(codes);
        countryCodeRepository.flush();
    }
}

Bean Declaration

In the above example, we are using the @Service annotation to initialize the bean, but there is no reason you can't declare the bootstrap bean more explicitly.

Logs for Logging logs

The advantage of the 'individual function' sort of pattern is you easily see what parts of the bootstrapping process are occuring

E.g. on first run:

Bootstrapping data...
... creating system user
... creating Country codes
...Bootstrapping completed

And subsequent runs:

Bootstrapping data...
...Bootstrapping completed