Added checkstyle
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -36,13 +36,14 @@ import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Default implementation of the TaskConfigurer interface. If no {@link TaskConfigurer}
|
||||
* implementation is present, then this configuration will be used.
|
||||
* The following defaults will be used:
|
||||
* Default implementation of the TaskConfigurer interface. If no {@link TaskConfigurer}
|
||||
* implementation is present, then this configuration will be used. The following defaults
|
||||
* will be used:
|
||||
* <ul>
|
||||
* <li>{@link SimpleTaskRepository} is the default {@link TaskRepository} returned.
|
||||
* If a data source is present then a data will be stored in the database {@link JdbcTaskExecutionDao} else it will
|
||||
* be stored in a map {@link MapTaskExecutionDao}.
|
||||
* <li>{@link SimpleTaskRepository} is the default {@link TaskRepository} returned. If a
|
||||
* data source is present then a data will be stored in the database
|
||||
* {@link JdbcTaskExecutionDao} else it will be stored in a map
|
||||
* {@link MapTaskExecutionDao}.
|
||||
* </ul>
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
@@ -67,12 +68,11 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the DefaultTaskConfigurer and sets the default table prefix
|
||||
* to {@link TaskProperties#DEFAULT_TABLE_PREFIX}.
|
||||
*
|
||||
* Initializes the DefaultTaskConfigurer and sets the default table prefix to
|
||||
* {@link TaskProperties#DEFAULT_TABLE_PREFIX}.
|
||||
* @param dataSource references the {@link DataSource} to be used as the Task
|
||||
* repository. If none is provided, a Map will be used (not recommended for
|
||||
* production use.
|
||||
* repository. If none is provided, a Map will be used (not recommended for production
|
||||
* use.
|
||||
*/
|
||||
public DefaultTaskConfigurer(DataSource dataSource) {
|
||||
this(dataSource, TaskProperties.DEFAULT_TABLE_PREFIX, null);
|
||||
@@ -80,9 +80,8 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
|
||||
|
||||
/**
|
||||
* Initializes the DefaultTaskConfigurer.
|
||||
*
|
||||
* @param tablePrefix the prefix to apply to the task table names used by
|
||||
* task infrastructure.
|
||||
* @param tablePrefix the prefix to apply to the task table names used by task
|
||||
* infrastructure.
|
||||
*/
|
||||
public DefaultTaskConfigurer(String tablePrefix) {
|
||||
this(null, tablePrefix, null);
|
||||
@@ -90,23 +89,23 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
|
||||
|
||||
/**
|
||||
* Initializes the DefaultTaskConfigurer.
|
||||
*
|
||||
* @param dataSource references the {@link DataSource} to be used as the Task
|
||||
* repository. If none is provided, a Map will be used (not recommended for
|
||||
* production use.
|
||||
* @param tablePrefix the prefix to apply to the task table names used by
|
||||
* task infrastructure.
|
||||
* repository. If none is provided, a Map will be used (not recommended for production
|
||||
* use.
|
||||
* @param tablePrefix the prefix to apply to the task table names used by task
|
||||
* infrastructure.
|
||||
* @param context the context to be used.
|
||||
*/
|
||||
public DefaultTaskConfigurer(DataSource dataSource, String tablePrefix, ApplicationContext context) {
|
||||
public DefaultTaskConfigurer(DataSource dataSource, String tablePrefix,
|
||||
ApplicationContext context) {
|
||||
this.dataSource = dataSource;
|
||||
this.context = context;
|
||||
|
||||
TaskExecutionDaoFactoryBean taskExecutionDaoFactoryBean;
|
||||
|
||||
if(this.dataSource != null) {
|
||||
taskExecutionDaoFactoryBean = new
|
||||
TaskExecutionDaoFactoryBean(this.dataSource, tablePrefix);
|
||||
if (this.dataSource != null) {
|
||||
taskExecutionDaoFactoryBean = new TaskExecutionDaoFactoryBean(this.dataSource,
|
||||
tablePrefix);
|
||||
}
|
||||
else {
|
||||
taskExecutionDaoFactoryBean = new TaskExecutionDaoFactoryBean();
|
||||
@@ -137,22 +136,27 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
|
||||
if (isDataSourceAvailable()) {
|
||||
try {
|
||||
Class.forName("javax.persistence.EntityManager");
|
||||
if (this.context != null && this.context.getBeanNamesForType(EntityManager.class).length > 0) {
|
||||
logger.debug("EntityManager was found, using JpaTransactionManager");
|
||||
if (this.context != null && this.context
|
||||
.getBeanNamesForType(EntityManager.class).length > 0) {
|
||||
logger.debug(
|
||||
"EntityManager was found, using JpaTransactionManager");
|
||||
this.transactionManager = new JpaTransactionManager();
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ignore) {
|
||||
logger.debug("No EntityManager was found, using DataSourceTransactionManager");
|
||||
logger.debug(
|
||||
"No EntityManager was found, using DataSourceTransactionManager");
|
||||
}
|
||||
finally {
|
||||
if (this.transactionManager == null) {
|
||||
this.transactionManager = new DataSourceTransactionManager(this.dataSource);
|
||||
this.transactionManager = new DataSourceTransactionManager(
|
||||
this.dataSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.debug("No DataSource was found, using ResourcelessTransactionManager");
|
||||
logger.debug(
|
||||
"No DataSource was found, using ResourcelessTransactionManager");
|
||||
this.transactionManager = new ResourcelessTransactionManager();
|
||||
}
|
||||
}
|
||||
@@ -163,4 +167,5 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
|
||||
private boolean isDataSourceAvailable() {
|
||||
return this.dataSource != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -23,13 +23,12 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.cloud.task.repository.TaskRepository;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Enables the {@link org.springframework.cloud.task.listener.TaskLifecycleListener}
|
||||
* so that the features of Spring Cloud Task will be applied.
|
||||
* Enables the {@link org.springframework.cloud.task.listener.TaskLifecycleListener} so
|
||||
* that the features of Spring Cloud Task will be applied.
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -39,13 +38,14 @@ import org.springframework.context.annotation.Import;
|
||||
* @Bean
|
||||
* public MyCommandLineRunner myCommandLineRunner() {
|
||||
* return new MyCommandLineRunner()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Note that only one of your configuration classes needs to have the <code>@EnableTask</code>
|
||||
* annotation. Once you have an <code>@EnableTask</code> class in your configuration
|
||||
* the task will have the Spring Cloud Task features available.
|
||||
* Note that only one of your configuration classes needs to have the
|
||||
* <code>@EnableTask</code> annotation. Once you have an
|
||||
* <code>@EnableTask</code> class in your configuration the task will have the Spring
|
||||
* Cloud Task features available.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*
|
||||
@@ -56,4 +56,5 @@ import org.springframework.context.annotation.Import;
|
||||
@Inherited
|
||||
@Import(TaskLifecycleConfiguration.class)
|
||||
public @interface EnableTask {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -54,10 +54,13 @@ import org.springframework.util.CollectionUtils;
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableConfigurationProperties(TaskProperties.class)
|
||||
// @checkstyle:off
|
||||
@ConditionalOnProperty(prefix = "spring.cloud.task.autoconfiguration", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
// @checkstyle:on
|
||||
public class SimpleTaskAutoConfiguration {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(SimpleTaskAutoConfiguration.class);
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(SimpleTaskAutoConfiguration.class);
|
||||
|
||||
@Autowired(required = false)
|
||||
private Collection<DataSource> dataSources;
|
||||
@@ -80,7 +83,7 @@ public class SimpleTaskAutoConfiguration {
|
||||
private TaskExplorer taskExplorer;
|
||||
|
||||
@Bean
|
||||
public TaskRepository taskRepository(){
|
||||
public TaskRepository taskRepository() {
|
||||
return this.taskRepository;
|
||||
}
|
||||
|
||||
@@ -104,7 +107,7 @@ public class SimpleTaskAutoConfiguration {
|
||||
public TaskRepositoryInitializer taskRepositoryInitializer() {
|
||||
TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer();
|
||||
DataSource initializerDataSource = getDefaultConfigurer().getTaskDataSource();
|
||||
if(initializerDataSource != null) {
|
||||
if (initializerDataSource != null) {
|
||||
taskRepositoryInitializer.setDataSource(initializerDataSource);
|
||||
}
|
||||
|
||||
@@ -116,7 +119,7 @@ public class SimpleTaskAutoConfiguration {
|
||||
*/
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
if (initialized) {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,7 +131,7 @@ public class SimpleTaskAutoConfiguration {
|
||||
this.taskRepository = taskConfigurer.getTaskRepository();
|
||||
this.platformTransactionManager = taskConfigurer.getTransactionManager();
|
||||
this.taskExplorer = taskConfigurer.getTaskExplorer();
|
||||
initialized = true;
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
private TaskConfigurer getDefaultConfigurer() {
|
||||
@@ -138,36 +141,44 @@ public class SimpleTaskAutoConfiguration {
|
||||
|
||||
if (configurers < 1) {
|
||||
TaskConfigurer taskConfigurer;
|
||||
if(!CollectionUtils.isEmpty(this.dataSources) && this.dataSources.size() == 1) {
|
||||
if (!CollectionUtils.isEmpty(this.dataSources)
|
||||
&& this.dataSources.size() == 1) {
|
||||
taskConfigurer = new DefaultTaskConfigurer(
|
||||
this.dataSources.iterator().next(),
|
||||
taskProperties.getTablePrefix(), context);
|
||||
this.taskProperties.getTablePrefix(), this.context);
|
||||
}
|
||||
else {
|
||||
taskConfigurer = new DefaultTaskConfigurer(taskProperties.getTablePrefix());
|
||||
taskConfigurer = new DefaultTaskConfigurer(
|
||||
this.taskProperties.getTablePrefix());
|
||||
}
|
||||
this.context.getBeanFactory().registerSingleton("taskConfigurer", taskConfigurer);
|
||||
this.context.getBeanFactory().registerSingleton("taskConfigurer",
|
||||
taskConfigurer);
|
||||
return taskConfigurer;
|
||||
}
|
||||
else {
|
||||
if(configurers == 1) {
|
||||
if (configurers == 1) {
|
||||
return this.context.getBean(TaskConfigurer.class);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Expected one TaskConfigurer but found " + configurers);
|
||||
throw new IllegalStateException(
|
||||
"Expected one TaskConfigurer but found " + configurers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyEnvironment() {
|
||||
int configurers = this.context.getBeanNamesForType(TaskConfigurer.class).length;
|
||||
// retrieve the count of dataSources (without instantiating them) excluding DataSource proxy beans
|
||||
long dataSources = Arrays.stream(this.context.getBeanNamesForType(DataSource.class))
|
||||
// retrieve the count of dataSources (without instantiating them) excluding
|
||||
// DataSource proxy beans
|
||||
long dataSources = Arrays
|
||||
.stream(this.context.getBeanNamesForType(DataSource.class))
|
||||
.filter((name -> !ScopedProxyUtils.isScopedTarget(name))).count();
|
||||
|
||||
if(configurers == 0 && dataSources > 1) {
|
||||
throw new IllegalStateException("To use the default TaskConfigurer the context must contain no more than" +
|
||||
" one DataSource, found " + dataSources);
|
||||
if (configurers == 0 && dataSources > 1) {
|
||||
throw new IllegalStateException(
|
||||
"To use the default TaskConfigurer the context must contain no more than"
|
||||
+ " one DataSource, found " + dataSources);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.configuration;
|
||||
@@ -39,10 +39,10 @@ import org.springframework.integration.support.leader.LockRegistryLeaderInitiato
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
|
||||
/**
|
||||
* When spring.cloud.task.single-instance-enabled is set to true this listener will create a lock for the task
|
||||
* based on the spring.cloud.task.name. If a lock already exists this Listener will throw
|
||||
* a TaskExecutionException. If this listener is added manually, then it should
|
||||
* be added as the first listener in the chain.
|
||||
* When spring.cloud.task.single-instance-enabled is set to true this listener will create
|
||||
* a lock for the task based on the spring.cloud.task.name. If a lock already exists this
|
||||
* Listener will throw a TaskExecutionException. If this listener is added manually, then
|
||||
* it should be added as the first listener in the chain.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @since 2.0.0
|
||||
@@ -68,19 +68,18 @@ public class SingleInstanceTaskListener implements ApplicationListener<Applicati
|
||||
private TaskProperties taskProperties;
|
||||
|
||||
public SingleInstanceTaskListener(LockRegistry lockRegistry,
|
||||
TaskNameResolver taskNameResolver,
|
||||
TaskProperties taskProperties,
|
||||
TaskNameResolver taskNameResolver, TaskProperties taskProperties,
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.lockRegistry = lockRegistry;
|
||||
this.taskNameResolver = taskNameResolver;
|
||||
this.taskProperties = taskProperties;
|
||||
this.lockRegistryLeaderInitiator = new LockRegistryLeaderInitiator(this.lockRegistry);
|
||||
this.lockRegistryLeaderInitiator = new LockRegistryLeaderInitiator(
|
||||
this.lockRegistry);
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
public SingleInstanceTaskListener(DataSource dataSource,
|
||||
TaskNameResolver taskNameResolver,
|
||||
TaskProperties taskProperties,
|
||||
TaskNameResolver taskNameResolver, TaskProperties taskProperties,
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.taskNameResolver = taskNameResolver;
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
@@ -90,14 +89,15 @@ public class SingleInstanceTaskListener implements ApplicationListener<Applicati
|
||||
|
||||
@BeforeTask
|
||||
public void lockTask(TaskExecution taskExecution) {
|
||||
if(this.lockRegistry == null ) {
|
||||
if (this.lockRegistry == null) {
|
||||
this.lockRegistry = getDefaultLockRegistry(taskExecution.getExecutionId());
|
||||
}
|
||||
this.lockRegistryLeaderInitiator = new LockRegistryLeaderInitiator(
|
||||
this.lockRegistry,
|
||||
new DefaultCandidate(String.valueOf(taskExecution.getExecutionId()),
|
||||
taskNameResolver.getTaskName()));
|
||||
this.lockRegistryLeaderInitiator.setApplicationEventPublisher(this.applicationEventPublisher);
|
||||
this.taskNameResolver.getTaskName()));
|
||||
this.lockRegistryLeaderInitiator
|
||||
.setApplicationEventPublisher(this.applicationEventPublisher);
|
||||
this.lockRegistryLeaderInitiator.setPublishFailedEvents(true);
|
||||
this.lockRegistryLeaderInitiator.start();
|
||||
while (!this.lockReady) {
|
||||
@@ -115,7 +115,8 @@ public class SingleInstanceTaskListener implements ApplicationListener<Applicati
|
||||
this.lockRegistryLeaderInitiator.destroy();
|
||||
}
|
||||
catch (Exception exception) {
|
||||
throw new TaskExecutionException("Failed to destroy lock.", exception);
|
||||
throw new TaskExecutionException("Failed to destroy lock.",
|
||||
exception);
|
||||
}
|
||||
throw new TaskExecutionException(errorMessage);
|
||||
}
|
||||
@@ -128,7 +129,8 @@ public class SingleInstanceTaskListener implements ApplicationListener<Applicati
|
||||
}
|
||||
|
||||
@FailedTask
|
||||
public void unlockTaskOnError(TaskExecution taskExecution, Throwable throwable) throws Exception {
|
||||
public void unlockTaskOnError(TaskExecution taskExecution, Throwable throwable)
|
||||
throws Exception {
|
||||
this.lockRegistryLeaderInitiator.destroy();
|
||||
}
|
||||
|
||||
@@ -142,13 +144,13 @@ public class SingleInstanceTaskListener implements ApplicationListener<Applicati
|
||||
}
|
||||
}
|
||||
|
||||
private LockRegistry getDefaultLockRegistry( long executionId) {
|
||||
DefaultLockRepository lockRepository =
|
||||
new DefaultLockRepository(this.dataSource, String.valueOf(
|
||||
executionId));
|
||||
private LockRegistry getDefaultLockRegistry(long executionId) {
|
||||
DefaultLockRepository lockRepository = new DefaultLockRepository(this.dataSource,
|
||||
String.valueOf(executionId));
|
||||
lockRepository.setPrefix(this.taskProperties.getTablePrefix());
|
||||
lockRepository.setTimeToLive(this.taskProperties.getSingleInstanceLockTtl());
|
||||
lockRepository.afterPropertiesSet();
|
||||
return new JdbcLockRegistry(lockRepository);
|
||||
return new JdbcLockRegistry(lockRepository);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.configuration;
|
||||
@@ -47,17 +47,15 @@ public class SingleTaskConfiguration {
|
||||
@Autowired
|
||||
private TaskConfigurer taskConfigurer;
|
||||
|
||||
|
||||
@Bean
|
||||
public SingleInstanceTaskListener taskListener(TaskNameResolver resolver) {
|
||||
if (taskConfigurer.getTaskDataSource() == null) {
|
||||
return new SingleInstanceTaskListener(new PassThruLockRegistry(),
|
||||
resolver, this.taskProperties, this.applicationEventPublisher);
|
||||
if (this.taskConfigurer.getTaskDataSource() == null) {
|
||||
return new SingleInstanceTaskListener(new PassThruLockRegistry(), resolver,
|
||||
this.taskProperties, this.applicationEventPublisher);
|
||||
}
|
||||
|
||||
return new SingleInstanceTaskListener(taskConfigurer.getTaskDataSource(),
|
||||
resolver,
|
||||
this.taskProperties,
|
||||
this.applicationEventPublisher);
|
||||
return new SingleInstanceTaskListener(this.taskConfigurer.getTaskDataSource(),
|
||||
resolver, this.taskProperties, this.applicationEventPublisher);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -23,10 +23,9 @@ import org.springframework.cloud.task.repository.TaskRepository;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Provides a strategy interface for providing configuration
|
||||
* customization to the task system. Users should not directly use getter methods
|
||||
* from a <code>TaskConfigurer</code> directly unless they are using it to supply the implementations
|
||||
* for Spring Beans.
|
||||
* Provides a strategy interface for providing configuration customization to the task
|
||||
* system. Users should not directly use getter methods from a <code>TaskConfigurer</code>
|
||||
* directly unless they are using it to supply the implementations for Spring Beans.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@@ -34,7 +33,6 @@ public interface TaskConfigurer {
|
||||
|
||||
/**
|
||||
* Create a {@link TaskRepository} for the Task.
|
||||
*
|
||||
* @return A TaskRepository
|
||||
*/
|
||||
TaskRepository getTaskRepository();
|
||||
@@ -42,23 +40,22 @@ public interface TaskConfigurer {
|
||||
/**
|
||||
* Create a {@link PlatformTransactionManager} for use with the
|
||||
* <code>TaskRepository</code>.
|
||||
*
|
||||
* @return A <code>PlatformTransactionManager</code>
|
||||
*/
|
||||
PlatformTransactionManager getTransactionManager();
|
||||
|
||||
/**
|
||||
* Create a {@link TaskExplorer} for the task.
|
||||
*
|
||||
* @return a <code>TaskExplorer</code>
|
||||
*/
|
||||
TaskExplorer getTaskExplorer();
|
||||
|
||||
/**
|
||||
* Retrieves the {@link DataSource} that will be used for task operations. If a
|
||||
* DataSource is not being used for the implemented TaskConfigurer this
|
||||
* method will return null.
|
||||
* Retrieves the {@link DataSource} that will be used for task operations. If a
|
||||
* DataSource is not being used for the implemented TaskConfigurer this method will
|
||||
* return null.
|
||||
* @return {@link DataSource} that will be used for task operations.
|
||||
*/
|
||||
DataSource getTaskDataSource();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.configuration;
|
||||
@@ -43,7 +43,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
public class TaskLifecycleConfiguration {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(TaskLifecycleConfiguration.class);
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(TaskLifecycleConfiguration.class);
|
||||
|
||||
private TaskProperties taskProperties;
|
||||
|
||||
@@ -63,10 +64,8 @@ public class TaskLifecycleConfiguration {
|
||||
|
||||
@Autowired
|
||||
public TaskLifecycleConfiguration(TaskProperties taskProperties,
|
||||
ConfigurableApplicationContext context,
|
||||
TaskRepository taskRepository,
|
||||
TaskExplorer taskExplorer,
|
||||
TaskNameResolver taskNameResolver,
|
||||
ConfigurableApplicationContext context, TaskRepository taskRepository,
|
||||
TaskExplorer taskExplorer, TaskNameResolver taskNameResolver,
|
||||
ObjectProvider<ApplicationArguments> applicationArguments) {
|
||||
|
||||
this.taskProperties = taskProperties;
|
||||
@@ -88,15 +87,13 @@ public class TaskLifecycleConfiguration {
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
if (!this.initialized) {
|
||||
this.taskLifecycleListener =
|
||||
new TaskLifecycleListener(this.taskRepository,
|
||||
this.taskNameResolver,
|
||||
this.applicationArguments,
|
||||
this.taskExplorer,
|
||||
this.taskProperties,
|
||||
new TaskListenerExecutorObjectFactory(context));
|
||||
this.taskLifecycleListener = new TaskLifecycleListener(this.taskRepository,
|
||||
this.taskNameResolver, this.applicationArguments, this.taskExplorer,
|
||||
this.taskProperties,
|
||||
new TaskListenerExecutorObjectFactory(this.context));
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.configuration;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -32,11 +31,14 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "spring.cloud.task")
|
||||
public class TaskProperties {
|
||||
|
||||
/**
|
||||
* Default table prefix for Spring Cloud Task.
|
||||
*/
|
||||
public static final String DEFAULT_TABLE_PREFIX = "TASK_";
|
||||
|
||||
private static final int DEFAULT_CHECK_INTERVAL = 500;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskProperties.class);
|
||||
|
||||
public static final String DEFAULT_TABLE_PREFIX = "TASK_";
|
||||
|
||||
/**
|
||||
* An id that can be associated with a task.
|
||||
@@ -49,8 +51,8 @@ public class TaskProperties {
|
||||
private Long executionid;
|
||||
|
||||
/**
|
||||
* The id of the parent task execution id that launched this task execution.
|
||||
* Defaults to null if task execution had no parent.
|
||||
* The id of the parent task execution id that launched this task execution. Defaults
|
||||
* to null if task execution had no parent.
|
||||
*/
|
||||
private Long parentExecutionId;
|
||||
|
||||
@@ -60,35 +62,34 @@ public class TaskProperties {
|
||||
private String tablePrefix = DEFAULT_TABLE_PREFIX;
|
||||
|
||||
/**
|
||||
* When set to true the context is closed at the end of the task. Else
|
||||
* the context remains open.
|
||||
* When set to true the context is closed at the end of the task. Else the context
|
||||
* remains open.
|
||||
*/
|
||||
private Boolean closecontextEnabled = false;
|
||||
|
||||
/**
|
||||
* When set to true it
|
||||
* will check to see if a task execution with the same task name is already
|
||||
* running. If a task is still running then it will throw a
|
||||
* {@link org.springframework.cloud.task.listener.TaskExecutionException}.
|
||||
* When task execution ends the lock is released.
|
||||
* When set to true it will check to see if a task execution with the same task name
|
||||
* is already running. If a task is still running then it will throw a
|
||||
* {@link org.springframework.cloud.task.listener.TaskExecutionException}. When task
|
||||
* execution ends the lock is released.
|
||||
*/
|
||||
private boolean singleInstanceEnabled = false;
|
||||
|
||||
/**
|
||||
* Declares the maximum amount of time (in millis) that a task execution can
|
||||
* hold a lock to prevent another task from executing with a specific task
|
||||
* name when the single-instance-enabled is set to true. Default time is: Integer.MAX_VALUE.
|
||||
* Declares the maximum amount of time (in millis) that a task execution can hold a
|
||||
* lock to prevent another task from executing with a specific task name when the
|
||||
* single-instance-enabled is set to true. Default time is: Integer.MAX_VALUE.
|
||||
*/
|
||||
private int singleInstanceLockTtl = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Declares the time (in millis) that a task execution will wait between
|
||||
* checks. Default time is: 500 millis.
|
||||
* Declares the time (in millis) that a task execution will wait between checks.
|
||||
* Default time is: 500 millis.
|
||||
*/
|
||||
private int singleInstanceLockCheckInterval = DEFAULT_CHECK_INTERVAL;
|
||||
|
||||
public String getExternalExecutionId() {
|
||||
return externalExecutionId;
|
||||
return this.externalExecutionId;
|
||||
}
|
||||
|
||||
public void setExternalExecutionId(String externalExecutionId) {
|
||||
@@ -96,7 +97,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public Long getExecutionid() {
|
||||
return executionid;
|
||||
return this.executionid;
|
||||
}
|
||||
|
||||
public void setExecutionid(Long executionid) {
|
||||
@@ -104,7 +105,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public Boolean getClosecontextEnabled() {
|
||||
return closecontextEnabled;
|
||||
return this.closecontextEnabled;
|
||||
}
|
||||
|
||||
public void setClosecontextEnabled(Boolean closecontextEnabled) {
|
||||
@@ -112,7 +113,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public String getTablePrefix() {
|
||||
return tablePrefix;
|
||||
return this.tablePrefix;
|
||||
}
|
||||
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
@@ -120,7 +121,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public Long getParentExecutionId() {
|
||||
return parentExecutionId;
|
||||
return this.parentExecutionId;
|
||||
}
|
||||
|
||||
public void setParentExecutionId(Long parentExecutionId) {
|
||||
@@ -128,7 +129,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public boolean getSingleInstanceEnabled() {
|
||||
return singleInstanceEnabled;
|
||||
return this.singleInstanceEnabled;
|
||||
}
|
||||
|
||||
public void setSingleInstanceEnabled(boolean singleInstanceEnabled) {
|
||||
@@ -136,7 +137,7 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public int getSingleInstanceLockTtl() {
|
||||
return singleInstanceLockTtl;
|
||||
return this.singleInstanceLockTtl;
|
||||
}
|
||||
|
||||
public void setSingleInstanceLockTtl(int singleInstanceLockTtl) {
|
||||
@@ -144,10 +145,11 @@ public class TaskProperties {
|
||||
}
|
||||
|
||||
public int getSingleInstanceLockCheckInterval() {
|
||||
return singleInstanceLockCheckInterval;
|
||||
return this.singleInstanceLockCheckInterval;
|
||||
}
|
||||
|
||||
public void setSingleInstanceLockCheckInterval(int singleInstanceLockCheckInterval) {
|
||||
this.singleInstanceLockCheckInterval = singleInstanceLockCheckInterval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces for configuring Spring Cloud Task and a default implementations.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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,15 +18,16 @@ package org.springframework.cloud.task.listener;
|
||||
|
||||
/**
|
||||
* Base Exception for any Task issues.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class TaskException extends RuntimeException {
|
||||
|
||||
public TaskException(String message, Throwable e){
|
||||
public TaskException(String message, Throwable e) {
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
public TaskException(String message){
|
||||
public TaskException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -23,11 +23,12 @@ package org.springframework.cloud.task.listener;
|
||||
*/
|
||||
public class TaskExecutionException extends TaskException {
|
||||
|
||||
public TaskExecutionException(String message){
|
||||
public TaskExecutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TaskExecutionException(String message, Throwable throwable){
|
||||
public TaskExecutionException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -21,29 +21,32 @@ import org.springframework.cloud.task.repository.TaskRepository;
|
||||
|
||||
/**
|
||||
* The listener interface for receiving task execution events.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public interface TaskExecutionListener {
|
||||
|
||||
/**
|
||||
* Invoked after the {@link TaskExecution} has been stored in the {@link TaskRepository}.
|
||||
* Invoked after the {@link TaskExecution} has been stored in the
|
||||
* {@link TaskRepository}.
|
||||
* @param taskExecution instance containing the information about the current task.
|
||||
*/
|
||||
void onTaskStartup(TaskExecution taskExecution);
|
||||
|
||||
/**
|
||||
* Invoked before the {@link TaskExecution} has been updated in the {@link TaskRepository}
|
||||
* upon task end.
|
||||
* Invoked before the {@link TaskExecution} has been updated in the
|
||||
* {@link TaskRepository} upon task end.
|
||||
* @param taskExecution instance containing the information about the current task.
|
||||
*/
|
||||
void onTaskEnd(TaskExecution taskExecution);
|
||||
|
||||
/**
|
||||
* Invoked if an uncaught exception occurs during a task execution. This invocation
|
||||
* will occur before the {@link TaskExecution} has been updated in the {@link TaskRepository}
|
||||
* and before the onTaskEnd is called.
|
||||
* Invoked if an uncaught exception occurs during a task execution. This invocation
|
||||
* will occur before the {@link TaskExecution} has been updated in the
|
||||
* {@link TaskRepository} and before the onTaskEnd is called.
|
||||
* @param taskExecution instance containing the information about the current task.
|
||||
* @param throwable the uncaught exception that was thrown during task execution.
|
||||
*/
|
||||
void onTaskFailed(TaskExecution taskExecution, Throwable throwable);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.listener;
|
||||
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.cloud.task.repository.TaskExecution;
|
||||
* @since 1.2
|
||||
*/
|
||||
public class TaskExecutionListenerSupport implements TaskExecutionListener {
|
||||
|
||||
@Override
|
||||
public void onTaskStartup(TaskExecution taskExecution) {
|
||||
|
||||
@@ -39,4 +41,5 @@ public class TaskExecutionListenerSupport implements TaskExecutionListener {
|
||||
public void onTaskFailed(TaskExecution taskExecution, Throwable throwable) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.listener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -49,33 +50,42 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Monitors the lifecycle of a task. This listener will record both the start and end of
|
||||
* a task in the registered {@link TaskRepository}.
|
||||
* Monitors the lifecycle of a task. This listener will record both the start and end of a
|
||||
* task in the registered {@link TaskRepository}.
|
||||
*
|
||||
* The following events are used to identify the start and end of a task:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link SmartLifecycle#start()} - Used to identify the start of a task. A task
|
||||
* is expected to contain a single application context.</li>
|
||||
* <li>{@link ApplicationReadyEvent} - Used to identify the successful end of a task.</li>
|
||||
* <li>{@link ApplicationFailedEvent} - Used to identify the failure of a task.</li>
|
||||
* <li>{@link SmartLifecycle#stop()} - Used to identify the end of a task,
|
||||
* if the {@link ApplicationReadyEvent} or {@link ApplicationFailedEvent}
|
||||
* is not emitted. This can occur if an error occurs while executing a BeforeTask.
|
||||
* </li>
|
||||
* <li>{@link SmartLifecycle#start()} - Used to identify the start of a task. A task is
|
||||
* expected to contain a single application context.</li>
|
||||
* <li>{@link ApplicationReadyEvent} - Used to identify the successful end of a task.</li>
|
||||
* <li>{@link ApplicationFailedEvent} - Used to identify the failure of a task.</li>
|
||||
* <li>{@link SmartLifecycle#stop()} - Used to identify the end of a task, if the
|
||||
* {@link ApplicationReadyEvent} or {@link ApplicationFailedEvent} is not emitted. This
|
||||
* can occur if an error occurs while executing a BeforeTask.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <b>Note:</b> By default, the context will close at the completion of the task unless other non-daemon
|
||||
* threads keep it running. Programatic closing of the context can be configured via the
|
||||
* property <code>spring.cloud.task.closecontext.enabled</code> (defaults to false).
|
||||
* If the <code>spring.cloud.task.closecontext.enabled</code> is set to true,
|
||||
* then the context will be closed upon task completion regardless if non-daemon threads are still running.
|
||||
* Also if the context did not start, the FailedTask and TaskEnd may not have all the dependencies met.
|
||||
* <b>Note:</b> By default, the context will close at the completion of the task unless
|
||||
* other non-daemon threads keep it running. Programatic closing of the context can be
|
||||
* configured via the property <code>spring.cloud.task.closecontext.enabled</code>
|
||||
* (defaults to false). If the <code>spring.cloud.task.closecontext.enabled</code> is set
|
||||
* to true, then the context will be closed upon task completion regardless if non-daemon
|
||||
* threads are still running. Also if the context did not start, the FailedTask and
|
||||
* TaskEnd may not have all the dependencies met.
|
||||
*
|
||||
* @author Michael Minella
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class TaskLifecycleListener implements ApplicationListener<ApplicationEvent>, SmartLifecycle, DisposableBean {
|
||||
public class TaskLifecycleListener
|
||||
implements ApplicationListener<ApplicationEvent>, SmartLifecycle, DisposableBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskLifecycleListener.class);
|
||||
|
||||
private final TaskRepository taskRepository;
|
||||
|
||||
private final TaskExplorer taskExplorer;
|
||||
|
||||
private final TaskListenerExecutorObjectFactory taskListenerExecutorObjectFactory;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableApplicationContext context;
|
||||
@@ -85,14 +95,6 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
|
||||
private List<TaskExecutionListener> taskExecutionListeners;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskLifecycleListener.class);
|
||||
|
||||
private final TaskRepository taskRepository;
|
||||
|
||||
private final TaskExplorer taskExplorer;
|
||||
|
||||
private final TaskListenerExecutorObjectFactory taskListenerExecutorObjectFactory;
|
||||
|
||||
private TaskExecution taskExecution;
|
||||
|
||||
private TaskProperties taskProperties;
|
||||
@@ -115,22 +117,25 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
|
||||
/**
|
||||
* @param taskRepository {@link TaskRepository} to record executions.
|
||||
* @param taskNameResolver {@link TaskNameResolver} used to determine task name for task execution.
|
||||
* @param applicationArguments {@link ApplicationArguments} to be used for task execution.
|
||||
* @param taskNameResolver {@link TaskNameResolver} used to determine task name for
|
||||
* task execution.
|
||||
* @param applicationArguments {@link ApplicationArguments} to be used for task
|
||||
* execution.
|
||||
* @param taskExplorer {@link TaskExplorer} to be used for task execution.
|
||||
* @param taskProperties {@link TaskProperties} to be used for the task execution.
|
||||
* @param taskListenerExecutorObjectFactory {@link TaskListenerExecutorObjectFactory} to initialize TaskListenerExecutor for a task
|
||||
* @param taskListenerExecutorObjectFactory {@link TaskListenerExecutorObjectFactory}
|
||||
* to initialize TaskListenerExecutor for a task
|
||||
*/
|
||||
public TaskLifecycleListener(TaskRepository taskRepository,
|
||||
TaskNameResolver taskNameResolver,
|
||||
ApplicationArguments applicationArguments, TaskExplorer taskExplorer,
|
||||
TaskProperties taskProperties,
|
||||
TaskNameResolver taskNameResolver, ApplicationArguments applicationArguments,
|
||||
TaskExplorer taskExplorer, TaskProperties taskProperties,
|
||||
TaskListenerExecutorObjectFactory taskListenerExecutorObjectFactory) {
|
||||
Assert.notNull(taskRepository, "A taskRepository is required");
|
||||
Assert.notNull(taskNameResolver, "A taskNameResolver is required");
|
||||
Assert.notNull(taskExplorer, "A taskExplorer is required");
|
||||
Assert.notNull(taskProperties, "TaskProperties is required");
|
||||
Assert.notNull(taskListenerExecutorObjectFactory, "A TaskListenerExecutorObjectFactory is required");
|
||||
Assert.notNull(taskListenerExecutorObjectFactory,
|
||||
"A TaskListenerExecutorObjectFactory is required");
|
||||
|
||||
this.taskRepository = taskRepository;
|
||||
this.taskNameResolver = taskNameResolver;
|
||||
@@ -141,25 +146,25 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilizes {@link ApplicationEvent}s to determine the end and failure of a
|
||||
* task. Specifically:
|
||||
* Utilizes {@link ApplicationEvent}s to determine the end and failure of a task.
|
||||
* Specifically:
|
||||
* <ul>
|
||||
* <li>{@link ApplicationReadyEvent} - Successful end of a task</li>
|
||||
* <li>{@link ApplicationFailedEvent} - Failure of a task</li>
|
||||
* <li>{@link ApplicationReadyEvent} - Successful end of a task</li>
|
||||
* <li>{@link ApplicationFailedEvent} - Failure of a task</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param applicationEvent The application being listened for.
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent applicationEvent) {
|
||||
if(applicationEvent instanceof ApplicationFailedEvent) {
|
||||
this.applicationFailedException = ((ApplicationFailedEvent) applicationEvent).getException();
|
||||
if (applicationEvent instanceof ApplicationFailedEvent) {
|
||||
this.applicationFailedException = ((ApplicationFailedEvent) applicationEvent)
|
||||
.getException();
|
||||
doTaskEnd();
|
||||
}
|
||||
else if(applicationEvent instanceof ExitCodeEvent){
|
||||
else if (applicationEvent instanceof ExitCodeEvent) {
|
||||
this.exitCodeEvent = (ExitCodeEvent) applicationEvent;
|
||||
}
|
||||
else if(applicationEvent instanceof ApplicationReadyEvent) {
|
||||
else if (applicationEvent instanceof ApplicationReadyEvent) {
|
||||
doTaskEnd();
|
||||
}
|
||||
}
|
||||
@@ -174,37 +179,41 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
}
|
||||
|
||||
private void doTaskEnd() {
|
||||
if((this.listenerFailed || this.started) && !this.finished) {
|
||||
if ((this.listenerFailed || this.started) && !this.finished) {
|
||||
this.taskExecution.setEndTime(new Date());
|
||||
|
||||
if(this.applicationFailedException != null) {
|
||||
this.taskExecution.setErrorMessage(stackTraceToString(this.applicationFailedException));
|
||||
if (this.applicationFailedException != null) {
|
||||
this.taskExecution.setErrorMessage(
|
||||
stackTraceToString(this.applicationFailedException));
|
||||
}
|
||||
|
||||
this.taskExecution.setExitCode(calcExitStatus());
|
||||
if (this.applicationFailedException != null) {
|
||||
setExitMessage(invokeOnTaskError(this.taskExecution, this.applicationFailedException));
|
||||
setExitMessage(invokeOnTaskError(this.taskExecution,
|
||||
this.applicationFailedException));
|
||||
}
|
||||
|
||||
setExitMessage(invokeOnTaskEnd(this.taskExecution));
|
||||
this.taskRepository.completeTaskExecution(this.taskExecution.getExecutionId(), this.taskExecution.getExitCode(),
|
||||
this.taskExecution.getEndTime(), this.taskExecution.getExitMessage(), this.taskExecution.getErrorMessage());
|
||||
this.taskRepository.completeTaskExecution(this.taskExecution.getExecutionId(),
|
||||
this.taskExecution.getExitCode(), this.taskExecution.getEndTime(),
|
||||
this.taskExecution.getExitMessage(),
|
||||
this.taskExecution.getErrorMessage());
|
||||
|
||||
this.finished = true;
|
||||
|
||||
if(this.taskProperties.getClosecontextEnabled() && this.context.isActive()) {
|
||||
if (this.taskProperties.getClosecontextEnabled() && this.context.isActive()) {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
}
|
||||
else if(!this.started){
|
||||
logger.error("An event to end a task has been received for a task that has " +
|
||||
"not yet started.");
|
||||
else if (!this.started) {
|
||||
logger.error("An event to end a task has been received for a task that has "
|
||||
+ "not yet started.");
|
||||
}
|
||||
}
|
||||
|
||||
private void setExitMessage(TaskExecution taskExecutionParam) {
|
||||
if(taskExecutionParam.getExitMessage() != null) {
|
||||
if (taskExecutionParam.getExitMessage() != null) {
|
||||
this.taskExecution.setExitMessage(taskExecutionParam.getExitMessage());
|
||||
}
|
||||
}
|
||||
@@ -218,10 +227,12 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
Throwable exception = this.listenerException;
|
||||
if (exception instanceof TaskExecutionException) {
|
||||
TaskExecutionException taskExecutionException = (TaskExecutionException) exception;
|
||||
if (taskExecutionException.getCause() instanceof InvocationTargetException) {
|
||||
if (taskExecutionException
|
||||
.getCause() instanceof InvocationTargetException) {
|
||||
InvocationTargetException invocationTargetException = (InvocationTargetException) taskExecutionException
|
||||
.getCause();
|
||||
if(invocationTargetException != null && invocationTargetException.getTargetException() != null) {
|
||||
if (invocationTargetException != null
|
||||
&& invocationTargetException.getTargetException() != null) {
|
||||
exception = invocationTargetException.getTargetException();
|
||||
}
|
||||
}
|
||||
@@ -240,25 +251,32 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
|
||||
private void doTaskStart() {
|
||||
try {
|
||||
if(!this.started) {
|
||||
if (!this.started) {
|
||||
this.taskExecutionListeners = new ArrayList<>();
|
||||
this.taskListenerExecutorObjectFactory.getObject();
|
||||
if(!CollectionUtils.isEmpty(this.taskExecutionListenersFromContext)) {
|
||||
this.taskExecutionListeners.addAll(this.taskExecutionListenersFromContext);
|
||||
if (!CollectionUtils.isEmpty(this.taskExecutionListenersFromContext)) {
|
||||
this.taskExecutionListeners
|
||||
.addAll(this.taskExecutionListenersFromContext);
|
||||
}
|
||||
this.taskExecutionListeners.add(this.taskListenerExecutorObjectFactory.getObject());
|
||||
this.taskExecutionListeners
|
||||
.add(this.taskListenerExecutorObjectFactory.getObject());
|
||||
|
||||
List<String> args = new ArrayList<>(0);
|
||||
|
||||
if(this.applicationArguments != null) {
|
||||
if (this.applicationArguments != null) {
|
||||
args = Arrays.asList(this.applicationArguments.getSourceArgs());
|
||||
}
|
||||
if(this.taskProperties.getExecutionid() != null) {
|
||||
TaskExecution taskExecution = this.taskExplorer.getTaskExecution(this.taskProperties.getExecutionid());
|
||||
Assert.notNull(taskExecution, String.format("Invalid TaskExecution, ID %s not found", this.taskProperties.getExecutionid()));
|
||||
if (this.taskProperties.getExecutionid() != null) {
|
||||
TaskExecution taskExecution = this.taskExplorer
|
||||
.getTaskExecution(this.taskProperties.getExecutionid());
|
||||
Assert.notNull(taskExecution,
|
||||
String.format("Invalid TaskExecution, ID %s not found",
|
||||
this.taskProperties.getExecutionid()));
|
||||
Assert.isNull(taskExecution.getEndTime(), String.format(
|
||||
"Invalid TaskExecution, ID %s task is already complete", this.taskProperties.getExecutionid()));
|
||||
this.taskExecution = this.taskRepository.startTaskExecution(this.taskProperties.getExecutionid(),
|
||||
"Invalid TaskExecution, ID %s task is already complete",
|
||||
this.taskProperties.getExecutionid()));
|
||||
this.taskExecution = this.taskRepository.startTaskExecution(
|
||||
this.taskProperties.getExecutionid(),
|
||||
this.taskNameResolver.getTaskName(), new Date(), args,
|
||||
this.taskProperties.getExternalExecutionId(),
|
||||
this.taskProperties.getParentExecutionId());
|
||||
@@ -268,15 +286,18 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
taskExecution.setTaskName(this.taskNameResolver.getTaskName());
|
||||
taskExecution.setStartTime(new Date());
|
||||
taskExecution.setArguments(args);
|
||||
taskExecution.setExternalExecutionId(this.taskProperties.getExternalExecutionId());
|
||||
taskExecution.setParentExecutionId(this.taskProperties.getParentExecutionId());
|
||||
this.taskExecution = this.taskRepository.createTaskExecution(
|
||||
taskExecution);
|
||||
taskExecution.setExternalExecutionId(
|
||||
this.taskProperties.getExternalExecutionId());
|
||||
taskExecution.setParentExecutionId(
|
||||
this.taskProperties.getParentExecutionId());
|
||||
this.taskExecution = this.taskRepository
|
||||
.createTaskExecution(taskExecution);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.error("Multiple start events have been received. The first one was " +
|
||||
"recorded.");
|
||||
logger.error(
|
||||
"Multiple start events have been received. The first one was "
|
||||
+ "recorded.");
|
||||
}
|
||||
|
||||
setExitMessage(invokeOnTaskStartup(this.taskExecution));
|
||||
@@ -289,9 +310,10 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
}
|
||||
}
|
||||
|
||||
private TaskExecution invokeOnTaskStartup(TaskExecution taskExecution){
|
||||
private TaskExecution invokeOnTaskStartup(TaskExecution taskExecution) {
|
||||
TaskExecution listenerTaskExecution = getTaskExecutionCopy(taskExecution);
|
||||
List<TaskExecutionListener> startupListenerList = new ArrayList<>(this.taskExecutionListeners);
|
||||
List<TaskExecutionListener> startupListenerList = new ArrayList<>(
|
||||
this.taskExecutionListeners);
|
||||
if (!CollectionUtils.isEmpty(startupListenerList)) {
|
||||
try {
|
||||
Collections.reverse(startupListenerList);
|
||||
@@ -310,7 +332,7 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
return listenerTaskExecution;
|
||||
}
|
||||
|
||||
private TaskExecution invokeOnTaskEnd(TaskExecution taskExecution){
|
||||
private TaskExecution invokeOnTaskEnd(TaskExecution taskExecution) {
|
||||
TaskExecution listenerTaskExecution = getTaskExecutionCopy(taskExecution);
|
||||
if (this.taskExecutionListeners != null) {
|
||||
try {
|
||||
@@ -321,7 +343,8 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
catch (Throwable listenerException) {
|
||||
String errorMessage = stackTraceToString(listenerException);
|
||||
if (StringUtils.hasText(listenerTaskExecution.getErrorMessage())) {
|
||||
errorMessage = String.format("%s :Task also threw this Exception: %s", errorMessage, listenerTaskExecution.getErrorMessage());
|
||||
errorMessage = String.format("%s :Task also threw this Exception: %s",
|
||||
errorMessage, listenerTaskExecution.getErrorMessage());
|
||||
}
|
||||
logger.error(errorMessage);
|
||||
listenerTaskExecution.setErrorMessage(errorMessage);
|
||||
@@ -331,7 +354,8 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
return listenerTaskExecution;
|
||||
}
|
||||
|
||||
private TaskExecution invokeOnTaskError(TaskExecution taskExecution, Throwable throwable){
|
||||
private TaskExecution invokeOnTaskError(TaskExecution taskExecution,
|
||||
Throwable throwable) {
|
||||
TaskExecution listenerTaskExecution = getTaskExecutionCopy(taskExecution);
|
||||
if (this.taskExecutionListeners != null) {
|
||||
try {
|
||||
@@ -342,9 +366,9 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
catch (Throwable listenerException) {
|
||||
this.listenerFailed = true;
|
||||
String errorMessage;
|
||||
if(StringUtils.hasText(listenerTaskExecution.getErrorMessage())) {
|
||||
errorMessage = String.format("%s :While handling " +
|
||||
"this error: %s", listenerException.getMessage(),
|
||||
if (StringUtils.hasText(listenerTaskExecution.getErrorMessage())) {
|
||||
errorMessage = String.format("%s :While handling " + "this error: %s",
|
||||
listenerException.getMessage(),
|
||||
listenerTaskExecution.getErrorMessage());
|
||||
}
|
||||
else {
|
||||
@@ -359,14 +383,14 @@ public class TaskLifecycleListener implements ApplicationListener<ApplicationEve
|
||||
return listenerTaskExecution;
|
||||
}
|
||||
|
||||
private TaskExecution getTaskExecutionCopy(TaskExecution taskExecution){
|
||||
private TaskExecution getTaskExecutionCopy(TaskExecution taskExecution) {
|
||||
Date startTime = new Date(taskExecution.getStartTime().getTime());
|
||||
Date endTime = (taskExecution.getEndTime() == null) ?
|
||||
null : new Date(taskExecution.getEndTime().getTime());
|
||||
Date endTime = (taskExecution.getEndTime() == null) ? null
|
||||
: new Date(taskExecution.getEndTime().getTime());
|
||||
|
||||
return new TaskExecution(taskExecution.getExecutionId(),
|
||||
taskExecution.getExitCode(), taskExecution.getTaskName(), startTime,
|
||||
endTime,taskExecution.getExitMessage(),
|
||||
endTime, taskExecution.getExitMessage(),
|
||||
Collections.unmodifiableList(taskExecution.getArguments()),
|
||||
taskExecution.getErrorMessage(), taskExecution.getExternalExecutionId());
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.listener;
|
||||
@@ -47,12 +47,13 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
* @author Glenn Renfro
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExecutionListener> {
|
||||
public class TaskListenerExecutorObjectFactory
|
||||
implements ObjectFactory<TaskExecutionListener> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskListenerExecutor.class);
|
||||
|
||||
private final Set<Class<?>> nonAnnotatedClasses =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private final Set<Class<?>> nonAnnotatedClasses = Collections
|
||||
.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@@ -62,7 +63,7 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
|
||||
private Map<Method, Object> failedTaskInstances;
|
||||
|
||||
public TaskListenerExecutorObjectFactory(ConfigurableApplicationContext context){
|
||||
public TaskListenerExecutorObjectFactory(ConfigurableApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@@ -72,12 +73,13 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
this.afterTaskInstances = new HashMap<>();
|
||||
this.failedTaskInstances = new HashMap<>();
|
||||
initializeExecutor();
|
||||
return new TaskListenerExecutor(beforeTaskInstances, afterTaskInstances, failedTaskInstances);
|
||||
return new TaskListenerExecutor(this.beforeTaskInstances, this.afterTaskInstances,
|
||||
this.failedTaskInstances);
|
||||
}
|
||||
|
||||
private void initializeExecutor( ) {
|
||||
ConfigurableListableBeanFactory factory = context.getBeanFactory();
|
||||
for( String beanName : context.getBeanDefinitionNames()) {
|
||||
private void initializeExecutor() {
|
||||
ConfigurableListableBeanFactory factory = this.context.getBeanFactory();
|
||||
for (String beanName : this.context.getBeanDefinitionNames()) {
|
||||
|
||||
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
|
||||
Class<?> type = null;
|
||||
@@ -85,9 +87,11 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
type = AutoProxyUtils.determineTargetClass(factory, beanName);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
|
||||
// An unresolvable bean type, probably from a lazy bean - let's ignore
|
||||
// it.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
|
||||
logger.debug("Could not resolve target class for bean with name '"
|
||||
+ beanName + "'", ex);
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
@@ -99,7 +103,10 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
catch (RuntimeException ex) {
|
||||
// An invalid scoped proxy arrangement - let's ignore it.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
|
||||
logger.debug(
|
||||
"Could not resolve target bean for scoped proxy '"
|
||||
+ beanName + "'",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,8 +114,11 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
processBean(beanName, type);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw new BeanInitializationException("Failed to process @BeforeTask " +
|
||||
"annotation on bean with name '" + beanName + "'", ex);
|
||||
throw new BeanInitializationException(
|
||||
"Failed to process @BeforeTask "
|
||||
+ "annotation on bean with name '" + beanName
|
||||
+ "'",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,41 +126,49 @@ public class TaskListenerExecutorObjectFactory implements ObjectFactory<TaskExec
|
||||
|
||||
}
|
||||
|
||||
private void processBean(String beanName, final Class<?> type){
|
||||
private void processBean(String beanName, final Class<?> type) {
|
||||
if (!this.nonAnnotatedClasses.contains(type)) {
|
||||
Map<Method, BeforeTask> beforeTaskMethods =
|
||||
(new MethodGetter<BeforeTask>()).getMethods(type, BeforeTask.class);
|
||||
Map<Method, AfterTask> afterTaskMethods =
|
||||
(new MethodGetter<AfterTask>()).getMethods(type, AfterTask.class);
|
||||
Map<Method, FailedTask> failedTaskMethods =
|
||||
(new MethodGetter<FailedTask>()).getMethods(type, FailedTask.class);
|
||||
Map<Method, BeforeTask> beforeTaskMethods = (new MethodGetter<BeforeTask>())
|
||||
.getMethods(type, BeforeTask.class);
|
||||
Map<Method, AfterTask> afterTaskMethods = (new MethodGetter<AfterTask>())
|
||||
.getMethods(type, AfterTask.class);
|
||||
Map<Method, FailedTask> failedTaskMethods = (new MethodGetter<FailedTask>())
|
||||
.getMethods(type, FailedTask.class);
|
||||
|
||||
if (beforeTaskMethods.isEmpty() && afterTaskMethods.isEmpty()) {
|
||||
this.nonAnnotatedClasses.add(type);
|
||||
return;
|
||||
}
|
||||
if(!beforeTaskMethods.isEmpty()) {
|
||||
for(Method beforeTaskMethod : beforeTaskMethods.keySet()) {
|
||||
this.beforeTaskInstances.put(beforeTaskMethod, context.getBean(beanName));
|
||||
if (!beforeTaskMethods.isEmpty()) {
|
||||
for (Method beforeTaskMethod : beforeTaskMethods.keySet()) {
|
||||
this.beforeTaskInstances.put(beforeTaskMethod,
|
||||
this.context.getBean(beanName));
|
||||
}
|
||||
}
|
||||
if(!afterTaskMethods.isEmpty()){
|
||||
for(Method afterTaskMethod : afterTaskMethods.keySet()) {
|
||||
this.afterTaskInstances.put(afterTaskMethod, context.getBean(beanName));
|
||||
if (!afterTaskMethods.isEmpty()) {
|
||||
for (Method afterTaskMethod : afterTaskMethods.keySet()) {
|
||||
this.afterTaskInstances.put(afterTaskMethod,
|
||||
this.context.getBean(beanName));
|
||||
}
|
||||
}
|
||||
if(!failedTaskMethods.isEmpty()){
|
||||
for(Method failedTaskMethod : failedTaskMethods.keySet()) {
|
||||
this.failedTaskInstances.put(failedTaskMethod, context.getBean(beanName));
|
||||
if (!failedTaskMethods.isEmpty()) {
|
||||
for (Method failedTaskMethod : failedTaskMethods.keySet()) {
|
||||
this.failedTaskInstances.put(failedTaskMethod,
|
||||
this.context.getBean(beanName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MethodGetter<T extends Annotation> {
|
||||
public Map<Method, T> getMethods(final Class<?> type, final Class<T> annotationClass){
|
||||
|
||||
public Map<Method, T> getMethods(final Class<?> type,
|
||||
final Class<T> annotationClass) {
|
||||
return MethodIntrospector.selectMethods(type,
|
||||
(MethodIntrospector.MetadataLookup<T>) method -> AnnotationUtils.findAnnotation(method, annotationClass));
|
||||
(MethodIntrospector.MetadataLookup<T>) method -> AnnotationUtils
|
||||
.findAnnotation(method, annotationClass));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -27,22 +27,22 @@ import org.springframework.cloud.task.repository.TaskExecution;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link TaskExecutionListener#onTaskEnd(TaskExecution)}
|
||||
* {@link TaskExecutionListener#onTaskEnd(TaskExecution)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class MyListener {
|
||||
|
||||
* @AfterTask
|
||||
* public void doSomething(TaskExecution taskExecution) {
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface AfterTask {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -27,22 +27,22 @@ import org.springframework.cloud.task.repository.TaskExecution;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link TaskExecutionListener#onTaskStartup(TaskExecution)}
|
||||
* {@link TaskExecutionListener#onTaskStartup(TaskExecution)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class MyListener {
|
||||
|
||||
* @BeforeTask
|
||||
* public void doSomething(TaskExecution taskExecution) {
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface BeforeTask {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -27,22 +27,22 @@ import org.springframework.cloud.task.repository.TaskExecution;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link TaskExecutionListener#onTaskFailed(TaskExecution, Throwable)}
|
||||
* {@link TaskExecutionListener#onTaskFailed(TaskExecution, Throwable)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class MyListener {
|
||||
|
||||
* @FailedTask
|
||||
* public void doSomething(TaskExecution taskExecution, Throwable throwable) {
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface FailedTask {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -32,7 +32,7 @@ import org.springframework.cloud.task.repository.TaskExecution;
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class TaskListenerExecutor implements TaskExecutionListener{
|
||||
public class TaskListenerExecutor implements TaskExecutionListener {
|
||||
|
||||
private Map<Method, Object> beforeTaskInstances;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class TaskListenerExecutor implements TaskExecutionListener{
|
||||
|
||||
public TaskListenerExecutor(Map<Method, Object> beforeTaskInstances,
|
||||
Map<Method, Object> afterTaskInstances,
|
||||
Map<Method, Object> failedTaskInstances){
|
||||
Map<Method, Object> failedTaskInstances) {
|
||||
|
||||
this.beforeTaskInstances = beforeTaskInstances;
|
||||
this.afterTaskInstances = afterTaskInstances;
|
||||
@@ -50,66 +50,77 @@ public class TaskListenerExecutor implements TaskExecutionListener{
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all the methods that have been annotated with @BeforeTask.
|
||||
* Executes all the methods that have been annotated with @BeforeTask.
|
||||
* @param taskExecution associated with the event.
|
||||
*/
|
||||
@Override
|
||||
public void onTaskStartup(TaskExecution taskExecution) {
|
||||
executeTaskListener(taskExecution, beforeTaskInstances.keySet(), beforeTaskInstances);
|
||||
executeTaskListener(taskExecution, this.beforeTaskInstances.keySet(),
|
||||
this.beforeTaskInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all the methods that have been annotated with @AfterTask.
|
||||
* Executes all the methods that have been annotated with @AfterTask.
|
||||
* @param taskExecution associated with the event.
|
||||
*/
|
||||
@Override
|
||||
public void onTaskEnd(TaskExecution taskExecution) {
|
||||
executeTaskListener(taskExecution, afterTaskInstances.keySet(), afterTaskInstances);
|
||||
executeTaskListener(taskExecution, this.afterTaskInstances.keySet(),
|
||||
this.afterTaskInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all the methods that have been annotated with @FailedTask.
|
||||
* Executes all the methods that have been annotated with @FailedTask.
|
||||
* @param throwable that was not caught for the task execution.
|
||||
* @param taskExecution associated with the event.
|
||||
*/
|
||||
@Override
|
||||
public void onTaskFailed(TaskExecution taskExecution, Throwable throwable) {
|
||||
executeTaskListenerWithThrowable(taskExecution, throwable,
|
||||
failedTaskInstances.keySet(),failedTaskInstances);
|
||||
this.failedTaskInstances.keySet(), this.failedTaskInstances);
|
||||
}
|
||||
|
||||
private void executeTaskListener(TaskExecution taskExecution, Set<Method> methods, Map<Method, Object> instances){
|
||||
private void executeTaskListener(TaskExecution taskExecution, Set<Method> methods,
|
||||
Map<Method, Object> instances) {
|
||||
for (Method method : methods) {
|
||||
try {
|
||||
method.invoke(instances.get(method),taskExecution);
|
||||
method.invoke(instances.get(method), taskExecution);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new TaskExecutionException("@BeforeTask and @AfterTask annotated methods must be public.", e);
|
||||
throw new TaskExecutionException(
|
||||
"@BeforeTask and @AfterTask annotated methods must be public.",
|
||||
e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new TaskExecutionException(String.format("Failed to process @BeforeTask or @AfterTask" +
|
||||
" annotation because: %s", e.getTargetException().getMessage()), e);
|
||||
throw new TaskExecutionException(String.format(
|
||||
"Failed to process @BeforeTask or @AfterTask"
|
||||
+ " annotation because: %s",
|
||||
e.getTargetException().getMessage()), e);
|
||||
}
|
||||
catch (IllegalArgumentException e){
|
||||
throw new TaskExecutionException("taskExecution parameter is required for @BeforeTask and @AfterTask annotated methods", e);
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new TaskExecutionException("taskExecution parameter "
|
||||
+ "is required for @BeforeTask and @AfterTask annotated methods",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void executeTaskListenerWithThrowable(TaskExecution taskExecution,
|
||||
Throwable throwable, Set<Method> methods, Map<Method, Object> instances){
|
||||
Throwable throwable, Set<Method> methods, Map<Method, Object> instances) {
|
||||
for (Method method : methods) {
|
||||
try {
|
||||
method.invoke(instances.get(method),taskExecution, throwable);
|
||||
method.invoke(instances.get(method), taskExecution, throwable);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new TaskExecutionException("@FailedTask annotated methods must be public.", e);
|
||||
throw new TaskExecutionException(
|
||||
"@FailedTask annotated methods must be public.", e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new TaskExecutionException(String.format("Failed to process @FailedTask " +
|
||||
"annotation because: %s", e.getTargetException().getMessage()), e);
|
||||
throw new TaskExecutionException(String.format(
|
||||
"Failed to process @FailedTask " + "annotation because: %s",
|
||||
e.getTargetException().getMessage()), e);
|
||||
}
|
||||
catch (IllegalArgumentException e){
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new TaskExecutionException("taskExecution and throwable parameters "
|
||||
+ "are required for @FailedTask annotated methods", e);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base package for spring cloud task.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
|
||||
public class TaskExecution {
|
||||
|
||||
/**
|
||||
* The unique id associated with the task execution.
|
||||
* The unique id associated with the task execution.
|
||||
*/
|
||||
private long executionId;
|
||||
|
||||
@@ -75,7 +75,7 @@ public class TaskExecution {
|
||||
private String externalExecutionId;
|
||||
|
||||
/**
|
||||
* Error information available upon the failure of a task
|
||||
* Error information available upon the failure of a task.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@@ -87,14 +87,12 @@ public class TaskExecution {
|
||||
private List<String> arguments;
|
||||
|
||||
public TaskExecution() {
|
||||
arguments = new ArrayList<>();
|
||||
this.arguments = new ArrayList<>();
|
||||
}
|
||||
|
||||
public TaskExecution(long executionId, Integer exitCode, String taskName,
|
||||
Date startTime, Date endTime,
|
||||
String exitMessage, List<String> arguments,
|
||||
String errorMessage, String externalExecutionId,
|
||||
Long parentExecutionId) {
|
||||
Date startTime, Date endTime, String exitMessage, List<String> arguments,
|
||||
String errorMessage, String externalExecutionId, Long parentExecutionId) {
|
||||
|
||||
Assert.notNull(arguments, "arguments must not be null");
|
||||
this.executionId = executionId;
|
||||
@@ -102,24 +100,23 @@ public class TaskExecution {
|
||||
this.taskName = taskName;
|
||||
this.exitMessage = exitMessage;
|
||||
this.arguments = new ArrayList<>(arguments);
|
||||
this.startTime = (startTime != null) ? (Date)startTime.clone() : null;
|
||||
this.endTime = (endTime != null) ? (Date)endTime.clone() : null;
|
||||
this.startTime = (startTime != null) ? (Date) startTime.clone() : null;
|
||||
this.endTime = (endTime != null) ? (Date) endTime.clone() : null;
|
||||
this.errorMessage = errorMessage;
|
||||
this.externalExecutionId = externalExecutionId;
|
||||
this.parentExecutionId = parentExecutionId;
|
||||
}
|
||||
|
||||
public TaskExecution(long executionId, Integer exitCode, String taskName,
|
||||
Date startTime, Date endTime,
|
||||
String exitMessage, List<String> arguments,
|
||||
Date startTime, Date endTime, String exitMessage, List<String> arguments,
|
||||
String errorMessage, String externalExecutionId) {
|
||||
|
||||
this(executionId, exitCode, taskName, startTime, endTime, exitMessage,
|
||||
arguments, errorMessage,externalExecutionId, null);
|
||||
this(executionId, exitCode, taskName, startTime, endTime, exitMessage, arguments,
|
||||
errorMessage, externalExecutionId, null);
|
||||
}
|
||||
|
||||
public long getExecutionId() {
|
||||
return executionId;
|
||||
return this.executionId;
|
||||
}
|
||||
|
||||
public Integer getExitCode() {
|
||||
@@ -131,7 +128,7 @@ public class TaskExecution {
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
return this.taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
@@ -139,23 +136,23 @@ public class TaskExecution {
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return (startTime != null) ? (Date)startTime.clone() : null;
|
||||
return (this.startTime != null) ? (Date) this.startTime.clone() : null;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
this.startTime = (startTime != null) ? (Date)startTime.clone() : null;
|
||||
this.startTime = (startTime != null) ? (Date) startTime.clone() : null;
|
||||
}
|
||||
|
||||
public Date getEndTime() {
|
||||
return (endTime != null) ? (Date)endTime.clone() : null;
|
||||
return (this.endTime != null) ? (Date) this.endTime.clone() : null;
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime) {
|
||||
this.endTime = (endTime != null) ? (Date)endTime.clone() : null;
|
||||
this.endTime = (endTime != null) ? (Date) endTime.clone() : null;
|
||||
}
|
||||
|
||||
public String getExitMessage() {
|
||||
return exitMessage;
|
||||
return this.exitMessage;
|
||||
}
|
||||
|
||||
public void setExitMessage(String exitMessage) {
|
||||
@@ -163,15 +160,15 @@ public class TaskExecution {
|
||||
}
|
||||
|
||||
public List<String> getArguments() {
|
||||
return arguments;
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
public void setArguments(List<String> arguments) {
|
||||
this.arguments = new ArrayList<> (arguments);
|
||||
this.arguments = new ArrayList<>(arguments);
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
@@ -179,7 +176,7 @@ public class TaskExecution {
|
||||
}
|
||||
|
||||
public String getExternalExecutionId() {
|
||||
return externalExecutionId;
|
||||
return this.externalExecutionId;
|
||||
}
|
||||
|
||||
public void setExternalExecutionId(String externalExecutionId) {
|
||||
@@ -187,7 +184,7 @@ public class TaskExecution {
|
||||
}
|
||||
|
||||
public Long getParentExecutionId() {
|
||||
return parentExecutionId;
|
||||
return this.parentExecutionId;
|
||||
}
|
||||
|
||||
public void setParentExecutionId(Long parentExecutionId) {
|
||||
@@ -196,17 +193,13 @@ public class TaskExecution {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskExecution{" +
|
||||
"executionId=" + executionId +
|
||||
", parentExecutionId=" + parentExecutionId +
|
||||
", exitCode=" + exitCode +
|
||||
", taskName='" + taskName + '\'' +
|
||||
", startTime=" + startTime +
|
||||
", endTime=" + endTime +
|
||||
", exitMessage='" + exitMessage + '\'' +
|
||||
", externalExecutionId='" + externalExecutionId + '\'' +
|
||||
", errorMessage='" + errorMessage + '\'' +
|
||||
", arguments=" + arguments +
|
||||
'}';
|
||||
return "TaskExecution{" + "executionId=" + this.executionId
|
||||
+ ", parentExecutionId=" + this.parentExecutionId + ", exitCode="
|
||||
+ this.exitCode + ", taskName='" + this.taskName + '\'' + ", startTime="
|
||||
+ this.startTime + ", endTime=" + this.endTime + ", exitMessage='"
|
||||
+ this.exitMessage + '\'' + ", externalExecutionId='"
|
||||
+ this.externalExecutionId + '\'' + ", errorMessage='" + this.errorMessage
|
||||
+ '\'' + ", arguments=" + this.arguments + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -33,16 +33,13 @@ public interface TaskExplorer {
|
||||
|
||||
/**
|
||||
* Retrieve a {@link TaskExecution} by its id.
|
||||
*
|
||||
* @param executionId the task execution id
|
||||
* @return the {@link TaskExecution} with this id, or null if not found
|
||||
*/
|
||||
TaskExecution getTaskExecution(long executionId);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a collection of taskExecutions that have the task name provided.
|
||||
*
|
||||
* @param taskName the name of the task
|
||||
* @param pageable the constraints for the search
|
||||
* @return the set of running executions for tasks with the specified name
|
||||
@@ -51,14 +48,12 @@ public interface TaskExplorer {
|
||||
|
||||
/**
|
||||
* Retrieve a list of available task names.
|
||||
*
|
||||
* @return the set of task names that have been executed
|
||||
*/
|
||||
List<String> getTaskNames();
|
||||
|
||||
/**
|
||||
* Get number of executions for a taskName.
|
||||
*
|
||||
* @param taskName the name of the task to be searched
|
||||
* @return the number of running tasks that have the taskname specified
|
||||
*/
|
||||
@@ -66,21 +61,18 @@ public interface TaskExplorer {
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions.
|
||||
*
|
||||
* @return current number of task executions.
|
||||
*/
|
||||
long getTaskExecutionCount();
|
||||
|
||||
/**
|
||||
* Retrieves current number of running task executions.
|
||||
*
|
||||
* @return current number of running task executions.
|
||||
*/
|
||||
long getRunningTaskExecutionCount();
|
||||
|
||||
/**
|
||||
* Get a collection/page of executions
|
||||
*
|
||||
* Get a collection/page of executions.
|
||||
* @param taskName the name of the task to be searched
|
||||
* @param pageable the constraints for the search
|
||||
* @return list of task executions
|
||||
@@ -88,9 +80,8 @@ public interface TaskExplorer {
|
||||
Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieves all the task executions within the pageable constraints sorted by
|
||||
* start date descending, taskExecution id descending.
|
||||
*
|
||||
* Retrieves all the task executions within the pageable constraints sorted by start
|
||||
* date descending, taskExecution id descending.
|
||||
* @param pageable the constraints for the search
|
||||
* @return page containing the results from the search
|
||||
*/
|
||||
@@ -98,8 +89,7 @@ public interface TaskExplorer {
|
||||
|
||||
/**
|
||||
* Returns the id of the TaskExecution that the requested Spring Batch job execution
|
||||
* was executed within the context of. Returns null if none were found.
|
||||
*
|
||||
* was executed within the context of. Returns null if none were found.
|
||||
* @param jobExecutionId the id of the JobExecution
|
||||
* @return the id of the {@link TaskExecution}
|
||||
*/
|
||||
@@ -108,39 +98,39 @@ public interface TaskExplorer {
|
||||
/**
|
||||
* Returns a Set of JobExecution ids for the jobs that were executed within the scope
|
||||
* of the requested task.
|
||||
*
|
||||
* @param taskExecutionId id of the {@link TaskExecution}
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the task.
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the
|
||||
* task.
|
||||
*/
|
||||
Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of the latest {@link TaskExecution} for 1 or more task names.
|
||||
* Returns a {@link List} of the latest {@link TaskExecution} for 1 or more task
|
||||
* names.
|
||||
*
|
||||
* Latest is defined by the most recent start time. A {@link TaskExecution} does not have to be finished
|
||||
* (The results may including pending {@link TaskExecution}s).
|
||||
* Latest is defined by the most recent start time. A {@link TaskExecution} does not
|
||||
* have to be finished (The results may including pending {@link TaskExecution}s).
|
||||
*
|
||||
* It is theoretically possible that a {@link TaskExecution} with the same name to have more than 1
|
||||
* {@link TaskExecution} for the exact same start time. In that case the {@link TaskExecution} with the
|
||||
* highest Task Execution ID is returned.
|
||||
*
|
||||
* This method will not consider end times in its calculations. Thus, when a task execution {@code A} starts
|
||||
* after task execution {@code B} but finishes BEFORE task execution {@code A}, then task execution {@code B}
|
||||
* is being returned.
|
||||
* It is theoretically possible that a {@link TaskExecution} with the same name to
|
||||
* have more than 1 {@link TaskExecution} for the exact same start time. In that case
|
||||
* the {@link TaskExecution} with the highest Task Execution ID is returned.
|
||||
*
|
||||
* This method will not consider end times in its calculations. Thus, when a task
|
||||
* execution {@code A} starts after task execution {@code B} but finishes BEFORE task
|
||||
* execution {@code A}, then task execution {@code B} is being returned.
|
||||
* @param taskNames At least 1 task name must be provided
|
||||
* @return List of TaskExecutions. May be empty but never null.
|
||||
*/
|
||||
List<TaskExecution> getLatestTaskExecutionsByTaskNames(String... taskNames);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the latest task execution for a given task name. Will ultimately apply the same algorithm underneath
|
||||
* as {@link #getLatestTaskExecutionsByTaskNames(String...)} but will only return a single result.
|
||||
*
|
||||
* Returns the latest task execution for a given task name. Will ultimately apply the
|
||||
* same algorithm underneath as {@link #getLatestTaskExecutionsByTaskNames(String...)}
|
||||
* but will only return a single result.
|
||||
* @param taskName Must not be null or empty
|
||||
* @return The latest Task Execution or null
|
||||
* @see #getLatestTaskExecutionsByTaskNames(String...)
|
||||
*/
|
||||
TaskExecution getLatestTaskExecutionForTaskName(String taskName);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.repository;
|
||||
|
||||
/**
|
||||
@@ -26,4 +27,5 @@ public interface TaskNameResolver {
|
||||
* @return the name of the task being executed within this context.
|
||||
*/
|
||||
String getTaskName();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -31,7 +31,6 @@ public interface TaskRepository {
|
||||
|
||||
/**
|
||||
* Notifies the repository that a taskExecution has completed.
|
||||
*
|
||||
* @param executionId to the task execution to be updated.
|
||||
* @param exitCode to be stored for this task.
|
||||
* @param endTime designated when the task completed.
|
||||
@@ -40,11 +39,10 @@ public interface TaskRepository {
|
||||
*/
|
||||
@Transactional
|
||||
TaskExecution completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage);
|
||||
String exitMessage);
|
||||
|
||||
/**
|
||||
* Notifies the repository that a taskExecution has completed.
|
||||
*
|
||||
* @param executionId to the task execution to be updated.
|
||||
* @param exitCode to be stored for this task execution.
|
||||
* @param endTime designated when the task completed.
|
||||
@@ -55,30 +53,26 @@ public interface TaskRepository {
|
||||
*/
|
||||
@Transactional
|
||||
TaskExecution completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage, String errorMessage);
|
||||
String exitMessage, String errorMessage);
|
||||
|
||||
/**
|
||||
* Notifies the repository that a taskExecution needs to be created.
|
||||
*
|
||||
* @param taskExecution a TaskExecution instance containing the startTime,
|
||||
* arguments and externalExecutionId that will be stored in the repository.
|
||||
* Only the values enumerated above will be stored for this
|
||||
* @param taskExecution a TaskExecution instance containing the startTime, arguments
|
||||
* and externalExecutionId that will be stored in the repository. Only the values
|
||||
* enumerated above will be stored for this TaskExecution.
|
||||
* @return the {@link TaskExecution} that was stored in the repository. The
|
||||
* TaskExecution's taskExecutionId will also contain the id that was used to store the
|
||||
* TaskExecution.
|
||||
* @return the {@link TaskExecution} that was stored in the repository. The
|
||||
* TaskExecution's taskExecutionId will also contain the id that was used
|
||||
* to store the TaskExecution.
|
||||
*/
|
||||
@Transactional
|
||||
TaskExecution createTaskExecution(TaskExecution taskExecution);
|
||||
|
||||
/**
|
||||
* Creates an empty TaskExecution with just an id and name provided. This is intended to be
|
||||
* utilized in systems where the request of launching a task is separate from the
|
||||
* actual start of a task (the underlying system may need to deploy the task prior to
|
||||
* launching, etc).
|
||||
*
|
||||
* Creates an empty TaskExecution with just an id and name provided. This is intended
|
||||
* to be utilized in systems where the request of launching a task is separate from
|
||||
* the actual start of a task (the underlying system may need to deploy the task prior
|
||||
* to launching, etc).
|
||||
* @param name task name to be associated with the task execution.
|
||||
*
|
||||
* @return the initial {@link TaskExecution}
|
||||
*/
|
||||
@Transactional
|
||||
@@ -89,7 +83,6 @@ public interface TaskRepository {
|
||||
* utilized in systems where the request of launching a task is separate from the
|
||||
* actual start of a task (the underlying system may need to deploy the task prior to
|
||||
* launching, etc).
|
||||
*
|
||||
* @return the initial {@link TaskExecution}
|
||||
*/
|
||||
@Transactional
|
||||
@@ -97,43 +90,38 @@ public interface TaskRepository {
|
||||
|
||||
/**
|
||||
* Notifies the repository that a taskExecution has has started.
|
||||
*
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param externalExecutionId id assigned to the task by the platform.
|
||||
* @return TaskExecution created based on the parameters.
|
||||
*/
|
||||
@Transactional
|
||||
TaskExecution startTaskExecution(long executionid, String taskName,
|
||||
Date startTime,List<String> arguments, String externalExecutionId);
|
||||
TaskExecution startTaskExecution(long executionid, String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId);
|
||||
|
||||
/**
|
||||
* Notifies the repository to update the taskExecution's externalExecutionId.
|
||||
*
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param externalExecutionId id assigned to the task by the platform.
|
||||
*/
|
||||
@Transactional
|
||||
void updateExternalExecutionId(long executionid,
|
||||
String externalExecutionId);
|
||||
void updateExternalExecutionId(long executionid, String externalExecutionId);
|
||||
|
||||
/**
|
||||
* Notifies the repository that a taskExecution has has started.
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param executionid to the task execution to be updated.
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param externalExecutionId id assigned to the task by the platform.
|
||||
* @param parentExecutionId the parent task execution id.
|
||||
|
||||
* @return A TaskExecution that contains the information available at the
|
||||
* beginning of a TaskExecution.
|
||||
* @return A TaskExecution that contains the information available at the beginning of
|
||||
* a TaskExecution.
|
||||
*/
|
||||
@Transactional
|
||||
TaskExecution startTaskExecution(long executionid, String taskName,
|
||||
Date startTime,List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId);
|
||||
TaskExecution startTaskExecution(long executionid, String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId, Long parentExecutionId);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -61,22 +61,33 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
|
||||
/**
|
||||
* SELECT clause for task execution.
|
||||
*/
|
||||
public static final String SELECT_CLAUSE = "TASK_EXECUTION_ID, "
|
||||
+ "START_TIME, END_TIME, TASK_NAME, EXIT_CODE, "
|
||||
+ "EXIT_MESSAGE, ERROR_MESSAGE, LAST_UPDATED, "
|
||||
+ "EXTERNAL_EXECUTION_ID, PARENT_EXECUTION_ID ";
|
||||
|
||||
/**
|
||||
* FROM clause for task execution.
|
||||
*/
|
||||
public static final String FROM_CLAUSE = "%PREFIX%EXECUTION";
|
||||
|
||||
public static final String RUNNING_TASK_WHERE_CLAUSE =
|
||||
"where TASK_NAME = :taskName AND END_TIME IS NULL ";
|
||||
/**
|
||||
* WHERE clause for running task.
|
||||
*/
|
||||
public static final String RUNNING_TASK_WHERE_CLAUSE = "where TASK_NAME = :taskName AND END_TIME IS NULL ";
|
||||
|
||||
/**
|
||||
* WHERE clause for task name.
|
||||
*/
|
||||
public static final String TASK_NAME_WHERE_CLAUSE = "where TASK_NAME = :taskName ";
|
||||
|
||||
private static final String SAVE_TASK_EXECUTION = "INSERT into %PREFIX%EXECUTION"
|
||||
+ "(TASK_EXECUTION_ID, EXIT_CODE, START_TIME, TASK_NAME, LAST_UPDATED, EXTERNAL_EXECUTION_ID, PARENT_EXECUTION_ID)"
|
||||
+ "values (:taskExecutionId, :exitCode, :startTime, :taskName, :lastUpdated, :externalExecutionId, :parentExecutionId)";
|
||||
+ "values (:taskExecutionId, :exitCode, :startTime, "
|
||||
+ ":taskName, :lastUpdated, :externalExecutionId, :parentExecutionId)";
|
||||
|
||||
private static final String CREATE_TASK_ARGUMENT = "INSERT into "
|
||||
+ "%PREFIX%EXECUTION_PARAMS(TASK_EXECUTION_ID, TASK_PARAM ) values (:taskExecutionId, :taskParam)";
|
||||
@@ -85,9 +96,11 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
+ "START_TIME = :startTime, TASK_NAME = :taskName, LAST_UPDATED = :lastUpdated";
|
||||
|
||||
private static final String START_TASK_EXECUTION_EXTERNAL_ID_SUFFIX = ", "
|
||||
+ "EXTERNAL_EXECUTION_ID = :externalExecutionId, PARENT_EXECUTION_ID = :parentExecutionId where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
+ "EXTERNAL_EXECUTION_ID = :externalExecutionId, PARENT_EXECUTION_ID = :parentExecutionId "
|
||||
+ "where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private static final String START_TASK_EXECUTION_SUFFIX = ", PARENT_EXECUTION_ID = :parentExecutionId where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
private static final String START_TASK_EXECUTION_SUFFIX = ", PARENT_EXECUTION_ID = :parentExecutionId "
|
||||
+ "where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private static final String CHECK_TASK_EXECUTION_EXISTS = "SELECT COUNT(*) FROM "
|
||||
+ "%PREFIX%EXECUTION WHERE TASK_EXECUTION_ID = :taskExecutionId";
|
||||
@@ -99,8 +112,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
private static final String UPDATE_TASK_EXECUTION_EXTERNAL_EXECUTION_ID = "UPDATE %PREFIX%EXECUTION set "
|
||||
+ "EXTERNAL_EXECUTION_ID = :externalExecutionId where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private static final String GET_EXECUTION_BY_ID = "SELECT TASK_EXECUTION_ID, " +
|
||||
"START_TIME, END_TIME, TASK_NAME, EXIT_CODE, "
|
||||
private static final String GET_EXECUTION_BY_ID = "SELECT TASK_EXECUTION_ID, "
|
||||
+ "START_TIME, END_TIME, TASK_NAME, EXIT_CODE, "
|
||||
+ "EXIT_MESSAGE, ERROR_MESSAGE, LAST_UPDATED, EXTERNAL_EXECUTION_ID, "
|
||||
+ "PARENT_EXECUTION_ID "
|
||||
+ "from %PREFIX%EXECUTION where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
@@ -108,41 +121,40 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
private static final String FIND_ARGUMENT_FROM_ID = "SELECT TASK_EXECUTION_ID, "
|
||||
+ "TASK_PARAM from %PREFIX%EXECUTION_PARAMS where TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private static final String TASK_EXECUTION_COUNT = "SELECT COUNT(*) FROM " +
|
||||
"%PREFIX%EXECUTION ";
|
||||
private static final String TASK_EXECUTION_COUNT = "SELECT COUNT(*) FROM "
|
||||
+ "%PREFIX%EXECUTION ";
|
||||
|
||||
private static final String TASK_EXECUTION_COUNT_BY_NAME = "SELECT COUNT(*) FROM " +
|
||||
"%PREFIX%EXECUTION where TASK_NAME = :taskName";
|
||||
private static final String TASK_EXECUTION_COUNT_BY_NAME = "SELECT COUNT(*) FROM "
|
||||
+ "%PREFIX%EXECUTION where TASK_NAME = :taskName";
|
||||
|
||||
private static final String RUNNING_TASK_EXECUTION_COUNT_BY_NAME = "SELECT COUNT(*) FROM " +
|
||||
"%PREFIX%EXECUTION where TASK_NAME = :taskName AND END_TIME IS NULL ";
|
||||
private static final String RUNNING_TASK_EXECUTION_COUNT_BY_NAME = "SELECT COUNT(*) FROM "
|
||||
+ "%PREFIX%EXECUTION where TASK_NAME = :taskName AND END_TIME IS NULL ";
|
||||
|
||||
private static final String RUNNING_TASK_EXECUTION_COUNT = "SELECT COUNT(*) FROM " +
|
||||
"%PREFIX%EXECUTION where END_TIME IS NULL ";
|
||||
private static final String RUNNING_TASK_EXECUTION_COUNT = "SELECT COUNT(*) FROM "
|
||||
+ "%PREFIX%EXECUTION where END_TIME IS NULL ";
|
||||
|
||||
private static final String LAST_TASK_EXECUTIONS_BY_TASK_NAMES =
|
||||
"select TE2.* from (" +
|
||||
"select MAX(TE.TASK_EXECUTION_ID) as TASK_EXECUTION_ID, TE.TASK_NAME, TE.START_TIME from (" +
|
||||
"select TASK_NAME, MAX(START_TIME) as START_TIME" +
|
||||
" FROM %PREFIX%EXECUTION where TASK_NAME in (:taskNames)" +
|
||||
" GROUP BY TASK_NAME" +
|
||||
") TE_MAX " +
|
||||
"inner join %PREFIX%EXECUTION TE ON TE.TASK_NAME = TE_MAX.TASK_NAME AND TE.START_TIME = TE_MAX.START_TIME " +
|
||||
"group by TE.TASK_NAME, TE.START_TIME" +
|
||||
") TE1 " +
|
||||
"inner join %PREFIX%EXECUTION TE2 ON TE1.TASK_EXECUTION_ID = TE2.TASK_EXECUTION_ID " +
|
||||
"order by TE2.START_TIME DESC, TE2.TASK_EXECUTION_ID DESC";
|
||||
private static final String LAST_TASK_EXECUTIONS_BY_TASK_NAMES = "select TE2.* from ("
|
||||
+ "select MAX(TE.TASK_EXECUTION_ID) as TASK_EXECUTION_ID, TE.TASK_NAME, TE.START_TIME from ("
|
||||
+ "select TASK_NAME, MAX(START_TIME) as START_TIME"
|
||||
+ " FROM %PREFIX%EXECUTION where TASK_NAME in (:taskNames)"
|
||||
+ " GROUP BY TASK_NAME" + ") TE_MAX "
|
||||
+ "inner join %PREFIX%EXECUTION TE ON TE.TASK_NAME = TE_MAX.TASK_NAME AND TE.START_TIME = TE_MAX.START_TIME "
|
||||
+ "group by TE.TASK_NAME, TE.START_TIME" + ") TE1 "
|
||||
+ "inner join %PREFIX%EXECUTION TE2 ON TE1.TASK_EXECUTION_ID = TE2.TASK_EXECUTION_ID "
|
||||
+ "order by TE2.START_TIME DESC, TE2.TASK_EXECUTION_ID DESC";
|
||||
|
||||
private static final String FIND_TASK_NAMES = "SELECT distinct TASK_NAME from %PREFIX%EXECUTION order by TASK_NAME";
|
||||
|
||||
private static final String FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID = "SELECT TASK_EXECUTION_ID FROM %PREFIX%TASK_BATCH WHERE JOB_EXECUTION_ID = :jobExecutionId";
|
||||
private static final String FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID = "SELECT TASK_EXECUTION_ID FROM "
|
||||
+ "%PREFIX%TASK_BATCH WHERE JOB_EXECUTION_ID = :jobExecutionId";
|
||||
|
||||
private static final String FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID = "SELECT JOB_EXECUTION_ID FROM %PREFIX%TASK_BATCH WHERE TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private String tablePrefix = TaskProperties.DEFAULT_TABLE_PREFIX;
|
||||
private static final String FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID = "SELECT JOB_EXECUTION_ID "
|
||||
+ "FROM %PREFIX%TASK_BATCH WHERE TASK_EXECUTION_ID = :taskExecutionId";
|
||||
|
||||
private final NamedParameterJdbcTemplate jdbcTemplate;
|
||||
|
||||
private String tablePrefix = TaskProperties.DEFAULT_TABLE_PREFIX;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
private LinkedHashMap<String, Order> orderMap;
|
||||
@@ -169,120 +181,119 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
Assert.notNull(dataSource, "The dataSource must not be null.");
|
||||
this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
this.dataSource = dataSource;
|
||||
orderMap = new LinkedHashMap<>();
|
||||
orderMap.put("START_TIME", Order.DESCENDING);
|
||||
orderMap.put("TASK_EXECUTION_ID", Order.DESCENDING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId) {
|
||||
return createTaskExecution(taskName, startTime, arguments,
|
||||
externalExecutionId, null);
|
||||
this.orderMap = new LinkedHashMap<>();
|
||||
this.orderMap.put("START_TIME", Order.DESCENDING);
|
||||
this.orderMap.put("TASK_EXECUTION_ID", Order.DESCENDING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId) {
|
||||
List<String> arguments, String externalExecutionId) {
|
||||
return createTaskExecution(taskName, startTime, arguments, externalExecutionId,
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId, Long parentExecutionId) {
|
||||
long nextExecutionId = getNextExecutionId();
|
||||
|
||||
TaskExecution taskExecution = new TaskExecution(nextExecutionId, null, taskName,
|
||||
startTime, null, null, arguments, null, externalExecutionId);
|
||||
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskExecutionId", nextExecutionId, Types.BIGINT)
|
||||
.addValue("exitCode", null, Types.INTEGER)
|
||||
.addValue("startTime", startTime, Types.TIMESTAMP)
|
||||
.addValue("taskName", taskName, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("externalExecutionId", externalExecutionId, Types.VARCHAR)
|
||||
.addValue("parentExecutionId", parentExecutionId, Types.BIGINT);
|
||||
.addValue("taskExecutionId", nextExecutionId, Types.BIGINT)
|
||||
.addValue("exitCode", null, Types.INTEGER)
|
||||
.addValue("startTime", startTime, Types.TIMESTAMP)
|
||||
.addValue("taskName", taskName, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("externalExecutionId", externalExecutionId, Types.VARCHAR)
|
||||
.addValue("parentExecutionId", parentExecutionId, Types.BIGINT);
|
||||
|
||||
jdbcTemplate.update(
|
||||
getQuery(SAVE_TASK_EXECUTION),
|
||||
queryParameters);
|
||||
this.jdbcTemplate.update(getQuery(SAVE_TASK_EXECUTION), queryParameters);
|
||||
insertTaskArguments(nextExecutionId, arguments);
|
||||
return taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments,
|
||||
String externalExecutionId) {
|
||||
Date startTime, List<String> arguments, String externalExecutionId) {
|
||||
return startTaskExecution(executionId, taskName, startTime, arguments,
|
||||
externalExecutionId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments,
|
||||
String externalExecutionId, Long parentExecutionId) {
|
||||
Date startTime, List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId) {
|
||||
TaskExecution taskExecution = new TaskExecution(executionId, null, taskName,
|
||||
startTime, null, null, arguments,null, externalExecutionId, parentExecutionId);
|
||||
startTime, null, null, arguments, null, externalExecutionId,
|
||||
parentExecutionId);
|
||||
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("startTime", startTime, Types.TIMESTAMP)
|
||||
.addValue("exitCode", null, Types.INTEGER)
|
||||
.addValue("taskName", taskName, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("parentExecutionId", parentExecutionId, Types.BIGINT)
|
||||
.addValue("taskExecutionId", executionId, Types.BIGINT);
|
||||
.addValue("startTime", startTime, Types.TIMESTAMP)
|
||||
.addValue("exitCode", null, Types.INTEGER)
|
||||
.addValue("taskName", taskName, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("parentExecutionId", parentExecutionId, Types.BIGINT)
|
||||
.addValue("taskExecutionId", executionId, Types.BIGINT);
|
||||
|
||||
String updateString = START_TASK_EXECUTION_PREFIX;
|
||||
|
||||
if(externalExecutionId == null) {
|
||||
if (externalExecutionId == null) {
|
||||
updateString += START_TASK_EXECUTION_SUFFIX;
|
||||
}
|
||||
else {
|
||||
updateString += START_TASK_EXECUTION_EXTERNAL_ID_SUFFIX;
|
||||
queryParameters.addValue("externalExecutionId", externalExecutionId, Types.VARCHAR);
|
||||
queryParameters.addValue("externalExecutionId", externalExecutionId,
|
||||
Types.VARCHAR);
|
||||
}
|
||||
|
||||
jdbcTemplate.update(getQuery(updateString), queryParameters);
|
||||
this.jdbcTemplate.update(getQuery(updateString), queryParameters);
|
||||
insertTaskArguments(executionId, arguments);
|
||||
return taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeTaskExecution(long taskExecutionId, Integer exitCode, Date endTime,
|
||||
String exitMessage, String errorMessage) {
|
||||
public void completeTaskExecution(long taskExecutionId, Integer exitCode,
|
||||
Date endTime, String exitMessage, String errorMessage) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
|
||||
// Check if given TaskExecution's Id already exists, if none is found
|
||||
// it is invalid and an exception should be thrown.
|
||||
if (jdbcTemplate.queryForObject(getQuery(CHECK_TASK_EXECUTION_EXISTS), queryParameters, Integer.class) != 1) {
|
||||
throw new IllegalStateException("Invalid TaskExecution, ID " + taskExecutionId + " not found.");
|
||||
if (this.jdbcTemplate.queryForObject(getQuery(CHECK_TASK_EXECUTION_EXISTS),
|
||||
queryParameters, Integer.class) != 1) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid TaskExecution, ID " + taskExecutionId + " not found.");
|
||||
}
|
||||
|
||||
final MapSqlParameterSource parameters = new MapSqlParameterSource()
|
||||
.addValue("endTime", endTime, Types.TIMESTAMP)
|
||||
.addValue("exitCode", exitCode, Types.INTEGER)
|
||||
.addValue("exitMessage", exitMessage, Types.VARCHAR)
|
||||
.addValue("errorMessage", errorMessage, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
.addValue("endTime", endTime, Types.TIMESTAMP)
|
||||
.addValue("exitCode", exitCode, Types.INTEGER)
|
||||
.addValue("exitMessage", exitMessage, Types.VARCHAR)
|
||||
.addValue("errorMessage", errorMessage, Types.VARCHAR)
|
||||
.addValue("lastUpdated", new Date(), Types.TIMESTAMP)
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
|
||||
jdbcTemplate.update(
|
||||
getQuery(UPDATE_TASK_EXECUTION),
|
||||
parameters);
|
||||
this.jdbcTemplate.update(getQuery(UPDATE_TASK_EXECUTION), parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeTaskExecution(long taskExecutionId, Integer exitCode, Date endTime,
|
||||
String exitMessage) {
|
||||
public void completeTaskExecution(long taskExecutionId, Integer exitCode,
|
||||
Date endTime, String exitMessage) {
|
||||
completeTaskExecution(taskExecutionId, exitCode, endTime, exitMessage, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution getTaskExecution(long executionId) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskExecutionId", executionId, Types.BIGINT);
|
||||
.addValue("taskExecutionId", executionId, Types.BIGINT);
|
||||
|
||||
try {
|
||||
TaskExecution taskExecution = jdbcTemplate.queryForObject(getQuery(GET_EXECUTION_BY_ID),
|
||||
queryParameters, new TaskExecutionRowMapper());
|
||||
TaskExecution taskExecution = this.jdbcTemplate.queryForObject(
|
||||
getQuery(GET_EXECUTION_BY_ID), queryParameters,
|
||||
new TaskExecutionRowMapper());
|
||||
taskExecution.setArguments(getTaskArguments(executionId));
|
||||
return taskExecution;
|
||||
}
|
||||
@@ -295,11 +306,11 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
public long getTaskExecutionCountByTaskName(String taskName) {
|
||||
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskName", taskName, Types.VARCHAR);
|
||||
.addValue("taskName", taskName, Types.VARCHAR);
|
||||
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(TASK_EXECUTION_COUNT_BY_NAME), queryParameters, Long.class);
|
||||
return this.jdbcTemplate.queryForObject(
|
||||
getQuery(TASK_EXECUTION_COUNT_BY_NAME), queryParameters, Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return 0;
|
||||
@@ -309,11 +320,12 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public long getRunningTaskExecutionCountByTaskName(String taskName) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskName", taskName, Types.VARCHAR);
|
||||
.addValue("taskName", taskName, Types.VARCHAR);
|
||||
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(RUNNING_TASK_EXECUTION_COUNT_BY_NAME), queryParameters, Long.class);
|
||||
return this.jdbcTemplate.queryForObject(
|
||||
getQuery(RUNNING_TASK_EXECUTION_COUNT_BY_NAME), queryParameters,
|
||||
Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return 0;
|
||||
@@ -325,8 +337,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
try {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource();
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(RUNNING_TASK_EXECUTION_COUNT), queryParameters, Long.class);
|
||||
return this.jdbcTemplate.queryForObject(
|
||||
getQuery(RUNNING_TASK_EXECUTION_COUNT), queryParameters, Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return 0;
|
||||
@@ -345,14 +357,15 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(taskNamesAsList.size() == taskNames.length,
|
||||
String.format("Task names must not contain any empty elements but %s of %s were empty or null.",
|
||||
taskNames.length - taskNamesAsList.size(), taskNames.length));
|
||||
Assert.isTrue(taskNamesAsList.size() == taskNames.length, String.format(
|
||||
"Task names must not contain any empty elements but %s of %s were empty or null.",
|
||||
taskNames.length - taskNamesAsList.size(), taskNames.length));
|
||||
|
||||
try {
|
||||
final Map<String, List<String>> paramMap = Collections.singletonMap("taskNames", taskNamesAsList);
|
||||
return this.jdbcTemplate.query(
|
||||
getQuery(LAST_TASK_EXECUTIONS_BY_TASK_NAMES), paramMap, new TaskExecutionRowMapper());
|
||||
final Map<String, List<String>> paramMap = Collections
|
||||
.singletonMap("taskNames", taskNamesAsList);
|
||||
return this.jdbcTemplate.query(getQuery(LAST_TASK_EXECUTIONS_BY_TASK_NAMES),
|
||||
paramMap, new TaskExecutionRowMapper());
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return Collections.emptyList();
|
||||
@@ -362,7 +375,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public TaskExecution getLatestTaskExecutionForTaskName(String taskName) {
|
||||
Assert.hasText(taskName, "The task name must not be empty.");
|
||||
final List<TaskExecution> taskExecutions = this.getLatestTaskExecutionsByTaskNames(taskName);
|
||||
final List<TaskExecution> taskExecutions = this
|
||||
.getLatestTaskExecutionsByTaskNames(taskName);
|
||||
if (taskExecutions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -370,7 +384,9 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
return taskExecutions.get(0);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Only expected a single TaskExecution but received " + taskExecutions.size());
|
||||
throw new IllegalStateException(
|
||||
"Only expected a single TaskExecution but received "
|
||||
+ taskExecutions.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,8 +394,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
public long getTaskExecutionCount() {
|
||||
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(TASK_EXECUTION_COUNT), new MapSqlParameterSource(), Long.class);
|
||||
return this.jdbcTemplate.queryForObject(getQuery(TASK_EXECUTION_COUNT),
|
||||
new MapSqlParameterSource(), Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return 0;
|
||||
@@ -387,14 +403,17 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable) {
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName,
|
||||
Pageable pageable) {
|
||||
return queryForPageableResults(pageable, SELECT_CLAUSE, FROM_CLAUSE,
|
||||
RUNNING_TASK_WHERE_CLAUSE, new MapSqlParameterSource("taskName", taskName),
|
||||
RUNNING_TASK_WHERE_CLAUSE,
|
||||
new MapSqlParameterSource("taskName", taskName),
|
||||
getRunningTaskExecutionCountByTaskName(taskName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable) {
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName,
|
||||
Pageable pageable) {
|
||||
return queryForPageableResults(pageable, SELECT_CLAUSE, FROM_CLAUSE,
|
||||
TASK_NAME_WHERE_CLAUSE, new MapSqlParameterSource("taskName", taskName),
|
||||
getTaskExecutionCountByTaskName(taskName));
|
||||
@@ -402,7 +421,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
@Override
|
||||
public List<String> getTaskNames() {
|
||||
return jdbcTemplate.queryForList(getQuery(FIND_TASK_NAMES), new MapSqlParameterSource(), String.class);
|
||||
return this.jdbcTemplate.queryForList(getQuery(FIND_TASK_NAMES),
|
||||
new MapSqlParameterSource(), String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -415,19 +435,18 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
this.taskIncrementer = taskIncrementer;
|
||||
}
|
||||
|
||||
public long getNextExecutionId(){
|
||||
return taskIncrementer.nextLongValue();
|
||||
public long getNextExecutionId() {
|
||||
return this.taskIncrementer.nextLongValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTaskExecutionIdByJobExecutionId(long jobExecutionId) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("jobExecutionId", jobExecutionId, Types.BIGINT);
|
||||
.addValue("jobExecutionId", jobExecutionId, Types.BIGINT);
|
||||
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID),
|
||||
queryParameters,
|
||||
return this.jdbcTemplate.queryForObject(
|
||||
getQuery(FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID), queryParameters,
|
||||
Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
@@ -438,19 +457,20 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
|
||||
try {
|
||||
return jdbcTemplate.query(
|
||||
getQuery(FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID),
|
||||
queryParameters,
|
||||
return this.jdbcTemplate.query(
|
||||
getQuery(FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID), queryParameters,
|
||||
new ResultSetExtractor<Set<Long>>() {
|
||||
@Override
|
||||
public Set<Long> extractData(ResultSet resultSet) throws SQLException, DataAccessException {
|
||||
public Set<Long> extractData(ResultSet resultSet)
|
||||
throws SQLException, DataAccessException {
|
||||
Set<Long> jobExecutionIds = new TreeSet<>();
|
||||
|
||||
while(resultSet.next()) {
|
||||
jobExecutionIds.add(resultSet.getLong("JOB_EXECUTION_ID"));
|
||||
while (resultSet.next()) {
|
||||
jobExecutionIds
|
||||
.add(resultSet.getLong("JOB_EXECUTION_ID"));
|
||||
}
|
||||
|
||||
return jobExecutionIds;
|
||||
@@ -463,29 +483,27 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExternalExecutionId(long taskExecutionId, String externalExecutionId) {
|
||||
public void updateExternalExecutionId(long taskExecutionId,
|
||||
String externalExecutionId) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("externalExecutionId", externalExecutionId, Types.VARCHAR)
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
.addValue("externalExecutionId", externalExecutionId, Types.VARCHAR)
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT);
|
||||
|
||||
if (jdbcTemplate.update(
|
||||
if (this.jdbcTemplate.update(
|
||||
getQuery(UPDATE_TASK_EXECUTION_EXTERNAL_EXECUTION_ID),
|
||||
queryParameters) != 1) {
|
||||
throw new IllegalStateException("Invalid TaskExecution, ID "
|
||||
+ taskExecutionId + " not found.");
|
||||
throw new IllegalStateException(
|
||||
"Invalid TaskExecution, ID " + taskExecutionId + " not found.");
|
||||
}
|
||||
}
|
||||
|
||||
private Page<TaskExecution> queryForPageableResults(Pageable pageable,
|
||||
String selectClause,
|
||||
String fromClause,
|
||||
String whereClause,
|
||||
MapSqlParameterSource queryParameters,
|
||||
long totalCount){
|
||||
String selectClause, String fromClause, String whereClause,
|
||||
MapSqlParameterSource queryParameters, long totalCount) {
|
||||
SqlPagingQueryProviderFactoryBean factoryBean = new SqlPagingQueryProviderFactoryBean();
|
||||
factoryBean.setSelectClause(selectClause);
|
||||
factoryBean.setFromClause(fromClause);
|
||||
if(StringUtils.hasText(whereClause)){
|
||||
if (StringUtils.hasText(whereClause)) {
|
||||
factoryBean.setWhereClause(whereClause);
|
||||
}
|
||||
final Sort sort = pageable.getSort();
|
||||
@@ -493,7 +511,8 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
if (sort != null) {
|
||||
for (Sort.Order sortOrder : sort) {
|
||||
sortOrderMap.put(sortOrder.getProperty(), sortOrder.isAscending() ? Order.ASCENDING : Order.DESCENDING);
|
||||
sortOrderMap.put(sortOrder.getProperty(),
|
||||
sortOrder.isAscending() ? Order.ASCENDING : Order.DESCENDING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,29 +527,25 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
PagingQueryProvider pagingQueryProvider;
|
||||
try {
|
||||
pagingQueryProvider = factoryBean.getObject();
|
||||
pagingQueryProvider.init(dataSource);
|
||||
pagingQueryProvider.init(this.dataSource);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
String query = pagingQueryProvider.getPageQuery(pageable);
|
||||
List<TaskExecution> resultList = jdbcTemplate.query(
|
||||
getQuery(query),
|
||||
queryParameters,
|
||||
new TaskExecutionRowMapper());
|
||||
List<TaskExecution> resultList = this.jdbcTemplate.query(getQuery(query),
|
||||
queryParameters, new TaskExecutionRowMapper());
|
||||
return new PageImpl<>(resultList, pageable, totalCount);
|
||||
}
|
||||
|
||||
private String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%PREFIX%", tablePrefix);
|
||||
return StringUtils.replace(base, "%PREFIX%", this.tablePrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts all arguments from the provided
|
||||
* task arguments.
|
||||
*
|
||||
* @param executionId The executionId to which the arguments are associated.
|
||||
* @param taskArguments The arguments to be stored.
|
||||
* Convenience method that inserts all arguments from the provided task arguments.
|
||||
* @param executionId The executionId to which the arguments are associated.
|
||||
* @param taskArguments The arguments to be stored.
|
||||
*/
|
||||
private void insertTaskArguments(long executionId, List<String> taskArguments) {
|
||||
for (String args : taskArguments) {
|
||||
@@ -541,26 +556,29 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
/**
|
||||
* Convenience method that inserts an individual records into the
|
||||
* TASK_EXECUTION_PARAMS table.
|
||||
* @param taskExecutionId id of a task execution
|
||||
* @param taskParam task parameters
|
||||
*/
|
||||
private void insertArgument(long taskExecutionId, String taskParam) {
|
||||
final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT)
|
||||
.addValue("taskParam", taskParam, Types.VARCHAR);
|
||||
jdbcTemplate.update(getQuery(CREATE_TASK_ARGUMENT), queryParameters);
|
||||
.addValue("taskExecutionId", taskExecutionId, Types.BIGINT)
|
||||
.addValue("taskParam", taskParam, Types.VARCHAR);
|
||||
this.jdbcTemplate.update(getQuery(CREATE_TASK_ARGUMENT), queryParameters);
|
||||
}
|
||||
|
||||
private List<String> getTaskArguments(long taskExecutionId){
|
||||
final List<String> params= new ArrayList<>();
|
||||
private List<String> getTaskArguments(long taskExecutionId) {
|
||||
final List<String> params = new ArrayList<>();
|
||||
RowCallbackHandler handler = new RowCallbackHandler() {
|
||||
@Override
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
params.add(rs.getString(2));
|
||||
}
|
||||
};
|
||||
jdbcTemplate.query(getQuery(FIND_ARGUMENT_FROM_ID), new MapSqlParameterSource("taskExecutionId", taskExecutionId),
|
||||
handler);
|
||||
this.jdbcTemplate.query(getQuery(FIND_ARGUMENT_FROM_ID),
|
||||
new MapSqlParameterSource("taskExecutionId", taskExecutionId), handler);
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-usable mapper for {@link TaskExecution} instances.
|
||||
*
|
||||
@@ -572,26 +590,23 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
@Override
|
||||
public TaskExecution mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
long id = rs.getLong("TASK_EXECUTION_ID");
|
||||
long id = rs.getLong("TASK_EXECUTION_ID");
|
||||
Long parentExecutionId = rs.getLong("PARENT_EXECUTION_ID");
|
||||
if(rs.wasNull()) {
|
||||
if (rs.wasNull()) {
|
||||
parentExecutionId = null;
|
||||
}
|
||||
return new TaskExecution(id,
|
||||
getNullableExitCode(rs),
|
||||
rs.getString("TASK_NAME"),
|
||||
rs.getTimestamp("START_TIME"),
|
||||
rs.getTimestamp("END_TIME"),
|
||||
rs.getString("EXIT_MESSAGE"),
|
||||
getTaskArguments(id),
|
||||
rs.getString("ERROR_MESSAGE"),
|
||||
rs.getString("EXTERNAL_EXECUTION_ID"),
|
||||
parentExecutionId);
|
||||
return new TaskExecution(id, getNullableExitCode(rs),
|
||||
rs.getString("TASK_NAME"), rs.getTimestamp("START_TIME"),
|
||||
rs.getTimestamp("END_TIME"), rs.getString("EXIT_MESSAGE"),
|
||||
getTaskArguments(id), rs.getString("ERROR_MESSAGE"),
|
||||
rs.getString("EXTERNAL_EXECUTION_ID"), parentExecutionId);
|
||||
}
|
||||
|
||||
private Integer getNullableExitCode(ResultSet rs) throws SQLException {
|
||||
int exitCode = rs.getInt("EXIT_CODE");
|
||||
return !rs.wasNull() ? exitCode : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -46,36 +46,38 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
private final AtomicLong currentId = new AtomicLong(0L);
|
||||
|
||||
private ConcurrentMap<Long, TaskExecution> taskExecutions;
|
||||
|
||||
private ConcurrentMap<Long, Set<Long>> batchJobAssociations;
|
||||
|
||||
private final AtomicLong currentId = new AtomicLong(0L);
|
||||
|
||||
public MapTaskExecutionDao() {
|
||||
taskExecutions = new ConcurrentHashMap<>();
|
||||
batchJobAssociations = new ConcurrentHashMap<>();
|
||||
this.taskExecutions = new ConcurrentHashMap<>();
|
||||
this.batchJobAssociations = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId) {
|
||||
return createTaskExecution(taskName, startTime, arguments,
|
||||
externalExecutionId, null);
|
||||
public TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId) {
|
||||
return createTaskExecution(taskName, startTime, arguments, externalExecutionId,
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String taskName, Date startTime, List<String> arguments, String externalExecutionId, Long parentExecutionId) {
|
||||
public TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId, Long parentExecutionId) {
|
||||
long taskExecutionId = getNextExecutionId();
|
||||
TaskExecution taskExecution = new TaskExecution(taskExecutionId, null, taskName,
|
||||
startTime, null, null, arguments, null, externalExecutionId, parentExecutionId);
|
||||
taskExecutions.put(taskExecutionId, taskExecution);
|
||||
startTime, null, null, arguments, null, externalExecutionId,
|
||||
parentExecutionId);
|
||||
this.taskExecutions.put(taskExecutionId, taskExecution);
|
||||
return taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution startTaskExecution(long executionId, String taskName, Date startTime, List<String> arguments,
|
||||
String externalExecutionid) {
|
||||
public TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionid) {
|
||||
return startTaskExecution(executionId, taskName, startTime, arguments,
|
||||
externalExecutionid, null);
|
||||
}
|
||||
@@ -84,24 +86,26 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
public TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionid,
|
||||
Long parentExecutionId) {
|
||||
TaskExecution taskExecution= taskExecutions.get(executionId);
|
||||
TaskExecution taskExecution = this.taskExecutions.get(executionId);
|
||||
taskExecution.setTaskName(taskName);
|
||||
taskExecution.setStartTime(startTime);
|
||||
taskExecution.setArguments(arguments);
|
||||
taskExecution.setParentExecutionId(parentExecutionId);
|
||||
if(externalExecutionid != null) {
|
||||
if (externalExecutionid != null) {
|
||||
taskExecution.setExternalExecutionId(externalExecutionid);
|
||||
}
|
||||
return taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeTaskExecution(long executionId, Integer exitCode, Date endTime, String exitMessage, String errorMessage) {
|
||||
if(!this.taskExecutions.containsKey(executionId)) {
|
||||
throw new IllegalStateException("Invalid TaskExecution, ID " + executionId + " not found.");
|
||||
public void completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage, String errorMessage) {
|
||||
if (!this.taskExecutions.containsKey(executionId)) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid TaskExecution, ID " + executionId + " not found.");
|
||||
}
|
||||
|
||||
TaskExecution taskExecution= taskExecutions.get(executionId);
|
||||
TaskExecution taskExecution = this.taskExecutions.get(executionId);
|
||||
taskExecution.setEndTime(endTime);
|
||||
taskExecution.setExitCode(exitCode);
|
||||
taskExecution.setExitMessage(exitMessage);
|
||||
@@ -109,19 +113,20 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeTaskExecution(long executionId, Integer exitCode, Date endTime, String exitMessage) {
|
||||
public void completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage) {
|
||||
completeTaskExecution(executionId, exitCode, endTime, exitMessage, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution getTaskExecution(long executionId) {
|
||||
return taskExecutions.get(executionId);
|
||||
return this.taskExecutions.get(executionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTaskExecutionCountByTaskName(String taskName) {
|
||||
int count = 0;
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName)) {
|
||||
count++;
|
||||
}
|
||||
@@ -132,9 +137,9 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public long getRunningTaskExecutionCountByTaskName(String taskName) {
|
||||
int count = 0;
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName) &&
|
||||
entry.getValue().getEndTime() == null) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName)
|
||||
&& entry.getValue().getEndTime() == null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -144,8 +149,8 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public long getRunningTaskExecutionCount() {
|
||||
long count = 0;
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
if ( entry.getValue().getEndTime() == null) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getEndTime() == null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -154,15 +159,16 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
@Override
|
||||
public long getTaskExecutionCount() {
|
||||
return taskExecutions.size();
|
||||
return this.taskExecutions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable) {
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName,
|
||||
Pageable pageable) {
|
||||
Set<TaskExecution> result = getTaskExecutionTreeSet();
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName) &&
|
||||
entry.getValue().getEndTime() == null) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName)
|
||||
&& entry.getValue().getEndTime() == null) {
|
||||
result.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -171,9 +177,10 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable) {
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName,
|
||||
Pageable pageable) {
|
||||
Set<TaskExecution> filteredSet = getTaskExecutionTreeSet();
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
if (entry.getValue().getTaskName().equals(taskName)) {
|
||||
filteredSet.add(entry.getValue());
|
||||
}
|
||||
@@ -185,7 +192,7 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public List<String> getTaskNames() {
|
||||
Set<String> result = new TreeSet<>();
|
||||
for (Map.Entry<Long, TaskExecution> entry : taskExecutions.entrySet()) {
|
||||
for (Map.Entry<Long, TaskExecution> entry : this.taskExecutions.entrySet()) {
|
||||
result.add(entry.getValue().getTaskName());
|
||||
}
|
||||
return new ArrayList<>(result);
|
||||
@@ -194,17 +201,17 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public Page<TaskExecution> findAll(Pageable pageable) {
|
||||
TreeSet<TaskExecution> sortedSet = getTaskExecutionTreeSet();
|
||||
sortedSet.addAll(taskExecutions.values());
|
||||
sortedSet.addAll(this.taskExecutions.values());
|
||||
List<TaskExecution> result = new ArrayList<>(sortedSet.descendingSet());
|
||||
return getPageFromList(result, pageable, getTaskExecutionCount());
|
||||
}
|
||||
|
||||
public Map<Long, TaskExecution> getTaskExecutions() {
|
||||
return Collections.unmodifiableMap(taskExecutions);
|
||||
return Collections.unmodifiableMap(this.taskExecutions);
|
||||
}
|
||||
|
||||
public long getNextExecutionId(){
|
||||
return currentId.getAndIncrement();
|
||||
public long getNextExecutionId() {
|
||||
return this.currentId.getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,9 +220,10 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
found:
|
||||
|
||||
for (Map.Entry<Long, Set<Long>> association : batchJobAssociations.entrySet()) {
|
||||
for (Map.Entry<Long, Set<Long>> association : this.batchJobAssociations
|
||||
.entrySet()) {
|
||||
for (Long curJobExecutionId : association.getValue()) {
|
||||
if(curJobExecutionId.equals(jobExecutionId)) {
|
||||
if (curJobExecutionId.equals(jobExecutionId)) {
|
||||
taskId = association.getKey();
|
||||
break found;
|
||||
}
|
||||
@@ -227,8 +235,9 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
if(batchJobAssociations.containsKey(taskExecutionId)) {
|
||||
return Collections.unmodifiableSet(batchJobAssociations.get(taskExecutionId));
|
||||
if (this.batchJobAssociations.containsKey(taskExecutionId)) {
|
||||
return Collections
|
||||
.unmodifiableSet(this.batchJobAssociations.get(taskExecutionId));
|
||||
}
|
||||
else {
|
||||
return new TreeSet<>();
|
||||
@@ -236,15 +245,16 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExternalExecutionId(long taskExecutionId, String externalExecutionId) {
|
||||
TaskExecution taskExecution = taskExecutions.get(taskExecutionId);
|
||||
Assert.notNull(taskExecution, "Invalid TaskExecution, ID "
|
||||
+ taskExecutionId + " not found.");
|
||||
public void updateExternalExecutionId(long taskExecutionId,
|
||||
String externalExecutionId) {
|
||||
TaskExecution taskExecution = this.taskExecutions.get(taskExecutionId);
|
||||
Assert.notNull(taskExecution,
|
||||
"Invalid TaskExecution, ID " + taskExecutionId + " not found.");
|
||||
taskExecution.setExternalExecutionId(externalExecutionId);
|
||||
}
|
||||
|
||||
public ConcurrentMap<Long, Set<Long>> getBatchJobAssociations() {
|
||||
return batchJobAssociations;
|
||||
return this.batchJobAssociations;
|
||||
}
|
||||
|
||||
private TreeSet<TaskExecution> getTaskExecutionTreeSet() {
|
||||
@@ -252,19 +262,22 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public int compare(TaskExecution e1, TaskExecution e2) {
|
||||
int result = e1.getStartTime().compareTo(e2.getStartTime());
|
||||
if (result == 0){
|
||||
result = Long.valueOf(e1.getExecutionId()).compareTo(e2.getExecutionId());
|
||||
if (result == 0) {
|
||||
result = Long.valueOf(e1.getExecutionId())
|
||||
.compareTo(e2.getExecutionId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Page getPageFromList(List<TaskExecution> executionList, Pageable pageable, long maxSize){
|
||||
long toIndex = (pageable.getOffset() + pageable.getPageSize() > executionList.size()) ?
|
||||
executionList.size() : pageable.getOffset() + pageable.getPageSize();
|
||||
private Page getPageFromList(List<TaskExecution> executionList, Pageable pageable,
|
||||
long maxSize) {
|
||||
long toIndex = (pageable.getOffset() + pageable.getPageSize() > executionList
|
||||
.size()) ? executionList.size()
|
||||
: pageable.getOffset() + pageable.getPageSize();
|
||||
return new PageImpl<>(
|
||||
executionList.subList((int)pageable.getOffset(), (int)toIndex),
|
||||
executionList.subList((int) pageable.getOffset(), (int) toIndex),
|
||||
pageable, maxSize);
|
||||
}
|
||||
|
||||
@@ -281,29 +294,34 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(taskNamesAsList.size() == taskNames.length,
|
||||
String.format("Task names must not contain any empty elements but %s of %s were empty or null.",
|
||||
taskNames.length - taskNamesAsList.size(), taskNames.length));
|
||||
Assert.isTrue(taskNamesAsList.size() == taskNames.length, String.format(
|
||||
"Task names must not contain any empty elements but %s of %s were empty or null.",
|
||||
taskNames.length - taskNamesAsList.size(), taskNames.length));
|
||||
|
||||
final Map<String, TaskExecution> tempTaskExecutions = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Long, TaskExecution> taskExecutionMapEntry : this.taskExecutions.entrySet()) {
|
||||
if (!taskNamesAsList.contains(taskExecutionMapEntry.getValue().getTaskName())) {
|
||||
for (Map.Entry<Long, TaskExecution> taskExecutionMapEntry : this.taskExecutions
|
||||
.entrySet()) {
|
||||
if (!taskNamesAsList
|
||||
.contains(taskExecutionMapEntry.getValue().getTaskName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final TaskExecution tempTaskExecution = tempTaskExecutions.get(taskExecutionMapEntry.getValue().getTaskName());
|
||||
final TaskExecution tempTaskExecution = tempTaskExecutions
|
||||
.get(taskExecutionMapEntry.getValue().getTaskName());
|
||||
if (tempTaskExecution == null
|
||||
|| tempTaskExecution.getStartTime().before(taskExecutionMapEntry.getValue().getStartTime())
|
||||
|| (
|
||||
tempTaskExecution.getStartTime().equals(taskExecutionMapEntry.getValue().getStartTime())
|
||||
&& tempTaskExecution.getExecutionId() < taskExecutionMapEntry.getValue().getExecutionId()
|
||||
)
|
||||
) {
|
||||
tempTaskExecutions.put(taskExecutionMapEntry.getValue().getTaskName(), taskExecutionMapEntry.getValue());
|
||||
|| tempTaskExecution.getStartTime()
|
||||
.before(taskExecutionMapEntry.getValue().getStartTime())
|
||||
|| (tempTaskExecution.getStartTime()
|
||||
.equals(taskExecutionMapEntry.getValue().getStartTime())
|
||||
&& tempTaskExecution.getExecutionId() < taskExecutionMapEntry
|
||||
.getValue().getExecutionId())) {
|
||||
tempTaskExecutions.put(taskExecutionMapEntry.getValue().getTaskName(),
|
||||
taskExecutionMapEntry.getValue());
|
||||
}
|
||||
}
|
||||
final List<TaskExecution> latestTaskExecutions = new ArrayList<>(tempTaskExecutions.values());
|
||||
final List<TaskExecution> latestTaskExecutions = new ArrayList<>(
|
||||
tempTaskExecutions.values());
|
||||
Collections.sort(latestTaskExecutions, new TaskExecutionComparator());
|
||||
return latestTaskExecutions;
|
||||
}
|
||||
@@ -311,7 +329,8 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
@Override
|
||||
public TaskExecution getLatestTaskExecutionForTaskName(String taskName) {
|
||||
Assert.hasText(taskName, "The task name must not be empty.");
|
||||
final List<TaskExecution> taskExecutions = this.getLatestTaskExecutionsByTaskNames(taskName);
|
||||
final List<TaskExecution> taskExecutions = this
|
||||
.getLatestTaskExecutionsByTaskNames(taskName);
|
||||
if (taskExecutions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -319,20 +338,29 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
return taskExecutions.get(0);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Only expected a single TaskExecution but received " + taskExecutions.size());
|
||||
throw new IllegalStateException(
|
||||
"Only expected a single TaskExecution but received "
|
||||
+ taskExecutions.size());
|
||||
}
|
||||
}
|
||||
|
||||
private static class TaskExecutionComparator implements Comparator<TaskExecution>, Serializable {
|
||||
private static class TaskExecutionComparator
|
||||
implements Comparator<TaskExecution>, Serializable {
|
||||
|
||||
@Override
|
||||
public int compare(TaskExecution firstTaskExecution, TaskExecution secondTaskExecution) {
|
||||
if (firstTaskExecution.getStartTime().equals(secondTaskExecution.getStartTime())) {
|
||||
return Long.compare(firstTaskExecution.getExecutionId(), secondTaskExecution.getExecutionId());
|
||||
public int compare(TaskExecution firstTaskExecution,
|
||||
TaskExecution secondTaskExecution) {
|
||||
if (firstTaskExecution.getStartTime()
|
||||
.equals(secondTaskExecution.getStartTime())) {
|
||||
return Long.compare(firstTaskExecution.getExecutionId(),
|
||||
secondTaskExecution.getExecutionId());
|
||||
}
|
||||
else {
|
||||
return secondTaskExecution.getStartTime().compareTo(firstTaskExecution.getStartTime());
|
||||
return secondTaskExecution.getStartTime()
|
||||
.compareTo(firstTaskExecution.getStartTime());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -36,19 +36,17 @@ public interface TaskExecutionDao {
|
||||
|
||||
/**
|
||||
* Save a new {@link TaskExecution}.
|
||||
*
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param externalExecutionId id assigned to the task by the platform
|
||||
* @return A fully qualified {@link TaskExecution} instance.
|
||||
*/
|
||||
TaskExecution createTaskExecution( String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId);
|
||||
TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId);
|
||||
|
||||
/**
|
||||
* Save a new {@link TaskExecution}.
|
||||
*
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
@@ -57,65 +55,62 @@ public interface TaskExecutionDao {
|
||||
* @return A fully qualified {@link TaskExecution} instance.
|
||||
* @since 1.2.0
|
||||
*/
|
||||
TaskExecution createTaskExecution( String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId);
|
||||
TaskExecution createTaskExecution(String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId, Long parentExecutionId);
|
||||
|
||||
/**
|
||||
* Update and existing {@link TaskExecution} to mark it as started.
|
||||
*
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param externalExecutionId id assigned to the task by the platform
|
||||
* @return A TaskExecution containing the information available at task execution start.
|
||||
* @return A TaskExecution containing the information available at task execution
|
||||
* start.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId);
|
||||
TaskExecution startTaskExecution(long executionId, String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId);
|
||||
|
||||
/**
|
||||
* Update and existing {@link TaskExecution} to mark it as started.
|
||||
*
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param arguments list of key/value pairs that configure the task.
|
||||
* @param externalExecutionId id assigned to the task by the platform
|
||||
* @param parentExecutionId the parent task execution id.
|
||||
* @return A TaskExecution containing the information available at task execution start.
|
||||
* @return A TaskExecution containing the information available at task execution
|
||||
* start.
|
||||
* @since 1.2.0
|
||||
*/
|
||||
TaskExecution startTaskExecution(long executionId, String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId);
|
||||
TaskExecution startTaskExecution(long executionId, String taskName, Date startTime,
|
||||
List<String> arguments, String externalExecutionId, Long parentExecutionId);
|
||||
|
||||
/**
|
||||
* Update and existing {@link TaskExecution} to mark it as completed.
|
||||
*
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param exitCode the status of the task upon completion.
|
||||
* @param endTime the time the task completed.
|
||||
* @param exitMessage the message assigned to the task upon completion.
|
||||
* @param errorMessage error information available upon failure of a task.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void completeTaskExecution(long executionId, Integer exitCode, Date endTime, String exitMessage, String errorMessage);
|
||||
void completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage, String errorMessage);
|
||||
|
||||
/**
|
||||
* Update and existing {@link TaskExecution}.
|
||||
*
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param executionId the id of the taskExecution to be updated.
|
||||
* @param exitCode the status of the task upon completion.
|
||||
* @param endTime the time the task completed.
|
||||
* @param exitMessage the message assigned to the task upon completion.
|
||||
*/
|
||||
void completeTaskExecution(long executionId, Integer exitCode, Date endTime, String exitMessage);
|
||||
void completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage);
|
||||
|
||||
/**
|
||||
* Retrieves a task execution from the task repository.
|
||||
*
|
||||
* @param executionId the id associated with the task execution.
|
||||
* @return a fully qualified TaskExecution instance.
|
||||
*/
|
||||
@@ -123,16 +118,14 @@ public interface TaskExecutionDao {
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions for a taskName.
|
||||
*
|
||||
* @param taskName the name of the task to search for in the repository.
|
||||
* @return current number of task executions for the taskName.
|
||||
*/
|
||||
long getTaskExecutionCountByTaskName(String taskName);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions for a taskName and with an endTime of null.
|
||||
*
|
||||
* Retrieves current number of task executions for a taskName and with an endTime of
|
||||
* null.
|
||||
* @param taskName the name of the task to search for in the repository.
|
||||
* @return current number of task executions for the taskName.
|
||||
*/
|
||||
@@ -140,15 +133,12 @@ public interface TaskExecutionDao {
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions with an endTime of null.
|
||||
*
|
||||
* @return current number of task executions.
|
||||
*/
|
||||
long getRunningTaskExecutionCount();
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions.
|
||||
*
|
||||
* @return current number of task executions.
|
||||
*/
|
||||
long getTaskExecutionCount();
|
||||
@@ -159,7 +149,7 @@ public interface TaskExecutionDao {
|
||||
* @param pageable the constraints for the search.
|
||||
* @return set of running task executions.
|
||||
*/
|
||||
Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable);
|
||||
Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieves a subset of task executions by task name, start location and size.
|
||||
@@ -172,7 +162,6 @@ public interface TaskExecutionDao {
|
||||
|
||||
/**
|
||||
* Retrieves a sorted list of distinct task names for the task executions.
|
||||
*
|
||||
* @return a list of distinct task names from the task repository..
|
||||
*/
|
||||
List<String> getTaskNames();
|
||||
@@ -193,8 +182,7 @@ public interface TaskExecutionDao {
|
||||
|
||||
/**
|
||||
* Returns the id of the TaskExecution that the requested Spring Batch job execution
|
||||
* was executed within the context of. Returns null if non were found.
|
||||
*
|
||||
* was executed within the context of. Returns null if non were found.
|
||||
* @param jobExecutionId the id of the JobExecution
|
||||
* @return the id of the {@link TaskExecution}
|
||||
*/
|
||||
@@ -203,7 +191,8 @@ public interface TaskExecutionDao {
|
||||
/**
|
||||
* Returns the job execution ids associated with a task execution id.
|
||||
* @param taskExecutionId id of the {@link TaskExecution}
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the task.
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the
|
||||
* task.
|
||||
*/
|
||||
Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId);
|
||||
|
||||
@@ -212,35 +201,35 @@ public interface TaskExecutionDao {
|
||||
* @param taskExecutionId the execution id for the task to be updated.
|
||||
* @param externalExecutionId the new externalExecutionId.
|
||||
*/
|
||||
void updateExternalExecutionId(long taskExecutionId,
|
||||
String externalExecutionId);
|
||||
void updateExternalExecutionId(long taskExecutionId, String externalExecutionId);
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of the latest {@link TaskExecution} for 1 or more task names.
|
||||
* Returns a {@link List} of the latest {@link TaskExecution} for 1 or more task
|
||||
* names.
|
||||
*
|
||||
* Latest is defined by the most recent start time. A {@link TaskExecution} does not have to be finished
|
||||
* (The results may including pending {@link TaskExecution}s).
|
||||
* Latest is defined by the most recent start time. A {@link TaskExecution} does not
|
||||
* have to be finished (The results may including pending {@link TaskExecution}s).
|
||||
*
|
||||
* It is theoretically possible that a {@link TaskExecution} with the same name to have more than 1
|
||||
* {@link TaskExecution} for the exact same start time. In that case the {@link TaskExecution} with the
|
||||
* highest Task Execution ID is returned.
|
||||
*
|
||||
* This method will not consider end times in its calculations. Thus, when a task execution {@code A} starts
|
||||
* after task execution {@code B} but finishes BEFORE task execution {@code A}, then task execution {@code B}
|
||||
* is being returned.
|
||||
* It is theoretically possible that a {@link TaskExecution} with the same name to
|
||||
* have more than 1 {@link TaskExecution} for the exact same start time. In that case
|
||||
* the {@link TaskExecution} with the highest Task Execution ID is returned.
|
||||
*
|
||||
* This method will not consider end times in its calculations. Thus, when a task
|
||||
* execution {@code A} starts after task execution {@code B} but finishes BEFORE task
|
||||
* execution {@code A}, then task execution {@code B} is being returned.
|
||||
* @param taskNames At least 1 task name must be provided
|
||||
* @return List of TaskExecutions. May be empty but never null.
|
||||
*/
|
||||
List<TaskExecution> getLatestTaskExecutionsByTaskNames(String... taskNames);
|
||||
|
||||
/**
|
||||
* Returns the latest task execution for a given task name. Will ultimately apply the same algorithm underneath
|
||||
* as {@link #getLatestTaskExecutionsByTaskNames(String...)} but will only return a single result.
|
||||
*
|
||||
* Returns the latest task execution for a given task name. Will ultimately apply the
|
||||
* same algorithm underneath as {@link #getLatestTaskExecutionsByTaskNames(String...)}
|
||||
* but will only return a single result.
|
||||
* @param taskName Must not be null or empty
|
||||
* @return The latest Task Execution or null
|
||||
* @see #getLatestTaskExecutionsByTaskNames(String...)
|
||||
*/
|
||||
TaskExecution getLatestTaskExecutionForTaskName(String taskName);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface DAO and default implementations for storing and retrieving data for tasks
|
||||
* from a repository.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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,35 +25,33 @@ import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* Interface defining the functionality to be provided for generating paging queries.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public interface PagingQueryProvider {
|
||||
|
||||
/**
|
||||
* Initialize the query provider using the provided {@link DataSource} if necessary.
|
||||
*
|
||||
* @param dataSource DataSource to use for any initialization
|
||||
* @throws Exception throws {@link Exception} if query provider initialize fails.
|
||||
*/
|
||||
void init(DataSource dataSource) throws Exception;
|
||||
|
||||
/**
|
||||
* The number of parameters that are declared in the query
|
||||
* The number of parameters that are declared in the query.
|
||||
* @return number of parameters
|
||||
*/
|
||||
int getParameterCount();
|
||||
|
||||
/**
|
||||
* Indicate whether the generated queries use named parameter syntax.
|
||||
*
|
||||
* @return true if named parameter syntax is used
|
||||
*/
|
||||
boolean isUsingNamedParameters();
|
||||
|
||||
/**
|
||||
* The sort keys. A Map of the columns that make up the key and a Boolean indicating ascending or descending
|
||||
* (ascending = true).
|
||||
*
|
||||
* The sort keys. A Map of the columns that make up the key and a Boolean indicating
|
||||
* ascending or descending (ascending = true).
|
||||
* @return the sort keys used to order the query
|
||||
*/
|
||||
Map<String, Order> getSortKeys();
|
||||
@@ -61,9 +59,9 @@ public interface PagingQueryProvider {
|
||||
/**
|
||||
*
|
||||
* Generate the query that will provide the jump to item query.
|
||||
*
|
||||
* @param pageable the coordinates to pull the next page from the datasource
|
||||
* @return the generated query
|
||||
*/
|
||||
String getPageQuery(Pageable pageable);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -31,15 +31,15 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract SQL Paging Query Provider to serve as a base class for all provided
|
||||
* SQL paging query providers.
|
||||
* Abstract SQL Paging Query Provider to serve as a base class for all provided SQL paging
|
||||
* query providers.
|
||||
*
|
||||
* Any implementation must provide a way to specify the select clause, from
|
||||
* clause and optionally a where clause. It is recommended that there should be an index for
|
||||
* the sort key to provide better performance.
|
||||
* Any implementation must provide a way to specify the select clause, from clause and
|
||||
* optionally a where clause. It is recommended that there should be an index for the sort
|
||||
* key to provide better performance.
|
||||
*
|
||||
* Provides properties and preparation for the mandatory "selectClause" and
|
||||
* "fromClause" as well as for the optional "whereClause".
|
||||
* Provides properties and preparation for the mandatory "selectClause" and "fromClause"
|
||||
* as well as for the optional "whereClause".
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@@ -51,12 +51,19 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
|
||||
private String whereClause;
|
||||
|
||||
private Map<String, Order> sortKeys = new LinkedHashMap<String, Order>();
|
||||
private Map<String, Order> sortKeys = new LinkedHashMap<>();
|
||||
|
||||
private int parameterCount;
|
||||
|
||||
private boolean usingNamedParameters;
|
||||
|
||||
/**
|
||||
* @return SQL SELECT clause part of SQL query string
|
||||
*/
|
||||
protected String getSelectClause() {
|
||||
return this.selectClause;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selectClause SELECT clause part of SQL query string
|
||||
*/
|
||||
@@ -65,11 +72,10 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL SELECT clause part of SQL query string
|
||||
* @return SQL FROM clause part of SQL query string
|
||||
*/
|
||||
protected String getSelectClause() {
|
||||
return selectClause;
|
||||
protected String getFromClause() {
|
||||
return this.fromClause;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,11 +86,10 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL FROM clause part of SQL query string
|
||||
* @return SQL WHERE clause part of SQL query string
|
||||
*/
|
||||
protected String getFromClause() {
|
||||
return fromClause;
|
||||
protected String getWhereClause() {
|
||||
return this.whereClause;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,11 +105,13 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SQL WHERE clause part of SQL query string
|
||||
* A Map<String, Order> of sort columns as the key and {@link Order} for
|
||||
* ascending/descending.
|
||||
* @return sortKey key to use to sort and limit page content
|
||||
*/
|
||||
protected String getWhereClause() {
|
||||
return whereClause;
|
||||
@Override
|
||||
public Map<String, Order> getSortKeys() {
|
||||
return this.sortKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,56 +121,51 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi
|
||||
this.sortKeys = sortKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Map<String, Order> of sort columns as the key and {@link Order} for ascending/descending.
|
||||
*
|
||||
* @return sortKey key to use to sort and limit page content
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Order> getSortKeys() {
|
||||
return sortKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameterCount() {
|
||||
return parameterCount;
|
||||
return this.parameterCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsingNamedParameters() {
|
||||
return usingNamedParameters;
|
||||
return this.usingNamedParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(DataSource dataSource) throws Exception {
|
||||
Assert.notNull(dataSource, "DataSource must not be null");
|
||||
Assert.hasLength(selectClause, "selectClause must be specified");
|
||||
Assert.hasLength(fromClause, "fromClause must be specified");
|
||||
Assert.notEmpty(sortKeys, "sortKey must be specified");
|
||||
Assert.hasLength(this.selectClause, "selectClause must be specified");
|
||||
Assert.hasLength(this.fromClause, "fromClause must be specified");
|
||||
Assert.notEmpty(this.sortKeys, "sortKey must be specified");
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(selectClause);
|
||||
sql.append(" FROM ").append(fromClause);
|
||||
if (whereClause != null) {
|
||||
sql.append(" WHERE ").append(whereClause);
|
||||
sql.append("SELECT ").append(this.selectClause);
|
||||
sql.append(" FROM ").append(this.fromClause);
|
||||
if (this.whereClause != null) {
|
||||
sql.append(" WHERE ").append(this.whereClause);
|
||||
}
|
||||
List<String> namedParameters = new ArrayList<String>();
|
||||
parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql.toString(), namedParameters);
|
||||
List<String> namedParameters = new ArrayList<>();
|
||||
this.parameterCount = JdbcParameterUtils
|
||||
.countParameterPlaceholders(sql.toString(), namedParameters);
|
||||
if (namedParameters.size() > 0) {
|
||||
if (parameterCount != namedParameters.size()) {
|
||||
if (this.parameterCount != namedParameters.size()) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"You can't use both named parameters and classic \"?\" placeholders: " + sql);
|
||||
"You can't use both named parameters and classic \"?\" placeholders: "
|
||||
+ sql);
|
||||
}
|
||||
usingNamedParameters = true;
|
||||
this.usingNamedParameters = true;
|
||||
}
|
||||
}
|
||||
|
||||
private String removeKeyWord(String keyWord, String clause) {
|
||||
String temp = clause.trim();
|
||||
String keyWordString = keyWord + " ";
|
||||
if (temp.toLowerCase().startsWith(keyWordString) && temp.length() > keyWordString.length()) {
|
||||
if (temp.toLowerCase().startsWith(keyWordString)
|
||||
&& temp.length() > keyWordString.length()) {
|
||||
return temp.substring(keyWordString.length());
|
||||
}
|
||||
else {
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -19,9 +19,10 @@ package org.springframework.cloud.task.repository.database.support;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* IBM DB2 implementation of a {@link org.springframework.cloud.task.repository.database.PagingQueryProvider} using database
|
||||
* specific features.
|
||||
*
|
||||
* IBM DB2 implementation of a
|
||||
* {@link org.springframework.cloud.task.repository.database.PagingQueryProvider} using
|
||||
* database specific features.
|
||||
*
|
||||
* @author Thomas Schuettel
|
||||
*/
|
||||
public class Db2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
@@ -30,15 +31,18 @@ public class Db2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
long offset = pageable.getOffset() + 1;
|
||||
return generateRowNumSqlQueryWithNesting(getSelectClause(), false,
|
||||
"TMP_ROW_NUM BETWEEN " + offset + " AND " + (offset + pageable.getPageSize()));
|
||||
"TMP_ROW_NUM BETWEEN " + offset + " AND "
|
||||
+ (offset + pageable.getPageSize()));
|
||||
}
|
||||
|
||||
private String generateRowNumSqlQueryWithNesting(String selectClause, boolean remainingPageQuery,
|
||||
String rowNumClause) {
|
||||
private String generateRowNumSqlQueryWithNesting(String selectClause,
|
||||
boolean remainingPageQuery, String rowNumClause) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ").append(selectClause).append(", ")
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ")
|
||||
.append(selectClause).append(", ")
|
||||
.append("ROW_NUMBER() OVER() as TMP_ROW_NUM");
|
||||
sql.append(" FROM (SELECT ").append(selectClause).append(" FROM ").append(this.getFromClause());
|
||||
sql.append(" FROM (SELECT ").append(selectClause).append(" FROM ")
|
||||
.append(this.getFromClause());
|
||||
SqlPagingQueryUtils.buildWhereClause(this, remainingPageQuery, sql);
|
||||
sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this));
|
||||
sql.append(")) WHERE ").append(rowNumClause);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -29,8 +29,8 @@ public class H2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
String topClause = new StringBuilder().append("LIMIT ")
|
||||
.append(pageable.getOffset()).append(" ")
|
||||
.append(pageable.getPageSize()).toString();
|
||||
.append(pageable.getOffset()).append(" ").append(pageable.getPageSize())
|
||||
.toString();
|
||||
return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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,7 +20,8 @@ import org.springframework.cloud.task.repository.database.PagingQueryProvider;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* HSQLDB implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
* HSQLDB implementation of a {@link PagingQueryProvider} using database specific
|
||||
* features.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@@ -29,8 +30,8 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
String topClause = new StringBuilder().append("LIMIT ")
|
||||
.append(pageable.getOffset()).append(" ")
|
||||
.append(pageable.getPageSize()).toString();
|
||||
.append(pageable.getOffset()).append(" ").append(pageable.getPageSize())
|
||||
.toString();
|
||||
return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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,11 +25,12 @@ import org.springframework.data.domain.Pageable;
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
String topClause = new StringBuilder().append("LIMIT ")
|
||||
.append(pageable.getOffset()).append(", ")
|
||||
.append(pageable.getPageSize()).toString();
|
||||
.append(pageable.getOffset()).append(", ").append(pageable.getPageSize())
|
||||
.toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, topClause);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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,7 +20,8 @@ import org.springframework.cloud.task.repository.database.PagingQueryProvider;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* Oracle implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
* Oracle implementation of a {@link PagingQueryProvider} using database specific
|
||||
* features.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@@ -28,22 +29,24 @@ public class OraclePagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
long offset = pageable.getOffset()+1;
|
||||
return generateRowNumSqlQueryWithNesting(getSelectClause(), false, "TMP_ROW_NUM >= "
|
||||
+ offset + " AND TMP_ROW_NUM < " + (offset+pageable.getPageSize()));
|
||||
long offset = pageable.getOffset() + 1;
|
||||
return generateRowNumSqlQueryWithNesting(getSelectClause(), false,
|
||||
"TMP_ROW_NUM >= " + offset + " AND TMP_ROW_NUM < "
|
||||
+ (offset + pageable.getPageSize()));
|
||||
}
|
||||
|
||||
private String generateRowNumSqlQueryWithNesting(String selectClause,
|
||||
boolean remainingPageQuery,
|
||||
String rowNumClause) {
|
||||
boolean remainingPageQuery, String rowNumClause) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ").append(selectClause)
|
||||
.append(", ").append("ROWNUM as TMP_ROW_NUM");
|
||||
sql.append(" FROM (SELECT ").append(selectClause).append(" FROM ").append(this.getFromClause());
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ")
|
||||
.append(selectClause).append(", ").append("ROWNUM as TMP_ROW_NUM");
|
||||
sql.append(" FROM (SELECT ").append(selectClause).append(" FROM ")
|
||||
.append(this.getFromClause());
|
||||
SqlPagingQueryUtils.buildWhereClause(this, remainingPageQuery, sql);
|
||||
sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this));
|
||||
sql.append(")) WHERE ").append(rowNumClause);
|
||||
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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,7 +20,8 @@ import org.springframework.cloud.task.repository.database.PagingQueryProvider;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* Postgres implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
* Postgres implementation of a {@link PagingQueryProvider} using database specific
|
||||
* features.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@@ -28,9 +29,10 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider
|
||||
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
String limitClause = new StringBuilder().append("LIMIT ").
|
||||
append(pageable.getPageSize()).append(" OFFSET ").
|
||||
append(pageable.getOffset()).toString();
|
||||
String limitClause = new StringBuilder().append("LIMIT ")
|
||||
.append(pageable.getPageSize()).append(" OFFSET ")
|
||||
.append(pageable.getOffset()).toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -16,17 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.task.repository.database.support;
|
||||
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2AS400;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2VSE;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2ZOS;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.HSQL;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.H2;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.MYSQL;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.ORACLE;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.POSTGRES;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.SQLSERVER;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -40,14 +29,26 @@ import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2AS400;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2VSE;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.DB2ZOS;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.H2;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.HSQL;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.MYSQL;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.ORACLE;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.POSTGRES;
|
||||
import static org.springframework.cloud.task.repository.support.DatabaseType.SQLSERVER;
|
||||
|
||||
/**
|
||||
* Factory bean for {@link PagingQueryProvider} interface. The database type
|
||||
* will be determined from the data source if not provided explicitly. Valid
|
||||
* types are given by the {@link DatabaseType} enum.
|
||||
* Factory bean for {@link PagingQueryProvider} interface. The database type will be
|
||||
* determined from the data source if not provided explicitly. Valid types are given by
|
||||
* the {@link DatabaseType} enum.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class SqlPagingQueryProviderFactoryBean implements FactoryBean<PagingQueryProvider> {
|
||||
public class SqlPagingQueryProviderFactoryBean
|
||||
implements FactoryBean<PagingQueryProvider> {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
@@ -61,20 +62,19 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean<PagingQuer
|
||||
|
||||
private Map<String, Order> sortKeys;
|
||||
|
||||
private Map<DatabaseType, AbstractSqlPagingQueryProvider> providers = new HashMap<DatabaseType, AbstractSqlPagingQueryProvider>();
|
||||
|
||||
private Map<DatabaseType, AbstractSqlPagingQueryProvider> providers = new HashMap<>();
|
||||
|
||||
{
|
||||
providers.put(HSQL, new HsqlPagingQueryProvider());
|
||||
providers.put(H2, new H2PagingQueryProvider());
|
||||
providers.put(MYSQL, new MySqlPagingQueryProvider());
|
||||
providers.put(POSTGRES, new PostgresPagingQueryProvider());
|
||||
providers.put(ORACLE, new OraclePagingQueryProvider());
|
||||
providers.put(SQLSERVER, new SqlServerPagingQueryProvider());
|
||||
providers.put(DB2, new Db2PagingQueryProvider());
|
||||
providers.put(DB2VSE, new Db2PagingQueryProvider());
|
||||
providers.put(DB2ZOS, new Db2PagingQueryProvider());
|
||||
providers.put(DB2AS400, new Db2PagingQueryProvider());
|
||||
this.providers.put(HSQL, new HsqlPagingQueryProvider());
|
||||
this.providers.put(H2, new H2PagingQueryProvider());
|
||||
this.providers.put(MYSQL, new MySqlPagingQueryProvider());
|
||||
this.providers.put(POSTGRES, new PostgresPagingQueryProvider());
|
||||
this.providers.put(ORACLE, new OraclePagingQueryProvider());
|
||||
this.providers.put(SQLSERVER, new SqlServerPagingQueryProvider());
|
||||
this.providers.put(DB2, new Db2PagingQueryProvider());
|
||||
this.providers.put(DB2VSE, new Db2PagingQueryProvider());
|
||||
this.providers.put(DB2ZOS, new Db2PagingQueryProvider());
|
||||
this.providers.put(DB2AS400, new Db2PagingQueryProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,8 +124,8 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean<PagingQuer
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link PagingQueryProvider} instance using the provided properties
|
||||
* and appropriate for the given database type.
|
||||
* Get a {@link PagingQueryProvider} instance using the provided properties and
|
||||
* appropriate for the given database type.
|
||||
*
|
||||
* @see FactoryBean#getObject()
|
||||
*/
|
||||
@@ -134,24 +134,28 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean<PagingQuer
|
||||
|
||||
DatabaseType type;
|
||||
try {
|
||||
type = databaseType != null ? DatabaseType.valueOf(databaseType.toUpperCase()) : DatabaseType
|
||||
.fromMetaData(dataSource);
|
||||
type = this.databaseType != null
|
||||
? DatabaseType.valueOf(this.databaseType.toUpperCase())
|
||||
: DatabaseType.fromMetaData(this.dataSource);
|
||||
}
|
||||
catch (MetaDataAccessException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not inspect meta data for database type. You have to supply it explicitly.", e);
|
||||
"Could not inspect meta data for database type. You have to supply it explicitly.",
|
||||
e);
|
||||
}
|
||||
|
||||
AbstractSqlPagingQueryProvider provider = providers.get(type);
|
||||
Assert.state(provider != null, "Should not happen: missing PagingQueryProvider for DatabaseType=" + type);
|
||||
AbstractSqlPagingQueryProvider provider = this.providers.get(type);
|
||||
Assert.state(provider != null,
|
||||
"Should not happen: missing PagingQueryProvider for DatabaseType="
|
||||
+ type);
|
||||
|
||||
provider.setFromClause(fromClause);
|
||||
provider.setWhereClause(whereClause);
|
||||
provider.setSortKeys(sortKeys);
|
||||
if (StringUtils.hasText(selectClause)) {
|
||||
provider.setSelectClause(selectClause);
|
||||
provider.setFromClause(this.fromClause);
|
||||
provider.setWhereClause(this.whereClause);
|
||||
provider.setSortKeys(this.sortKeys);
|
||||
if (StringUtils.hasText(this.selectClause)) {
|
||||
provider.setSelectClause(this.selectClause);
|
||||
}
|
||||
provider.init(dataSource);
|
||||
provider.init(this.dataSource);
|
||||
|
||||
return provider;
|
||||
|
||||
@@ -176,4 +180,5 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean<PagingQuer
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -21,28 +21,29 @@ import java.util.Map;
|
||||
import org.springframework.batch.item.database.Order;
|
||||
|
||||
/**
|
||||
* Utility class that generates the actual SQL statements used by query
|
||||
* providers.
|
||||
* Utility class that generates the actual SQL statements used by query providers.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class SqlPagingQueryUtils {
|
||||
public final class SqlPagingQueryUtils {
|
||||
|
||||
private SqlPagingQueryUtils(){}
|
||||
private SqlPagingQueryUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SQL query string using a LIMIT clause
|
||||
*
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
|
||||
* implementation specifics
|
||||
* Generate SQL query string using a LIMIT clause.
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation
|
||||
* specifics
|
||||
* @param limitClause the implementation specific top clause to be used
|
||||
* @return the generated query
|
||||
*/
|
||||
public static String generateLimitJumpToQuery(AbstractSqlPagingQueryProvider provider, String limitClause) {
|
||||
public static String generateLimitJumpToQuery(AbstractSqlPagingQueryProvider provider,
|
||||
String limitClause) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(provider.getSelectClause());
|
||||
sql.append(" FROM ").append(provider.getFromClause());
|
||||
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
|
||||
sql.append(provider.getWhereClause() == null ? ""
|
||||
: " WHERE " + provider.getWhereClause());
|
||||
sql.append(" ORDER BY ").append(buildSortClause(provider));
|
||||
sql.append(" ").append(limitClause);
|
||||
|
||||
@@ -50,18 +51,20 @@ public class SqlPagingQueryUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SQL query string using a TOP clause
|
||||
*
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
|
||||
* implementation specifics
|
||||
* Generate SQL query string using a TOP clause.
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation
|
||||
* specifics
|
||||
* @param topClause the implementation specific top clause to be used
|
||||
* @return the generated query
|
||||
*/
|
||||
public static String generateTopJumpToQuery(AbstractSqlPagingQueryProvider provider, String topClause) {
|
||||
public static String generateTopJumpToQuery(AbstractSqlPagingQueryProvider provider,
|
||||
String topClause) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(topClause).append(" ").append(provider.getSelectClause());
|
||||
sql.append("SELECT ").append(topClause).append(" ")
|
||||
.append(provider.getSelectClause());
|
||||
sql.append(" FROM ").append(provider.getFromClause());
|
||||
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
|
||||
sql.append(provider.getWhereClause() == null ? ""
|
||||
: " WHERE " + provider.getWhereClause());
|
||||
sql.append(" ORDER BY ").append(buildSortClause(provider));
|
||||
|
||||
return sql.toString();
|
||||
@@ -69,13 +72,12 @@ public class SqlPagingQueryUtils {
|
||||
|
||||
/**
|
||||
* Generates WHERE clause for queries that require sub selects.
|
||||
*
|
||||
* @param provider the paging query provider that will provide the base where clause
|
||||
* @param remainingPageQuery if true assumes more will be appended to where clause
|
||||
* @param sql the sql statement to be appended.
|
||||
*/
|
||||
public static void buildWhereClause( AbstractSqlPagingQueryProvider provider,
|
||||
boolean remainingPageQuery, StringBuilder sql) {
|
||||
public static void buildWhereClause(AbstractSqlPagingQueryProvider provider,
|
||||
boolean remainingPageQuery, StringBuilder sql) {
|
||||
if (remainingPageQuery) {
|
||||
sql.append(" WHERE ");
|
||||
if (provider.getWhereClause() != null) {
|
||||
@@ -85,15 +87,15 @@ public class SqlPagingQueryUtils {
|
||||
}
|
||||
}
|
||||
else {
|
||||
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
|
||||
sql.append(provider.getWhereClause() == null ? ""
|
||||
: " WHERE " + provider.getWhereClause());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates ORDER BY attributes based on the sort keys.
|
||||
*
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
|
||||
* implementation specifics
|
||||
* @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation
|
||||
* specifics
|
||||
* @return a String that can be appended to an ORDER BY clause.
|
||||
*/
|
||||
public static String buildSortClause(AbstractSqlPagingQueryProvider provider) {
|
||||
@@ -102,7 +104,6 @@ public class SqlPagingQueryUtils {
|
||||
|
||||
/**
|
||||
* Generates ORDER BY attributes based on the sort keys.
|
||||
*
|
||||
* @param sortKeys generates order by clause from map
|
||||
* @return a String that can be appended to an ORDER BY clause.
|
||||
*/
|
||||
@@ -117,7 +118,7 @@ public class SqlPagingQueryUtils {
|
||||
|
||||
builder.append(sortKey.getKey());
|
||||
|
||||
if(sortKey.getValue() != null && sortKey.getValue() == Order.DESCENDING) {
|
||||
if (sortKey.getValue() != null && sortKey.getValue() == Order.DESCENDING) {
|
||||
builder.append(" DESC");
|
||||
}
|
||||
else {
|
||||
@@ -127,4 +128,5 @@ public class SqlPagingQueryUtils {
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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,31 +20,33 @@ import org.springframework.cloud.task.repository.database.PagingQueryProvider;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
/**
|
||||
* Sql Server implementation of a {@link PagingQueryProvider} using database specific features.
|
||||
* Sql Server implementation of a {@link PagingQueryProvider} using database specific
|
||||
* features.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class SqlServerPagingQueryProvider extends AbstractSqlPagingQueryProvider{
|
||||
public class SqlServerPagingQueryProvider extends AbstractSqlPagingQueryProvider {
|
||||
|
||||
@Override
|
||||
public String getPageQuery(Pageable pageable) {
|
||||
long offset = pageable.getOffset()+1;
|
||||
return generateRowNumSqlQueryWithNesting(getSelectClause(), false, "TMP_ROW_NUM >= "
|
||||
+ offset + " AND TMP_ROW_NUM < " + (offset+pageable.getPageSize()));
|
||||
long offset = pageable.getOffset() + 1;
|
||||
return generateRowNumSqlQueryWithNesting(getSelectClause(), false,
|
||||
"TMP_ROW_NUM >= " + offset + " AND TMP_ROW_NUM < "
|
||||
+ (offset + pageable.getPageSize()));
|
||||
}
|
||||
|
||||
private String generateRowNumSqlQueryWithNesting(String selectClause,
|
||||
boolean remainingPageQuery,
|
||||
String rowNumClause) {
|
||||
boolean remainingPageQuery, String rowNumClause) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ").append(selectClause)
|
||||
.append(", ").append("ROW_NUMBER() OVER (ORDER BY ")
|
||||
sql.append("SELECT ").append(selectClause).append(" FROM (SELECT ")
|
||||
.append(selectClause).append(", ").append("ROW_NUMBER() OVER (ORDER BY ")
|
||||
.append(SqlPagingQueryUtils.buildSortClause(this))
|
||||
.append(") AS TMP_ROW_NUM ")
|
||||
.append(" FROM ").append(getFromClause());
|
||||
.append(") AS TMP_ROW_NUM ").append(" FROM ").append(getFromClause());
|
||||
SqlPagingQueryUtils.buildWhereClause(this, remainingPageQuery, sql);
|
||||
sql.append(") TASK_EXECUTION_PAGE ");
|
||||
sql.append(" WHERE ").append(rowNumClause);
|
||||
sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this));
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2019 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,63 +25,107 @@ import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Enum representing a database type, such as DB2 or oracle. The type also
|
||||
* contains a product name, which is expected to be the same as the product name
|
||||
* provided by the database driver's metadata.
|
||||
* Enum representing a database type, such as DB2 or oracle. The type also contains a
|
||||
* product name, which is expected to be the same as the product name provided by the
|
||||
* database driver's metadata.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public enum DatabaseType {
|
||||
|
||||
/**
|
||||
* HSQL DB.
|
||||
*/
|
||||
HSQL("HSQL Database Engine"),
|
||||
|
||||
/**
|
||||
* H2 DB.
|
||||
*/
|
||||
H2("H2"),
|
||||
|
||||
/**
|
||||
* Oracle DB.
|
||||
*/
|
||||
ORACLE("Oracle"),
|
||||
|
||||
/**
|
||||
* MySQL DB.
|
||||
*/
|
||||
MYSQL("MySQL"),
|
||||
|
||||
/**
|
||||
* PostgreSQL DB.
|
||||
*/
|
||||
POSTGRES("PostgreSQL"),
|
||||
|
||||
/**
|
||||
* Microsoft SQL Server DB.
|
||||
*/
|
||||
SQLSERVER("Microsoft SQL Server"),
|
||||
|
||||
/**
|
||||
* DB2 DB.
|
||||
*/
|
||||
DB2("DB2"),
|
||||
|
||||
/**
|
||||
* DB2VSE DB.
|
||||
*/
|
||||
DB2VSE("DB2VSE"),
|
||||
|
||||
/**
|
||||
* DB2ZOS DB.
|
||||
*/
|
||||
DB2ZOS("DB2ZOS"),
|
||||
|
||||
/**
|
||||
* DB2AS400 DB.
|
||||
*/
|
||||
DB2AS400("DB2AS400");
|
||||
|
||||
private static final Map<String, DatabaseType> dbNameMap;
|
||||
|
||||
static {
|
||||
dbNameMap = new HashMap<>();
|
||||
for (DatabaseType type : values()) {
|
||||
dbNameMap.put(type.getProductName(), type);
|
||||
}
|
||||
}
|
||||
|
||||
private final String productName;
|
||||
|
||||
DatabaseType(String productName) {
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
static{
|
||||
dbNameMap = new HashMap<String, DatabaseType>();
|
||||
for(DatabaseType type: values()){
|
||||
dbNameMap.put(type.getProductName(), type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that pulls a database product name from the DataSource's metadata.
|
||||
*
|
||||
* Convenience method that pulls a database product name from the DataSource's
|
||||
* metadata.
|
||||
* @param dataSource the datasource used to extact metadata.
|
||||
* @return DatabaseType The database type associated with the datasource.
|
||||
* @throws MetaDataAccessException thrown if failure occurs on metadata lookup.
|
||||
*/
|
||||
public static DatabaseType fromMetaData(DataSource dataSource) throws MetaDataAccessException {
|
||||
String databaseProductName =
|
||||
JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString();
|
||||
if (StringUtils.hasText(databaseProductName) && !databaseProductName.equals("DB2/Linux") && databaseProductName.startsWith("DB2")) {
|
||||
String databaseProductVersion =
|
||||
JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductVersion").toString();
|
||||
public static DatabaseType fromMetaData(DataSource dataSource)
|
||||
throws MetaDataAccessException {
|
||||
String databaseProductName = JdbcUtils
|
||||
.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString();
|
||||
if (StringUtils.hasText(databaseProductName)
|
||||
&& !databaseProductName.equals("DB2/Linux")
|
||||
&& databaseProductName.startsWith("DB2")) {
|
||||
String databaseProductVersion = JdbcUtils
|
||||
.extractDatabaseMetaData(dataSource, "getDatabaseProductVersion")
|
||||
.toString();
|
||||
if (databaseProductVersion.startsWith("ARI")) {
|
||||
databaseProductName = "DB2VSE";
|
||||
}
|
||||
else if (databaseProductVersion.startsWith("DSN")) {
|
||||
databaseProductName = "DB2ZOS";
|
||||
}
|
||||
else if (databaseProductName.indexOf("AS") != -1 && (databaseProductVersion.startsWith("QSQ") ||
|
||||
databaseProductVersion.substring(databaseProductVersion.indexOf('V')).matches("V\\dR\\d[mM]\\d"))) {
|
||||
else if (databaseProductName.indexOf("AS") != -1
|
||||
&& (databaseProductVersion.startsWith("QSQ") || databaseProductVersion
|
||||
.substring(databaseProductVersion.indexOf('V'))
|
||||
.matches("V\\dR\\d[mM]\\d"))) {
|
||||
databaseProductName = "DB2AS400";
|
||||
}
|
||||
else {
|
||||
@@ -96,23 +140,22 @@ public enum DatabaseType {
|
||||
|
||||
/**
|
||||
* Static method to obtain a DatabaseType from the provided product name.
|
||||
*
|
||||
* @param productName the name of the database.
|
||||
* @return DatabaseType for given product name.
|
||||
* @throws IllegalArgumentException if none is found.
|
||||
*/
|
||||
public static DatabaseType fromProductName(String productName){
|
||||
if(!dbNameMap.containsKey(productName)){
|
||||
throw new IllegalArgumentException("DatabaseType not found for product name: [" +
|
||||
productName + "]");
|
||||
public static DatabaseType fromProductName(String productName) {
|
||||
if (!dbNameMap.containsKey(productName)) {
|
||||
throw new IllegalArgumentException(
|
||||
"DatabaseType not found for product name: [" + productName + "]");
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return dbNameMap.get(productName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getProductName() {
|
||||
return productName;
|
||||
return this.productName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -39,7 +39,8 @@ public class SimpleTaskExplorer implements TaskExplorer {
|
||||
private TaskExecutionDao taskExecutionDao;
|
||||
|
||||
public SimpleTaskExplorer(TaskExecutionDaoFactoryBean taskExecutionDaoFactoryBean) {
|
||||
Assert.notNull(taskExecutionDaoFactoryBean, "taskExecutionDaoFactoryBean must not be null");
|
||||
Assert.notNull(taskExecutionDaoFactoryBean,
|
||||
"taskExecutionDaoFactoryBean must not be null");
|
||||
|
||||
try {
|
||||
this.taskExecutionDao = taskExecutionDaoFactoryBean.getObject();
|
||||
@@ -51,62 +52,64 @@ public class SimpleTaskExplorer implements TaskExplorer {
|
||||
|
||||
@Override
|
||||
public TaskExecution getTaskExecution(long executionId) {
|
||||
return taskExecutionDao.getTaskExecution(executionId);
|
||||
return this.taskExecutionDao.getTaskExecution(executionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable) {
|
||||
return taskExecutionDao.findRunningTaskExecutions(taskName, pageable);
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName,
|
||||
Pageable pageable) {
|
||||
return this.taskExecutionDao.findRunningTaskExecutions(taskName, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTaskNames() {
|
||||
return taskExecutionDao.getTaskNames();
|
||||
return this.taskExecutionDao.getTaskNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTaskExecutionCountByTaskName(String taskName) {
|
||||
return taskExecutionDao.getTaskExecutionCountByTaskName(taskName);
|
||||
return this.taskExecutionDao.getTaskExecutionCountByTaskName(taskName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTaskExecutionCount() {
|
||||
return taskExecutionDao.getTaskExecutionCount();
|
||||
return this.taskExecutionDao.getTaskExecutionCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRunningTaskExecutionCount() {
|
||||
return taskExecutionDao.getRunningTaskExecutionCount();
|
||||
return this.taskExecutionDao.getRunningTaskExecutionCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable) {
|
||||
return taskExecutionDao.findTaskExecutionsByName(taskName, pageable);
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName,
|
||||
Pageable pageable) {
|
||||
return this.taskExecutionDao.findTaskExecutionsByName(taskName, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TaskExecution> findAll(Pageable pageable) {
|
||||
return taskExecutionDao.findAll(pageable);
|
||||
return this.taskExecutionDao.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTaskExecutionIdByJobExecutionId(long jobExecutionId) {
|
||||
return taskExecutionDao.getTaskExecutionIdByJobExecutionId(jobExecutionId);
|
||||
return this.taskExecutionDao.getTaskExecutionIdByJobExecutionId(jobExecutionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
return taskExecutionDao.getJobExecutionIdsByTaskExecutionId(taskExecutionId);
|
||||
return this.taskExecutionDao.getJobExecutionIdsByTaskExecutionId(taskExecutionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskExecution> getLatestTaskExecutionsByTaskNames(String... taskNames) {
|
||||
return taskExecutionDao.getLatestTaskExecutionsByTaskNames(taskNames);
|
||||
return this.taskExecutionDao.getLatestTaskExecutionsByTaskNames(taskNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution getLatestTaskExecutionForTaskName(String taskName) {
|
||||
return taskExecutionDao.getLatestTaskExecutionForTaskName(taskName);
|
||||
return this.taskExecutionDao.getLatestTaskExecutionForTaskName(taskName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.repository.support;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -23,11 +24,11 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of the {@link TaskNameResolver} interface. Names the task based
|
||||
* Simple implementation of the {@link TaskNameResolver} interface. Names the task based
|
||||
* on the following order of precidence:
|
||||
* <ol>
|
||||
* <li>A configured property <code>spring.cloud.task.name</code></li>
|
||||
* <li>The {@link ApplicationContext}'s id.</li>
|
||||
* <li>A configured property <code>spring.cloud.task.name</code></li>
|
||||
* <li>The {@link ApplicationContext}'s id.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Michael Minella
|
||||
@@ -45,17 +46,19 @@ public class SimpleTaskNameResolver implements TaskNameResolver, ApplicationCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
if(StringUtils.hasText(configuredName)) {
|
||||
return configuredName;
|
||||
if (StringUtils.hasText(this.configuredName)) {
|
||||
return this.configuredName;
|
||||
}
|
||||
else {
|
||||
return context.getId().replace(":", "_");
|
||||
return this.context.getId().replace(":", "_");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -31,15 +31,27 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Records the task execution information to the log and to TaskExecutionDao provided.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
public class SimpleTaskRepository implements TaskRepository {
|
||||
|
||||
/**
|
||||
* Max exit message size.
|
||||
*/
|
||||
public static final int MAX_EXIT_MESSAGE_SIZE = 2500;
|
||||
|
||||
/**
|
||||
* Max task name size.
|
||||
*/
|
||||
public static final int MAX_TASK_NAME_SIZE = 100;
|
||||
|
||||
/**
|
||||
* Max error message size.
|
||||
*/
|
||||
public static final int MAX_ERROR_MESSAGE_SIZE = 2500;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SimpleTaskRepository.class);
|
||||
private static final Log logger = LogFactory.getLog(SimpleTaskRepository.class);
|
||||
|
||||
private TaskExecutionDao taskExecutionDao;
|
||||
|
||||
@@ -53,63 +65,63 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
|
||||
private int maxErrorMessageSize = MAX_ERROR_MESSAGE_SIZE;
|
||||
|
||||
public SimpleTaskRepository(FactoryBean<TaskExecutionDao> taskExecutionDaoFactoryBean){
|
||||
Assert.notNull(taskExecutionDaoFactoryBean, "A FactoryBean that provides a TaskExecutionDao is required");
|
||||
public SimpleTaskRepository(
|
||||
FactoryBean<TaskExecutionDao> taskExecutionDaoFactoryBean) {
|
||||
Assert.notNull(taskExecutionDaoFactoryBean,
|
||||
"A FactoryBean that provides a TaskExecutionDao is required");
|
||||
|
||||
this.taskExecutionDaoFactoryBean = taskExecutionDaoFactoryBean;
|
||||
}
|
||||
|
||||
public SimpleTaskRepository(FactoryBean<TaskExecutionDao> taskExecutionDaoFactoryBean, Integer maxExitMessageSize,
|
||||
Integer maxTaskNameSize, Integer maxErrorMessageSize){
|
||||
Assert.notNull(taskExecutionDaoFactoryBean, "A FactoryBean that provides a TaskExecutionDao is required");
|
||||
if(maxTaskNameSize != null) {
|
||||
public SimpleTaskRepository(FactoryBean<TaskExecutionDao> taskExecutionDaoFactoryBean,
|
||||
Integer maxExitMessageSize, Integer maxTaskNameSize,
|
||||
Integer maxErrorMessageSize) {
|
||||
Assert.notNull(taskExecutionDaoFactoryBean,
|
||||
"A FactoryBean that provides a TaskExecutionDao is required");
|
||||
if (maxTaskNameSize != null) {
|
||||
this.maxTaskNameSize = maxTaskNameSize;
|
||||
}
|
||||
if(maxExitMessageSize != null) {
|
||||
if (maxExitMessageSize != null) {
|
||||
this.maxExitMessageSize = maxExitMessageSize;
|
||||
}
|
||||
if(maxErrorMessageSize != null) {
|
||||
if (maxErrorMessageSize != null) {
|
||||
this.maxErrorMessageSize = maxErrorMessageSize;
|
||||
}
|
||||
this.taskExecutionDaoFactoryBean = taskExecutionDaoFactoryBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution completeTaskExecution(long executionId, Integer exitCode, Date endTime, String exitMessage) {
|
||||
public TaskExecution completeTaskExecution(long executionId, Integer exitCode,
|
||||
Date endTime, String exitMessage) {
|
||||
return completeTaskExecution(executionId, exitCode, endTime, exitMessage, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution completeTaskExecution(long executionId, Integer exitCode, Date endTime,
|
||||
String exitMessage, String errorMessage) {
|
||||
public TaskExecution completeTaskExecution(long executionId, Integer exitCode,
|
||||
Date endTime, String exitMessage, String errorMessage) {
|
||||
initialize();
|
||||
|
||||
validateCompletedTaskExitInformation(executionId, exitCode, endTime);
|
||||
exitMessage = trimMessage(exitMessage, this.maxExitMessageSize);
|
||||
errorMessage = trimMessage(errorMessage, this.maxErrorMessageSize);
|
||||
taskExecutionDao.completeTaskExecution(executionId, exitCode, endTime, exitMessage, errorMessage);
|
||||
logger.debug("Updating: TaskExecution with executionId="+executionId
|
||||
+ " with the following {"
|
||||
+ "exitCode=" + exitCode
|
||||
+ ", endTime=" + endTime
|
||||
+ ", exitMessage='" + exitMessage + '\''
|
||||
+ ", errorMessage='" + errorMessage + '\''
|
||||
+ '}');
|
||||
this.taskExecutionDao.completeTaskExecution(executionId, exitCode, endTime,
|
||||
exitMessage, errorMessage);
|
||||
logger.debug("Updating: TaskExecution with executionId=" + executionId
|
||||
+ " with the following {" + "exitCode=" + exitCode + ", endTime="
|
||||
+ endTime + ", exitMessage='" + exitMessage + '\'' + ", errorMessage='"
|
||||
+ errorMessage + '\'' + '}');
|
||||
|
||||
return taskExecutionDao.getTaskExecution(executionId);
|
||||
return this.taskExecutionDao.getTaskExecution(executionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(TaskExecution taskExecution) {
|
||||
initialize();
|
||||
validateCreateInformation(taskExecution);
|
||||
TaskExecution daoTaskExecution =
|
||||
taskExecutionDao.createTaskExecution(
|
||||
taskExecution.getTaskName(),
|
||||
taskExecution.getStartTime(),
|
||||
taskExecution.getArguments(),
|
||||
taskExecution.getExternalExecutionId(),
|
||||
taskExecution.getParentExecutionId());
|
||||
TaskExecution daoTaskExecution = this.taskExecutionDao.createTaskExecution(
|
||||
taskExecution.getTaskName(), taskExecution.getStartTime(),
|
||||
taskExecution.getArguments(), taskExecution.getExternalExecutionId(),
|
||||
taskExecution.getParentExecutionId());
|
||||
logger.debug("Creating: " + taskExecution.toString());
|
||||
return daoTaskExecution;
|
||||
}
|
||||
@@ -117,21 +129,20 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
@Override
|
||||
public TaskExecution createTaskExecution(String name) {
|
||||
initialize();
|
||||
TaskExecution taskExecution =
|
||||
taskExecutionDao.createTaskExecution(name, null,
|
||||
Collections.<String>emptyList(), null);
|
||||
TaskExecution taskExecution = this.taskExecutionDao.createTaskExecution(name,
|
||||
null, Collections.<String>emptyList(), null);
|
||||
logger.debug("Creating: " + taskExecution.toString());
|
||||
return taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution createTaskExecution() {
|
||||
return createTaskExecution((String)null);
|
||||
return createTaskExecution((String) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskExecution startTaskExecution(long executionid, String taskName, Date startTime, List<String> arguments,
|
||||
String externalExecutionId) {
|
||||
public TaskExecution startTaskExecution(long executionid, String taskName,
|
||||
Date startTime, List<String> arguments, String externalExecutionId) {
|
||||
return startTaskExecution(executionid, taskName, startTime, arguments,
|
||||
externalExecutionId, null);
|
||||
}
|
||||
@@ -139,7 +150,7 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
@Override
|
||||
public void updateExternalExecutionId(long executionid, String externalExecutionId) {
|
||||
initialize();
|
||||
taskExecutionDao.updateExternalExecutionId(executionid, externalExecutionId);
|
||||
this.taskExecutionDao.updateExternalExecutionId(executionid, externalExecutionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,10 +158,9 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
Date startTime, List<String> arguments, String externalExecutionId,
|
||||
Long parentExecutionId) {
|
||||
initialize();
|
||||
TaskExecution taskExecution =
|
||||
taskExecutionDao.startTaskExecution(executionid, taskName,
|
||||
startTime, arguments, externalExecutionId,
|
||||
parentExecutionId);
|
||||
TaskExecution taskExecution = this.taskExecutionDao.startTaskExecution(
|
||||
executionid, taskName, startTime, arguments, externalExecutionId,
|
||||
parentExecutionId);
|
||||
logger.debug("Starting: " + taskExecution.toString());
|
||||
return taskExecution;
|
||||
}
|
||||
@@ -161,44 +171,47 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
*/
|
||||
public TaskExecutionDao getTaskExecutionDao() {
|
||||
initialize();
|
||||
return taskExecutionDao;
|
||||
return this.taskExecutionDao;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if(!initialized) {
|
||||
if (!this.initialized) {
|
||||
try {
|
||||
this.taskExecutionDao = this.taskExecutionDaoFactoryBean.getObject();
|
||||
this.initialized = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Unable to create the TaskExecutionDao", e);
|
||||
throw new IllegalStateException("Unable to create the TaskExecutionDao",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate startTime and taskName are valid.
|
||||
* @param taskExecution task execution to validate
|
||||
*/
|
||||
private void validateCreateInformation(TaskExecution taskExecution) {
|
||||
Assert.notNull(taskExecution.getStartTime(), "TaskExecution start time cannot be null.");
|
||||
Assert.notNull(taskExecution.getStartTime(),
|
||||
"TaskExecution start time cannot be null.");
|
||||
|
||||
if (taskExecution.getTaskName() != null &&
|
||||
taskExecution.getTaskName().length() > this.maxTaskNameSize) {
|
||||
throw new IllegalArgumentException("TaskName length exceeds "
|
||||
+ this.maxTaskNameSize + " characters");
|
||||
if (taskExecution.getTaskName() != null
|
||||
&& taskExecution.getTaskName().length() > this.maxTaskNameSize) {
|
||||
throw new IllegalArgumentException(
|
||||
"TaskName length exceeds " + this.maxTaskNameSize + " characters");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateCompletedTaskExitInformation(long executionId, Integer exitCode, Date endTime){
|
||||
private void validateCompletedTaskExitInformation(long executionId, Integer exitCode,
|
||||
Date endTime) {
|
||||
Assert.notNull(exitCode, "exitCode should not be null");
|
||||
Assert.isTrue(exitCode >= 0, "exit code must be greater than or equal to zero");
|
||||
Assert.notNull(endTime, "TaskExecution endTime cannot be null.");
|
||||
}
|
||||
|
||||
private String trimMessage(String exitMessage, int maxSize){
|
||||
private String trimMessage(String exitMessage, int maxSize) {
|
||||
String result = exitMessage;
|
||||
if(exitMessage != null &&
|
||||
exitMessage.length() > maxSize) {
|
||||
if (exitMessage != null && exitMessage.length() > maxSize) {
|
||||
result = exitMessage.substring(0, maxSize);
|
||||
}
|
||||
return result;
|
||||
@@ -215,4 +228,5 @@ public class SimpleTaskRepository implements TaskRepository {
|
||||
public void setMaxErrorMessageSize(int maxErrorMessageSize) {
|
||||
this.maxErrorMessageSize = maxErrorMessageSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.task.repository.support;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
@@ -43,7 +44,7 @@ public class TaskExecutionDaoFactoryBean implements FactoryBean<TaskExecutionDao
|
||||
private String tablePrefix = TaskProperties.DEFAULT_TABLE_PREFIX;
|
||||
|
||||
/**
|
||||
* Default constructor will result in a Map based TaskExecutionDao. <b>This is only
|
||||
* Default constructor will result in a Map based TaskExecutionDao. <b>This is only
|
||||
* intended for testing purposes.</b>
|
||||
*/
|
||||
public TaskExecutionDaoFactoryBean() {
|
||||
@@ -51,7 +52,6 @@ public class TaskExecutionDaoFactoryBean implements FactoryBean<TaskExecutionDao
|
||||
|
||||
/**
|
||||
* {@link DataSource} to be used.
|
||||
*
|
||||
* @param dataSource {@link DataSource} to be used.
|
||||
* @param tablePrefix the table prefix to use for this dao.
|
||||
*/
|
||||
@@ -63,7 +63,6 @@ public class TaskExecutionDaoFactoryBean implements FactoryBean<TaskExecutionDao
|
||||
|
||||
/**
|
||||
* {@link DataSource} to be used.
|
||||
*
|
||||
* @param dataSource {@link DataSource} to be used.
|
||||
*/
|
||||
public TaskExecutionDaoFactoryBean(DataSource dataSource) {
|
||||
@@ -74,7 +73,7 @@ public class TaskExecutionDaoFactoryBean implements FactoryBean<TaskExecutionDao
|
||||
|
||||
@Override
|
||||
public TaskExecutionDao getObject() throws Exception {
|
||||
if(this.dao == null) {
|
||||
if (this.dao == null) {
|
||||
if (this.dataSource != null) {
|
||||
buildTaskExecutionDao(this.dataSource);
|
||||
}
|
||||
@@ -97,15 +96,19 @@ public class TaskExecutionDaoFactoryBean implements FactoryBean<TaskExecutionDao
|
||||
}
|
||||
|
||||
private void buildTaskExecutionDao(DataSource dataSource) {
|
||||
DataFieldMaxValueIncrementerFactory incrementerFactory = new DefaultDataFieldMaxValueIncrementerFactory(dataSource);
|
||||
DataFieldMaxValueIncrementerFactory incrementerFactory = new DefaultDataFieldMaxValueIncrementerFactory(
|
||||
dataSource);
|
||||
this.dao = new JdbcTaskExecutionDao(dataSource, this.tablePrefix);
|
||||
String databaseType;
|
||||
try {
|
||||
databaseType = org.springframework.batch.support.DatabaseType.fromMetaData(dataSource).name();
|
||||
databaseType = org.springframework.batch.support.DatabaseType
|
||||
.fromMetaData(dataSource).name();
|
||||
}
|
||||
catch (MetaDataAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
((JdbcTaskExecutionDao) this.dao).setTaskIncrementer(incrementerFactory.getIncrementer(databaseType, this.tablePrefix + "SEQ"));
|
||||
((JdbcTaskExecutionDao) this.dao).setTaskIncrementer(incrementerFactory
|
||||
.getIncrementer(databaseType, this.tablePrefix + "SEQ"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2019 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.
|
||||
@@ -32,11 +32,11 @@ import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility for initializing the Task Repository's datasource. If a single
|
||||
* 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).
|
||||
* (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.
|
||||
@@ -67,7 +67,7 @@ public final class TaskRepositoryInitializer implements InitializingBean {
|
||||
@Value("${spring.cloud.task.tablePrefix:#{null}}")
|
||||
private String tablePrefix;
|
||||
|
||||
public TaskRepositoryInitializer(){
|
||||
public TaskRepositoryInitializer() {
|
||||
}
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
@@ -81,7 +81,9 @@ public final class TaskRepositoryInitializer implements InitializingBean {
|
||||
|
||||
private String getDatabaseType(DataSource dataSource) {
|
||||
try {
|
||||
return JdbcUtils.commonDatabaseName(DatabaseType.fromMetaData(dataSource).toString()).toLowerCase();
|
||||
return JdbcUtils
|
||||
.commonDatabaseName(DatabaseType.fromMetaData(dataSource).toString())
|
||||
.toLowerCase();
|
||||
}
|
||||
catch (MetaDataAccessException ex) {
|
||||
throw new IllegalStateException("Unable to detect database type", ex);
|
||||
@@ -90,10 +92,9 @@ public final class TaskRepositoryInitializer implements InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (dataSource != null &&
|
||||
taskInitializationEnable &&
|
||||
!StringUtils.hasText(this.tablePrefix)) {
|
||||
String platform = getDatabaseType(dataSource);
|
||||
if (this.dataSource != null && this.taskInitializationEnable
|
||||
&& !StringUtils.hasText(this.tablePrefix)) {
|
||||
String platform = getDatabaseType(this.dataSource);
|
||||
if ("hsql".equals(platform)) {
|
||||
platform = "hsqldb";
|
||||
}
|
||||
@@ -106,17 +107,18 @@ public final class TaskRepositoryInitializer implements InitializingBean {
|
||||
if ("mysql".equals(platform)) {
|
||||
platform = "mysql";
|
||||
}
|
||||
if ("sqlserver".equals(platform)){
|
||||
if ("sqlserver".equals(platform)) {
|
||||
platform = "sqlserver";
|
||||
}
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
String schemaLocation = schema;
|
||||
schemaLocation = schemaLocation.replace("@@platform@@", platform);
|
||||
populator.addScript(resourceLoader.getResource(schemaLocation));
|
||||
populator.addScript(this.resourceLoader.getResource(schemaLocation));
|
||||
populator.setContinueOnError(true);
|
||||
logger.debug(String.format("Initializing task schema for %s database",
|
||||
platform));
|
||||
DatabasePopulatorUtils.execute(populator, dataSource);
|
||||
logger.debug(
|
||||
String.format("Initializing task schema for %s database", platform));
|
||||
DatabasePopulatorUtils.execute(populator, this.dataSource);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015-2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes used for setting up and supporting a task repositories.
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"defaultValue": false,
|
||||
"name": "spring.cloud.task.single-instance-enabled",
|
||||
"description": "This property is used to determine if a task will execute if another task with the same app name is running.",
|
||||
"type": "java.lang.Boolean"
|
||||
}
|
||||
]
|
||||
"properties": [
|
||||
{
|
||||
"defaultValue": false,
|
||||
"name": "spring.cloud.task.single-instance-enabled",
|
||||
"description": "This property is used to determine if a task will execute if another task with the same app name is running.",
|
||||
"type": "java.lang.Boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user