Spring Application Bootstrap Data
When you install an application for the first time, many times you want ‘bootstrap’ data to exist before the application is used for the very first time. Here’s a simple but easy technique to get bootstrap data inserted into your application upon first startup.
Prior to the following approach, I used to have ‘default.data’ and ‘sample.data’ tasks in my ant scripts that either ran SQL manually, or started up a separate Spring ApplicationContext and inserted data explicitly. You had to run it manually from ant, which 1) required that ant be installed and 2) that you had the project checked out on the box that you were installing data to. Many production and QA environments didn’t meet this criteria, and even if they did, it is still cumbersome and isn’t as nice as an ‘automatic’ solution.
My newer automatic solution moves this type of data insertion logic into the actual application, where it is better managed and tested. There is another benefit too though: Since I use Hibernate and JCR as the EIS-tier APIs, it is far easier to insert data via these standard APIs than to do so via raw SQL. This is because you can write all of your initial data objects and graphs with Java or Groovy POJOs, utilizing the benefits of powerful IDE coding features, and let the Hibernate and JCR frameworks insert all the data with dependencies for you: a massive time saver.
So, here’s a simple way to do this:
You create a POJO that will execute at application startup automatically after its dependencies have been injected. Here’s an example:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
public class BootstrapDataPopulator implements InitializingBean {
private transient final Log log = LogFactory.getLog( getClass() );
//Spring's transaction manager - needed to ensure data is inserted in a transaction:
//any failures, and we can roll back everything.
private PlatformTransactionManager transactionManager = null;
//all other managers/dependencies here
public BootstrapDataPopulator() {
}
public void setTransactionManager( PlatformTransactionManager transactionManager ) {
this.transactionManager = transactionManager;
}
//other dependency setter methods
public void afterPropertiesSet() throws Exception {
if ( this.transactionManager == null ) {
throw new IllegalStateException( "transactionManager property must be set." );
}
//assert other injected dependencies here
TransactionTemplate txnTemplate = new TransactionTemplate( this.transactionManager );
txnTemplate.afterPropertiesSet();
txnTemplate.execute( new TransactionCallback() {
public Object doInTransaction( TransactionStatus status ) {
try {
insertBoostrapData();
} catch ( Exception e ) {
//error - roll back. Runtime exception triggers rollback:
if ( e instanceof RuntimeException ) {
throw (RuntimeException)e;
} else {
throw new RuntimeException( e );
}
}
return null;
}
} );
}
private boolean guestUserExists() {
return userManager.findUserByUsername( "guest" ) != null;
}
protected void insertBoostrapData() throws Exception {
//if the guest user account exists, take this as a sign that the bootstrap data populator has
//already been run, so just exit quietly:
if ( guestUserExists() ) {
if ( log.isDebugEnabled() ) {
log.debug( "Bootstrap data insertion has already occurred. Returning quietly." );
}
return;
}
if ( log.isInfoEnabled() ) {
log.info( "Inserting bootstrap data..." );
}
//otherwise, populate bootstrap data:
log.debug("Creating guest user...");
User guestUser = someManager.create( new User( "Guest", "guest@domain.com" ) );
//insert all other objects and call any other helper methods here
}
}
The key to this code working as a POJO in your normal application configuration is due to two things:
- The insertBootstrapData() method is wrapped in the TransactionTemplate. If anything goes wrong during the execution of that method, it will be rolled back and the database remains in a consistent state
- The first bit of code in insertBootstrapData() checks to see if a well-known entity already exists in the database. If it does, you can assume that the bootstrap data has already been inserted, and return quietly.
You can create other ‘Bootstrap Beans’ like this to do other things as well. The above one initialized RDBMS data. You can have another one that initializes your JCR repository. Or another that checks against a license store to ensure that the application installed is allowed to be installed. All sorts of things…
2 Responses to Spring Application Bootstrap Data
Leave a Reply Cancel reply
Tags
Archives
- June 2011
- December 2010
- November 2010
- September 2010
- April 2010
- February 2010
- January 2010
- December 2009
- November 2009
- August 2009
- May 2009
- March 2009
- December 2008
- August 2008
- March 2008
- February 2008
- January 2008
- December 2007
- August 2007
- July 2007
- June 2007
- February 2007
- November 2006
- August 2006
- July 2006
- June 2006
- April 2006
- March 2006
- February 2006
- January 2006





Thankss I wass doing in a quitee harder way
Thanks a lot for sharing!
Still works for me if i change
private PlatformTransactionManager transactionManager = null;
to
@Autowired
private PlatformTransactionManager transactionManager;
Using Spring 3.1.1