Refactored database initialization
This commit introduces the `TaskRepositoryInitializer` component. This component will initialize the `DataSource` when appropriate and silently do nothing otherwise. It can be customized to initialize a specific `DataSource` as required. Resolves spring-cloud/spring-cloud-task#84
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,26 +25,25 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.cloud.task.listener.TaskLifecycleListener;
|
||||
import org.springframework.cloud.task.repository.TaskNameResolver;
|
||||
import org.springframework.cloud.task.repository.TaskRepository;
|
||||
import org.springframework.cloud.task.repository.support.SimpleTaskNameResolver;
|
||||
import org.springframework.cloud.task.repository.support.TaskDatabaseInitializer;
|
||||
import org.springframework.cloud.task.repository.support.TaskRepositoryInitializer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* Base {@code Configuration} class providing common structure for enabling and using
|
||||
* Spring Task. Customization is
|
||||
* available by implementing the {@link TaskConfigurer} interface.
|
||||
* Spring Task. Customization is available by implementing the {@link TaskConfigurer}
|
||||
* interface.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @author Michael Minella
|
||||
*/
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@@ -58,15 +57,9 @@ public class SimpleTaskConfiguration {
|
||||
@Autowired(required = false)
|
||||
private Collection<DataSource> dataSources;
|
||||
|
||||
@Autowired
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ApplicationArguments applicationArguments;
|
||||
|
||||
@Value("${spring.class.initialize.enable:true}")
|
||||
private boolean taskInitializationEnable;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private TaskRepository taskRepository;
|
||||
@@ -95,6 +88,17 @@ public class SimpleTaskConfiguration {
|
||||
return new SimpleTaskNameResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskRepositoryInitializer taskRepositoryInitializer() {
|
||||
TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer();
|
||||
|
||||
if(this.dataSources != null && this.dataSources.size() == 1) {
|
||||
taskRepositoryInitializer.setDataSource(this.dataSources.iterator().next());
|
||||
}
|
||||
|
||||
return taskRepositoryInitializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the basic components by extracting them from the {@link TaskConfigurer}, defaulting to some
|
||||
* sensible values as long as a unique DataSource is available.
|
||||
@@ -116,7 +120,7 @@ public class SimpleTaskConfiguration {
|
||||
}
|
||||
|
||||
private TaskConfigurer getDefaultConfigurer(Collection<TaskConfigurer> configurers) {
|
||||
boolean isDataSourceConfigured = (dataSources != null && !dataSources.isEmpty());
|
||||
boolean isDataSourceConfigured = (dataSources != null && dataSources.size() == 1);
|
||||
verifyEnvironment(configurers);
|
||||
if (configurers == null || configurers.isEmpty()) {
|
||||
if (!isDataSourceConfigured) {
|
||||
@@ -124,12 +128,7 @@ public class SimpleTaskConfiguration {
|
||||
return this.configurer;
|
||||
}
|
||||
else {
|
||||
DataSource dataSource = dataSources.iterator().next();
|
||||
if(taskInitializationEnable) {
|
||||
logger.debug("Initializing Task Schema");
|
||||
TaskDatabaseInitializer.initializeDatabase(dataSource, resourceLoader);
|
||||
}
|
||||
this.configurer = new DefaultTaskConfigurer(dataSource);
|
||||
this.configurer = new DefaultTaskConfigurer(this.dataSources.iterator().next());
|
||||
return this.configurer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,18 +20,32 @@ import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
|
||||
/**
|
||||
* Utility for initializing the Task Repository's datasource. If a single
|
||||
* {@link DataSource} is available in the current context, and functionality is enabled
|
||||
* (as it is by default), this will initialize the database. If more than one DataSource
|
||||
* is available in the current context, custom configuration of this is required
|
||||
* (if desired).
|
||||
*
|
||||
* By default, initialization of the database can be disabled by configuring the property
|
||||
* <code>spring.cloud.task.initialize.enable</code> to false.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @author Michael Minella
|
||||
*/
|
||||
|
||||
public final class TaskDatabaseInitializer {
|
||||
public final class TaskRepositoryInitializer implements InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskDatabaseInitializer.class);
|
||||
private static final Log logger = LogFactory.getLog(TaskRepositoryInitializer.class);
|
||||
|
||||
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
|
||||
+ "cloud/task/schema-@@platform@@.sql";
|
||||
@@ -41,12 +55,37 @@ public final class TaskDatabaseInitializer {
|
||||
*/
|
||||
private static String schema = DEFAULT_SCHEMA_LOCATION;
|
||||
|
||||
private TaskDatabaseInitializer(){
|
||||
private DataSource dataSource;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Value("${spring.cloud.task.initialize.enable:true}")
|
||||
private boolean taskInitializationEnable;
|
||||
|
||||
public TaskRepositoryInitializer(){
|
||||
}
|
||||
|
||||
public static void initializeDatabase(DataSource dataSource, ResourceLoader resourceLoader) {
|
||||
if (dataSource != null) {
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
private String getDatabaseType(DataSource dataSource) {
|
||||
try {
|
||||
return DatabaseType.fromMetaData(dataSource).toString().toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (dataSource != null && taskInitializationEnable) {
|
||||
String platform = getDatabaseType(dataSource);
|
||||
if ("hsql".equals(platform)) {
|
||||
platform = "hsqldb";
|
||||
@@ -70,14 +109,4 @@ public final class TaskDatabaseInitializer {
|
||||
DatabasePopulatorUtils.execute(populator, dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDatabaseType(DataSource dataSource) {
|
||||
try {
|
||||
return DatabaseType.fromMetaData(dataSource).toString().toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
|
||||
import org.springframework.cloud.task.repository.dao.TaskExecutionDao;
|
||||
import org.springframework.cloud.task.repository.support.SimpleTaskExplorer;
|
||||
import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
|
||||
import org.springframework.cloud.task.repository.support.TaskDatabaseInitializer;
|
||||
import org.springframework.cloud.task.repository.support.TaskRepositoryInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -46,6 +46,16 @@ public class TestConfiguration {
|
||||
@Autowired(required = false)
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Bean
|
||||
public TaskRepositoryInitializer taskRepositoryInitializer() throws Exception {
|
||||
TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer();
|
||||
taskRepositoryInitializer.setDataSource(this.dataSource);
|
||||
taskRepositoryInitializer.setResourceLoader(this.resourceLoader);
|
||||
taskRepositoryInitializer.afterPropertiesSet();
|
||||
|
||||
return taskRepositoryInitializer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskRepository taskRepository(TaskExecutionDao taskExecutionDao){
|
||||
return new SimpleTaskRepository(taskExecutionDao);
|
||||
@@ -57,8 +67,6 @@ public class TestConfiguration {
|
||||
return new ResourcelessTransactionManager();
|
||||
}
|
||||
else {
|
||||
TaskDatabaseInitializer.initializeDatabase(dataSource, this.resourceLoader);
|
||||
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,10 +18,10 @@ package org.springframework.cloud.task.repository.support;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.cloud.task.configuration.SimpleTaskConfiguration;
|
||||
@@ -30,42 +30,30 @@ import org.springframework.cloud.task.repository.TaskRepository;
|
||||
import org.springframework.cloud.task.util.TaskExecutionCreator;
|
||||
import org.springframework.cloud.task.util.TestDBUtils;
|
||||
import org.springframework.cloud.task.util.TestVerifierUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Tests for the SimpleTaskRepository that uses JDBC as a datastore.
|
||||
*
|
||||
* @author Glenn Renfro.
|
||||
* @author Michael Minella
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = {EmbeddedDataSourceConfiguration.class,
|
||||
SimpleTaskConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class})
|
||||
public class SimpleTaskRepositoryJdbcTests {
|
||||
|
||||
@Autowired
|
||||
private TaskRepository taskRepository;
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(SimpleTaskConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
dataSource = this.context.getBean(DataSource.class);
|
||||
JdbcTaskRepositoryFactoryBean factoryBean =
|
||||
new JdbcTaskRepositoryFactoryBean(dataSource);
|
||||
taskRepository = factoryBean.getObject();
|
||||
}
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testCreateTaskExecutionNoParam() {
|
||||
TaskExecution expectedTaskExecution =
|
||||
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
|
||||
@@ -75,6 +63,7 @@ public class SimpleTaskRepositoryJdbcTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testCreateTaskExecutionWithParam() {
|
||||
TaskExecution expectedTaskExecution =
|
||||
TaskExecutionCreator.createAndStoreTaskExecutionWithParams(taskRepository);
|
||||
@@ -84,6 +73,7 @@ public class SimpleTaskRepositoryJdbcTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testUpdateTaskExecution() {
|
||||
TaskExecution expectedTaskExecution =
|
||||
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
|
||||
@@ -95,6 +85,7 @@ public class SimpleTaskRepositoryJdbcTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testCreateTaskExecutionNoParamMaxExitMessageSize(){
|
||||
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
|
||||
expectedTaskExecution.setExitMessage(new String(new char[SimpleTaskRepository.MAX_EXIT_MESSAGE_SIZE+1]));
|
||||
@@ -102,6 +93,7 @@ public class SimpleTaskRepositoryJdbcTests {
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@DirtiesContext
|
||||
public void testCreateTaskExecutionNoParamMaxTaskName(){
|
||||
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
|
||||
expectedTaskExecution.setTaskName(new String(new char[SimpleTaskRepository.MAX_TASK_NAME_SIZE+1]));
|
||||
|
||||
Reference in New Issue
Block a user