SpringBot Seeding Data
Core Data
To seed this initial data, we first want to create a CoreData
class. This class will contain everything we need to seed all of the data we need in our application.
For this example we will be seeding a workflow from the Workflow extension.
ApplicationRunner Interface
Using the @Component
annotation allows this bean to be registered with SpringBoot.
Now to ensure this class runs on the application startup, we implement the ApplicationRunner
interface. This interface does one thing, ensures the run
method is executed at application start.
@Component
@Slf4j
public class CoreData implements ApplicationRunner {
...
Dependency Injection
Given we are working with data, we will need to inject all of the required repositories into our new class. This is allowed due to us declaring class as a SpringBoot component.
private final WorkflowRepository workflowRepository;
private final WorkflowVersionRepository workflowVersionRepository;
private final WorkflowStateRepository workflowStateRepository;
private final WorkflowTransitionRepository workflowTransitionRepository;
@Autowired
public CoreData(
WorkflowRepository workflowRepository,
WorkflowVersionRepository workflowVersionRepository,
WorkflowStateRepository workflowStateRepository,
WorkflowTransitionRepository workflowTransitionRepository) {
this.workflowRepository = workflowRepository;
this.workflowVersionRepository = workflowVersionRepository;
this.workflowStateRepository = workflowStateRepository;
this.workflowTransitionRepository = workflowTransitionRepository;
}
...
AnonymousHelper
Now, given everything is controlled by our security model and in our startup data class we are not registered within our authentication context, we in theory cannot access anything.
To bypass this, we can make use of the AnonymousHelper.runAnonymously
helper method that bypasses our security.
WARNING As this completely bypasses security, be very careful where you use this.
@Override
public void run(ApplicationArguments args) throws Exception {
AnonymousHelper.runAnonymously(() -> {
this.injectRegistrationWorkflow();
});
}
Injection
Given our class now runs on startup, we have the appropriate permissions, and we have our repositories injected and ready to use, we can begin to inject our data.
This example sets up the registration workflow, additional methods like this can be created and added to the run
method to insert more data.
You will notice before we do anything in this method, we check to ensure it has not already been run with the this.workflowVersionRepository.count() == 0
conditional.
This workflow will operate as follows.

/**
* Inject the workflow states and transitions for Registration entity
*/
private void injectRegistrationWorkflow() {
// Check to see if any already exist, only create if it is a fresh install
if (this.workflowVersionRepository.count() == 0) {
/* Setup Workflow */
var workflowName = "Registration Workflow";
var registrationWorkFlow = new WorkflowEntity();
registrationWorkFlow.setName(workflowName);
registrationWorkFlow = this.workflowRepository.save(registrationWorkFlow);
var registrationWorkflowVersion = new WorkflowVersionEntity();
registrationWorkflowVersion.setRegistrationAssociation(true);
registrationWorkflowVersion.setWorkflowDescription("Workflow for a patients registration.");
registrationWorkflowVersion.setWorkflowName(workflowName);
registrationWorkflowVersion.setWorkflow(registrationWorkFlow);
registrationWorkflowVersion = workflowVersionRepository.save(registrationWorkflowVersion);
/* Create states */
var pendingState = new WorkflowStateEntity();
pendingState.setStepName("Pending");
pendingState.setIsStartState(true);
pendingState.setWorkflowVersion(registrationWorkflowVersion);
this.workflowStateRepository.save(pendingState);
var bookedState = new WorkflowStateEntity();
bookedState.setStepName("Booked");
bookedState.setWorkflowVersion(registrationWorkflowVersion);
this.workflowStateRepository.save(bookedState);
var cancelledState = new WorkflowStateEntity();
cancelledState.setStepName("Cancelled");
cancelledState.setWorkflowVersion(registrationWorkflowVersion);
this.workflowStateRepository.save(cancelledState);
var completedState = new WorkflowStateEntity();
completedState.setStepName("Completed");
completedState.setWorkflowVersion(registrationWorkflowVersion);
this.workflowStateRepository.save(completedState);
/** Create transitions **/
var pendingToBookedTransition = new WorkflowTransitionEntity();
pendingToBookedTransition.setTransitionName("Booked");
pendingToBookedTransition.setSourceState(pendingState);
pendingToBookedTransition.setTargetState(bookedState);
this.workflowTransitionRepository.save(pendingToBookedTransition);
var pendingToCancelledTransition = new WorkflowTransitionEntity();
pendingToCancelledTransition.setTransitionName("Cancelled");
pendingToCancelledTransition.setTargetState(cancelledState);
pendingToCancelledTransition.setSourceState(pendingState);
this.workflowTransitionRepository.save(pendingToCancelledTransition);
var bookedToCancelledTransition = new WorkflowTransitionEntity();
bookedToCancelledTransition.setTransitionName("Cancelled");
bookedToCancelledTransition.setSourceState(bookedState);
bookedToCancelledTransition.setTargetState(cancelledState);
this.workflowTransitionRepository.save(bookedToCancelledTransition);
var bookedToCompletedTransition = new WorkflowTransitionEntity();
bookedToCompletedTransition.setTransitionName("Completed");
bookedToCompletedTransition.setSourceState(bookedState);
bookedToCompletedTransition.setTargetState(completedState);
this.workflowTransitionRepository.save(bookedToCompletedTransition);
}
}
Test Data
Often, you will have data you want to run when developing or testing that do not want in production. This can be achieved by creating another class like the CoreData
one above called TestData
.
To ensure this new class only runs when in test mode, add the annotation @Profile({"test"})
to the class signature.
@Component
@Profile({"test"})
public class TestData implements ApplicationRunner {
...
}
This annotation can used for the other run profile that SpringBot supports, dev
.
Was this article helpful?