diff --git a/pom.xml b/pom.xml
index 624ec3b3..c67ad143 100755
--- a/pom.xml
+++ b/pom.xml
@@ -145,6 +145,7 @@
1.2.0.RELEASE
3.0.7.RELEASE
1.1
+ 7.0
UTF-8
${project.build.directory}/coverage-reports/jacoco-ut.exec
diff --git a/spring-cloud-task-core/pom.xml b/spring-cloud-task-core/pom.xml
index c6304710..3d7b2c7a 100755
--- a/spring-cloud-task-core/pom.xml
+++ b/spring-cloud-task-core/pom.xml
@@ -60,6 +60,22 @@
org.springframework.data
spring-data-commons
+
+ javax
+ javaee-api
+ ${java-ee-api.version}
+ true
+
+
+ org.springframework
+ spring-orm
+ true
+
+
+ org.hibernate
+ hibernate-validator
+ test
+
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
index 75f61ba7..36d16348 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
@@ -16,8 +16,12 @@
package org.springframework.cloud.task.configuration;
+import javax.persistence.EntityManager;
import javax.sql.DataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.cloud.task.repository.TaskExplorer;
import org.springframework.cloud.task.repository.TaskRepository;
@@ -26,7 +30,9 @@ import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
import org.springframework.cloud.task.repository.support.SimpleTaskExplorer;
import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
import org.springframework.cloud.task.repository.support.TaskExecutionDaoFactoryBean;
+import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
/**
@@ -44,6 +50,8 @@ import org.springframework.transaction.PlatformTransactionManager;
*/
public class DefaultTaskConfigurer implements TaskConfigurer {
+ private static final Log logger = LogFactory.getLog(DefaultTaskConfigurer.class);
+
private TaskRepository taskRepository;
private TaskExplorer taskExplorer;
@@ -54,6 +62,8 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
private DataSource dataSource;
+ private ApplicationContext context;
+
public DefaultTaskConfigurer() {
this(TaskProperties.DEFAULT_TABLE_PREFIX);
}
@@ -67,7 +77,7 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
* production use.
*/
public DefaultTaskConfigurer(DataSource dataSource) {
- this(dataSource, TaskProperties.DEFAULT_TABLE_PREFIX);
+ this(dataSource, TaskProperties.DEFAULT_TABLE_PREFIX, null);
}
/**
@@ -77,7 +87,7 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
* task infrastructure.
*/
public DefaultTaskConfigurer(String tablePrefix) {
- this(null, tablePrefix);
+ this(null, tablePrefix, null);
}
/**
@@ -89,8 +99,9 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
* @param tablePrefix the prefix to apply to the task table names used by
* task infrastructure.
*/
- public DefaultTaskConfigurer(DataSource dataSource, String tablePrefix) {
+ public DefaultTaskConfigurer(DataSource dataSource, String tablePrefix, ApplicationContext context) {
this.dataSource = dataSource;
+ this.context = context;
if(this.dataSource != null) {
this.taskExecutionDaoFactoryBean = new
@@ -120,11 +131,26 @@ public class DefaultTaskConfigurer implements TaskConfigurer {
@Override
public PlatformTransactionManager getTransactionManager() {
- if(this.transactionManager == null) {
- if(isDataSourceAvailable()) {
- this.transactionManager = new DataSourceTransactionManager(this.dataSource);
+ if (this.transactionManager == null) {
+ 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");
+ this.transactionManager = new JpaTransactionManager();
+ }
+ }
+ catch (ClassNotFoundException ignore) {
+ logger.debug("No EntityManager was found, using DataSourceTransactionManager");
+ }
+ finally {
+ if (this.transactionManager == null) {
+ this.transactionManager = new DataSourceTransactionManager(this.dataSource);
+ }
+ }
}
else {
+ logger.debug("No DataSource was found, using ResourcelessTransactionManager");
this.transactionManager = new ResourcelessTransactionManager();
}
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
index 1fa7070d..d8c818fc 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
@@ -157,11 +157,10 @@ public class SimpleTaskConfiguration {
if(!CollectionUtils.isEmpty(this.dataSources) && this.dataSources.size() == 1) {
taskConfigurer = new DefaultTaskConfigurer(
this.dataSources.iterator().next(),
- taskProperties.getTablePrefix());
+ taskProperties.getTablePrefix(), context);
}
else {
- taskConfigurer = new DefaultTaskConfigurer(
- taskProperties.getTablePrefix());
+ taskConfigurer = new DefaultTaskConfigurer(taskProperties.getTablePrefix());
}
this.context.getBeanFactory().registerSingleton("taskConfigurer", taskConfigurer);
return taskConfigurer;
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurerTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurerTests.java
new file mode 100644
index 00000000..722aa142
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurerTests.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package org.springframework.cloud.task.configuration;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author Glenn Renfro
+ */
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = { EmbeddedDataSourceConfiguration.class })
+public class DefaultTaskConfigurerTests {
+
+ @Autowired
+ DataSource dataSource;
+
+ @Autowired
+ ApplicationContext context;
+
+ @Test
+ public void resourcelessTransactionManagerTest() {
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer();
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(),
+ is("org.springframework.batch.support.transaction.ResourcelessTransactionManager"));
+ defaultTaskConfigurer = new DefaultTaskConfigurer("foo");
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(),
+ is("org.springframework.batch.support.transaction.ResourcelessTransactionManager"));
+ }
+
+ @Test
+ public void testDefaultContext() throws Exception {
+ AnnotationConfigApplicationContext localContext = new AnnotationConfigApplicationContext();
+ localContext.register(EmbeddedDataSourceConfiguration.class,EntityManagerConfiguration.class);
+ localContext.refresh();
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource, TaskProperties.DEFAULT_TABLE_PREFIX, localContext);
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(), is(equalTo("org.springframework.orm.jpa.JpaTransactionManager")));
+ }
+
+ @Test
+ public void dataSourceTransactionManagerTest() {
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource);
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(),
+ is("org.springframework.jdbc.datasource.DataSourceTransactionManager"));
+ defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource, "FOO", null);
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(),
+ is("org.springframework.jdbc.datasource.DataSourceTransactionManager"));
+ defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource, "FOO", context);
+ assertThat(defaultTaskConfigurer.getTransactionManager().getClass().getName(),
+ is("org.springframework.jdbc.datasource.DataSourceTransactionManager"));
+ }
+
+ @Test
+ public void taskExplorerTest() {
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource);
+ assertThat(defaultTaskConfigurer.getTaskExplorer(), is(notNullValue()));
+ defaultTaskConfigurer = new DefaultTaskConfigurer();
+ assertThat(defaultTaskConfigurer.getTaskExplorer(), is(notNullValue()));
+ }
+
+ @Test
+ public void taskRepositoryTest() {
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource);
+ assertThat(defaultTaskConfigurer.getTaskRepository(), is(notNullValue()));
+ defaultTaskConfigurer = new DefaultTaskConfigurer();
+ assertThat(defaultTaskConfigurer.getTaskRepository(), is(notNullValue()));
+ }
+
+ @Test
+ public void taskDataSource() {
+ DefaultTaskConfigurer defaultTaskConfigurer = new DefaultTaskConfigurer(dataSource);
+ assertThat(defaultTaskConfigurer.getTaskDataSource(), is(notNullValue()));
+ defaultTaskConfigurer = new DefaultTaskConfigurer();
+ assertThat(defaultTaskConfigurer.getTaskDataSource(), is(nullValue()));
+ }
+
+ @Configuration
+ public static class EntityManagerConfiguration {
+ @Bean
+ public EntityManager entityManager() {
+ return mock(EntityManager.class);
+ }
+ }
+}
diff --git a/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..5fd4d502
Binary files /dev/null and b/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..eb919476
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
\ No newline at end of file
diff --git a/spring-cloud-task-samples/jpa-sample/README.adoc b/spring-cloud-task-samples/jpa-sample/README.adoc
new file mode 100644
index 00000000..d047e573
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/README.adoc
@@ -0,0 +1,28 @@
+= JPA Sample Task
+
+This is a Spring Cloud Task Boot Application that uses JPA to persist data to
+a data store.
+
+== Requirements:
+
+* Java 7 or Above
+
+== Classes:
+
+* JpaApplication - the Spring Boot Main Application.
+* TaskRunComponent - Component responsible for writing data to the repository.
+* TaskRunOutput - Entity to be written to the repository.
+
+== Build:
+
+[source,shell,indent=2]
+----
+$ mvn clean package
+----
+
+== Run:
+
+[source,shell,indent=2]
+----
+$ java -jar target/jpa-sample-1.3.0.RELEASE.jar
+----
diff --git a/spring-cloud-task-samples/jpa-sample/mvnw b/spring-cloud-task-samples/jpa-sample/mvnw
new file mode 100755
index 00000000..a1ba1bf5
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/mvnw
@@ -0,0 +1,233 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} "$@"
diff --git a/spring-cloud-task-samples/jpa-sample/mvnw.cmd b/spring-cloud-task-samples/jpa-sample/mvnw.cmd
new file mode 100644
index 00000000..2b934e89
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/mvnw.cmd
@@ -0,0 +1,145 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+set MAVEN_CMD_LINE_ARGS=%*
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
\ No newline at end of file
diff --git a/spring-cloud-task-samples/jpa-sample/pom.xml b/spring-cloud-task-samples/jpa-sample/pom.xml
new file mode 100644
index 00000000..4159c23a
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/pom.xml
@@ -0,0 +1,120 @@
+
+
+
+
+ 4.0.0
+
+ io.spring.cloud
+ jpa-sample
+ jar
+ 1.3.0.BUILD-SNAPSHOT
+ To show users how to enable a task with a JPA application.
+
+ Spring Cloud Task JPA Sample Application
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
+
+
+
+
+ UTF-8
+ 1.7
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-task-dependencies
+ 1.3.0.BUILD-SNAPSHOT
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-task
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.hibernate
+ hibernate-entitymanager
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/JpaApplication.java b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/JpaApplication.java
new file mode 100644
index 00000000..7675425b
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/JpaApplication.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package io.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.task.configuration.EnableTask;
+
+@SpringBootApplication
+@EnableTask
+public class JpaApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(JpaApplication.class, args);
+ }
+
+}
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunComponent.java b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunComponent.java
new file mode 100644
index 00000000..b580ac8a
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunComponent.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package io.spring.configuration;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.task.listener.annotation.BeforeTask;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.stereotype.Component;
+
+/**
+ * Records an entry in the TASK_RUN_OUTPUT table on the BeforeTask event.
+ *
+ * @author Glenn Renfro
+ * @author Pas Apicella
+ */
+@Component
+public class TaskRunComponent {
+
+ private static final Log logger = LogFactory.getLog(TaskRunComponent.class);
+
+ @Autowired
+ private TaskRunRepository taskRunRepository;
+
+ @BeforeTask
+ public void init(TaskExecution taskExecution) {
+ String execDate = new SimpleDateFormat().format(new Date());
+ taskRunRepository.save(new TaskRunOutput("Executed at " + execDate));
+ logger.info("Executed at : " + execDate);
+ }
+}
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunOutput.java b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunOutput.java
new file mode 100644
index 00000000..599ed97b
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunOutput.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package io.spring.configuration;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Entity for the id and output to be written to the data store.
+ *
+ * @author Pas Apicella
+ * @author Glenn Renfro
+ */
+@Entity
+@Table(name = "TASK_RUN_OUTPUT")
+public class TaskRunOutput {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String output;
+
+ public TaskRunOutput() {
+ }
+
+ public TaskRunOutput(String output) {
+ this.output = output;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ public void setOutput(String output) {
+ this.output = output;
+ }
+
+ @Override
+ public String toString() {
+ return "TaskRunOutput{" + "id=" + id + ", output='" + output + '\'' + '}';
+ }
+}
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunRepository.java b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunRepository.java
new file mode 100644
index 00000000..a97829bc
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/java/io/spring/configuration/TaskRunRepository.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package io.spring.configuration;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * @author Pas Apicella
+ * @author Glenn Renfro
+ */
+public interface TaskRunRepository extends JpaRepository {
+}
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/resources/application-cloud.yml b/spring-cloud-task-samples/jpa-sample/src/main/resources/application-cloud.yml
new file mode 100644
index 00000000..a10a7f45
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/resources/application-cloud.yml
@@ -0,0 +1,5 @@
+spring:
+ jpa:
+ hibernate:
+ ddl-auto: update
+ show-sql: true
diff --git a/spring-cloud-task-samples/jpa-sample/src/main/resources/application.yml b/spring-cloud-task-samples/jpa-sample/src/main/resources/application.yml
new file mode 100644
index 00000000..10a5a504
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+spring:
+ jpa:
+ hibernate:
+ ddl-auto: update
+ show-sql: true
+ application:
+ name: Spring Cloud Task JPA Sample Application
+logging:
+ level:
+ org:
+ springframework:
+ cloud:
+ task: debug
diff --git a/spring-cloud-task-samples/jpa-sample/src/test/java/io/spring/JpaApplicationTests.java b/spring-cloud-task-samples/jpa-sample/src/test/java/io/spring/JpaApplicationTests.java
new file mode 100644
index 00000000..4a36565b
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/test/java/io/spring/JpaApplicationTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017 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.
+ */
+
+package io.spring;
+
+import java.sql.SQLException;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.h2.tools.Server;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.test.rule.OutputCapture;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.util.SocketUtils;
+
+import static junit.framework.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Verifies that a JPA Application can write its data to a repository.
+ *
+ * @author Glenn Renfro
+ */
+public class JpaApplicationTests {
+
+ private final static String DATASOURCE_URL;
+
+ private final static String DATASOURCE_USER_NAME = "SA";
+
+ private final static String DATASOURCE_USER_PASSWORD = "";
+
+ private final static String DATASOURCE_DRIVER_CLASS_NAME = "org.h2.Driver";
+
+ private static int randomPort;
+
+ static {
+ randomPort = SocketUtils.findAvailableTcpPort();
+ DATASOURCE_URL = "jdbc:h2:tcp://localhost:" + randomPort + "/mem:dataflow;DB_CLOSE_DELAY=-1;"
+ + "DB_CLOSE_ON_EXIT=FALSE";
+ }
+
+ private DataSource dataSource;
+
+ private Server server;
+
+ @Before
+ public void setup() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(DATASOURCE_DRIVER_CLASS_NAME);
+ dataSource.setUrl(DATASOURCE_URL);
+ dataSource.setUsername(DATASOURCE_USER_NAME);
+ dataSource.setPassword(DATASOURCE_USER_PASSWORD);
+ this.dataSource = dataSource;
+ try {
+ this.server = Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", String.valueOf(randomPort))
+ .start();
+ }
+ catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ this.server.stop();
+ }
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ @Test
+ public void testBatchJobApp() throws Exception {
+ final String INSERT_MESSAGE = "Hibernate: insert into task_run_output (id, output) values (null, ?)";
+ SpringApplication.run(JpaApplication.class, "--spring.datasource.url=" + DATASOURCE_URL,
+ "--spring.datasource.username=" + DATASOURCE_USER_NAME,
+ "--spring.datasource.driverClassName=" + DATASOURCE_DRIVER_CLASS_NAME,
+ "--spring.jpa.database-platform=org.hibernate.dialect.H2Dialect");
+ String output = this.outputCapture.toString();
+ assertTrue("Unable to find the insert message: " + output, output.contains(INSERT_MESSAGE));
+ JdbcTemplate template = new JdbcTemplate(this.dataSource);
+ Map result = template.queryForMap("Select * from TASK_RUN_OUTPUT");
+ assertThat(((Long) result.get("ID")), is(1L));
+ assertThat(((String) result.get("OUTPUT")), containsString("Executed at"));
+ }
+
+}
diff --git a/spring-cloud-task-samples/jpa-sample/src/test/resources/application.properties b/spring-cloud-task-samples/jpa-sample/src/test/resources/application.properties
new file mode 100644
index 00000000..b7ac0859
--- /dev/null
+++ b/spring-cloud-task-samples/jpa-sample/src/test/resources/application.properties
@@ -0,0 +1,18 @@
+#
+# Copyright 2016 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+#
+
+logging.level.root=DEBUG
+spring.application.name=Spring Cloud Task JPA Sample Application
diff --git a/spring-cloud-task-samples/pom.xml b/spring-cloud-task-samples/pom.xml
index 7a8722cd..e35d04ee 100644
--- a/spring-cloud-task-samples/pom.xml
+++ b/spring-cloud-task-samples/pom.xml
@@ -27,6 +27,7 @@
partitioned-batch-job
task-events
batch-events
+ jpa-sample