diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java index bdd05e6e..1606f325 100644 --- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java +++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java @@ -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 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 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; } } diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskRepositoryInitializer.java similarity index 59% rename from spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java rename to spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskRepositoryInitializer.java index a6d2855c..79b9c7f9 100644 --- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java +++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskRepositoryInitializer.java @@ -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 + * spring.cloud.task.initialize.enable 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); - } - } - } diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/TestConfiguration.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/TestConfiguration.java index 1930a885..199d4267 100644 --- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/TestConfiguration.java +++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/TestConfiguration.java @@ -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); } } diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java index d34bf9cc..3da49518 100644 --- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java +++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java @@ -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]));