Pranav C Balan
Pranav C Balan

Reputation: 115272

Spring boot data insertion after spring boot starts

I am developing web project in spring boot. I'm using hibernate jpa and spring security. I need to create some user when the spring boot app is started using some service. I have tried using @PostConstruct annotation, but it's not inserting data to db.

@Component
public class Monitor {
    @Autowired private UserService service

    @PostConstruct
    public void init(){
        if(!service.findBySsoId('admin')) {
            service.save(new User(ssoId: 'admin',
            lastName: 'amdmin',
                    firstName: 'admin',
                    contactNumber: '9999999999',
                    password: '11changeme',
                    address2: '',
                    address1: '',
                    city: ''
            ),[UserProfileType.ADMIN,UserProfileType.USER,UserProfileType.DBA])
        }
    }
}

In grails I've done this by adding it in bootstrap.groovy, in spring boot how can I do that ?

Upvotes: 2

Views: 2906

Answers (3)

Christian Meyer
Christian Meyer

Reputation: 625

To be honest you can probably find better solutions if this is data that you always want to insert on startup, and not just for development purposes. But I usually just implement CommandLineRunner to quickly populate some useful objects and save them to my db while I'm developing other components in order to do some preliminary testing. This way, I do not need to, say, create controller methods to do the same thing when I know that I'll just be deleting a lot of the logic that I just implemented later on (since it's a bit more time consuming). For example:

@SpringBootApplication
class Application implements CommandLineRunner {
   public static void main(String... args){
      SpringApplication.run(Application.class, args);
   }

   @Autowired ObjectRepository repo;
   @Override
   public static void run(){
      Object obj1 = new Object(1, "obj1");
      repo.save(obj1);
   }
}

The downside to this approach is that it can be difficult to assess what is actually running in the run method, since it is being ran before the call to SpringApplication.run... You may need to explicitly add something like @ComponentScan(baseClassPackages="com.app.repository") to register your repositories in the first place.

On the other hand, if you are looking for something more permanent, you could create a sql file with the required insert statements and add it to your classpath. Then, add spring.datasource.data=objectinsertions.sql and it will automatically execute the insert statements in that sql file on startup. This may also require you to define a schema, and similarly add a spring.datasource.schema=objectddl.sql line. This approach will certainly work using JDBC, but I'm actually not sure if it will work using JPA.

Upvotes: 1

Rafal G.
Rafal G.

Reputation: 4432

Looking at your code I cannot see why your user creation has to be done from Java code. Spring Boot has a special feature called "Database Initialization" that would be imo quite a good way to achieve what you want.

Check out these docs.

You can just add file data.sql (or data-{platform}.sql) that would contain necessary logic written in SQL. This part could be easily tested using Spring Boot's integration testing capabilities (@IntegrationTest).

Upvotes: 3

Atul
Atul

Reputation: 2711

Instead of listening to bean creation event (@PostConstruct), do you want to listen to when the context or application starts

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html

@Component
public class SeedDataService {

    @EventListener
    public void handleContextRefresh(ContextStartedEvent event) {
        //Update the records in the DB
    }
}

You can use ApplicationStartedEvent in newer versions of boot or ContextStartedEvent

I think you are encountering the problem because all the dependencies are not created when your bean is created; some are still in the process of construction. These may not be your bean's dependencies as such but the dependencies which are preventing the SpringApplication to treat itself as started.

Upvotes: 2

Related Questions