Issue
I have a Spring Boot application that uses a large number pre-populated tables. The content of these tables can change between instances. I currently load the tables from JSON files using the following code:
@Configuration
public class PreLoader {
@Bean
@Conditional(PreloadCondition.class)
Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulatorNameType() {
Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean();
final Logger log = LoggerFactory.getLogger(Jackson2RepositoryPopulatorFactoryBean.class);
Resource[] resources = null;
try {
resources = new PathMatchingResourcePatternResolver().getResources("classpath*:*-data.json");
log.debug("Found {} resources for preloading:", resources.length);
for (Resource resource : resources) {
log.debug(resource.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
factory.setResources(resources);
return factory;
}
}
How can I modify this code to run only on initialization of the database? I have tried using @Conditional as follows:
@Configurable
public class PreloadCondition implements Condition {
@PersistenceContext
private EntityManager entityManager;
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return tableExistsService.exists("identity_use");
}
static boolean tableExistsSQL(Connection connection, String tableName) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement("SELECT count(*) "
+ "FROM information_schema.tables "
+ "WHERE table_name = ?"
+ "LIMIT 1;");
preparedStatement.setString(1, tableName);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
return resultSet.getInt(1) != 0;
}
}
However, the entityManager is null - possibly because the class is not "Spring managed"? @Configurable does not seem to help?
Solution
For reference, in case others stumble across this question. I decided to use a different Conditional to solve this issue. The code block follows. Note 1) the "conditional" data was read from application.properties and 2) multiple resource files can be loaded. Hope this helps someone!
@Configuration
@ConditionalOnProperty(
prefix = "myappname",
name = "initialize",
havingValue = "true",
matchIfMissing = false)
public class PreLoader {
@Bean
Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulatorNameType() {
Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean();
final Logger log = LoggerFactory.getLogger(Jackson2RepositoryPopulatorFactoryBean.class);
Resource[] resources = null;
try {
resources = new PathMatchingResourcePatternResolver().getResources("classpath*:*-data.json");
log.debug("Found {} resources for preloading:", resources.length);
for (Resource resource : resources) {
log.debug(resource.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
factory.setResources(resources);
return factory;
}
}
Answered By - skyman
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)