diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 7de84e78c8..4ff4029fc0 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -510,6 +510,11 @@
aspectjweaver
true
+
+ org.jooq
+ jooq
+ true
+
org.springframework.boot
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java
new file mode 100644
index 0000000000..c4e747e3e8
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import javax.sql.DataSource;
+
+import org.jooq.ConnectionProvider;
+import org.jooq.DSLContext;
+import org.jooq.ExecuteListenerProvider;
+import org.jooq.RecordListenerProvider;
+import org.jooq.RecordMapperProvider;
+import org.jooq.SQLDialect;
+import org.jooq.TransactionProvider;
+import org.jooq.VisitListenerProvider;
+import org.jooq.conf.Settings;
+import org.jooq.impl.DataSourceConnectionProvider;
+import org.jooq.impl.DefaultConfiguration;
+import org.jooq.impl.DefaultDSLContext;
+import org.jooq.impl.DefaultExecuteListenerProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.util.StringUtils;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for JOOQ.
+ *
+ * @author Andreas Ahlenstorf
+ * @since 1.3.0
+ */
+@Configuration
+@ConditionalOnClass(DSLContext.class)
+@ConditionalOnBean(DataSource.class)
+@AutoConfigureAfter(DataSourceAutoConfiguration.class)
+public class JooqAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(DataSourceConnectionProvider.class)
+ public DataSourceConnectionProvider dataSourceConnectionProvider(DataSource dataSource) {
+ return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(
+ dataSource));
+ }
+
+ @Bean
+ @ConditionalOnBean(PlatformTransactionManager.class)
+ public TransactionProvider transactionProvider(PlatformTransactionManager txManager) {
+ return new SpringTransactionProvider(txManager);
+ }
+
+ @Bean
+ public ExecuteListenerProvider jooqExceptionTranslatorExecuteListenerProvider() {
+ return new DefaultExecuteListenerProvider(new JooqExceptionTranslator());
+ }
+
+ @Configuration
+ @ConditionalOnMissingBean(DSLContext.class)
+ @EnableConfigurationProperties(JooqProperties.class)
+ public static class DslContextConfiguration {
+
+ @Autowired
+ private JooqProperties properties = new JooqProperties();
+
+ @Autowired
+ private ConnectionProvider connectionProvider;
+
+ @Autowired(required = false)
+ private TransactionProvider transactionProvider;
+
+ @Autowired(required = false)
+ private RecordMapperProvider recordMapperProvider;
+
+ @Autowired(required = false)
+ private Settings settings;
+
+ @Autowired(required = false)
+ private RecordListenerProvider[] recordListenerProviders;
+
+ @Autowired
+ private ExecuteListenerProvider[] executeListenerProviders;
+
+ @Autowired(required = false)
+ private VisitListenerProvider[] visitListenerProviders;
+
+ @Bean
+ public DefaultDSLContext dslContext(org.jooq.Configuration configuration) {
+ return new DefaultDSLContext(configuration);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(org.jooq.Configuration.class)
+ public DefaultConfiguration jooqConfiguration() {
+ DefaultConfiguration configuration = new DefaultConfiguration();
+ if (!StringUtils.isEmpty(this.properties.getSqlDialect())) {
+ configuration.set(SQLDialect.valueOf(this.properties.getSqlDialect()));
+ }
+ configuration.set(this.connectionProvider);
+ if (this.transactionProvider != null) {
+ configuration.set(this.transactionProvider);
+ }
+ if (this.recordMapperProvider != null) {
+ configuration.set(this.recordMapperProvider);
+ }
+ if (this.settings != null) {
+ configuration.set(this.settings);
+ }
+ configuration.set(this.recordListenerProviders);
+ configuration.set(this.executeListenerProviders);
+ configuration.set(this.visitListenerProviders);
+ return configuration;
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java
new file mode 100644
index 0000000000..addc5857ea
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import java.sql.SQLException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jooq.ExecuteContext;
+import org.jooq.SQLDialect;
+import org.jooq.impl.DefaultExecuteListener;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
+import org.springframework.jdbc.support.SQLExceptionTranslator;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+
+/**
+ * Transforms {@link java.sql.SQLException} into a Spring-specific @{link
+ * DataAccessException}.
+ *
+ * @author Lukas Eder
+ * @author Andreas Ahlenstorf
+ * @author Phillip Webb
+ */
+class JooqExceptionTranslator extends DefaultExecuteListener {
+
+ // Based on the jOOQ-spring-example from https://github.com/jOOQ/jOOQ
+
+ private static final Log logger = LogFactory.getLog(JooqExceptionTranslator.class);
+
+ @Override
+ public void exception(ExecuteContext context) {
+ SQLExceptionTranslator translator = getTranslator(context);
+ // The exception() callback is not only triggered for SQL exceptions but also for
+ // "normal" exceptions. In those cases sqlException() returns null.
+ SQLException exception = context.sqlException();
+ while (exception != null) {
+ handle(context, translator, exception);
+ exception = exception.getNextException();
+ }
+ }
+
+ private SQLExceptionTranslator getTranslator(ExecuteContext context) {
+ SQLDialect dialect = context.configuration().dialect();
+ if (dialect != null) {
+ return new SQLErrorCodeSQLExceptionTranslator(dialect.name());
+ }
+ return new SQLStateSQLExceptionTranslator();
+ }
+
+ /**
+ * Handle a single exception in the chain. SQLExceptions might be nested multiple
+ * levels deep. The outermost exception is usually the least interesting one
+ * ("Call getNextException to see the cause."). Therefore the innermost exception is
+ * propagated and all other exceptions are logged.
+ * @param context the execute context
+ * @param translator the exception translator
+ * @param exception the exception
+ */
+ private void handle(ExecuteContext context, SQLExceptionTranslator translator,
+ SQLException exception) {
+ DataAccessException translated = translate(context, translator, exception);
+ if (exception.getNextException() == null) {
+ context.exception(translated);
+ }
+ else {
+ logger.error("Execution of SQL statement failed.", translated);
+ }
+ }
+
+ private DataAccessException translate(ExecuteContext context,
+ SQLExceptionTranslator translator, SQLException exception) {
+ return translator.translate("jOOQ", context.sql(), exception);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqProperties.java
new file mode 100644
index 0000000000..c68961bb71
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqProperties.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Configuration properties for the JOOQ database library.
+ *
+ * @author Andreas Ahlenstorf
+ * @since 1.3.0
+ */
+@ConfigurationProperties(prefix = "spring.jooq")
+public class JooqProperties {
+
+ /**
+ * SQLDialect JOOQ used when communicating with the configured datasource, e.g.
+ * "POSTGRES".
+ */
+ private String sqlDialect;
+
+ public String getSqlDialect() {
+ return this.sqlDialect;
+ }
+
+ public void setSqlDialect(String sqlDialect) {
+ this.sqlDialect = sqlDialect;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransaction.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransaction.java
new file mode 100644
index 0000000000..c766d20a69
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransaction.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import org.jooq.Transaction;
+import org.springframework.transaction.TransactionStatus;
+
+/**
+ * Adapts a Spring transaction for JOOQ.
+ *
+ * @author Lukas Eder
+ * @author Andreas Ahlenstorf
+ * @author Phillip Webb
+ */
+class SpringTransaction implements Transaction {
+
+ // Based on the jOOQ-spring-example from https://github.com/jOOQ/jOOQ
+
+ private final TransactionStatus transactionStatus;
+
+ public SpringTransaction(TransactionStatus transactionStatus) {
+ this.transactionStatus = transactionStatus;
+ }
+
+ public TransactionStatus getTxStatus() {
+ return this.transactionStatus;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransactionProvider.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransactionProvider.java
new file mode 100644
index 0000000000..bfe80f1fc0
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/SpringTransactionProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import org.jooq.TransactionContext;
+import org.jooq.TransactionProvider;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+
+/**
+ * Allows Spring Transaction to be used with JOOQ.
+ *
+ * @author Lukas Eder
+ * @author Andreas Ahlenstorf
+ * @author Phillip Webb
+ */
+class SpringTransactionProvider implements TransactionProvider {
+
+ // Based on the jOOQ-spring-example from https://github.com/jOOQ/jOOQ
+
+ private final PlatformTransactionManager transactionManager;
+
+ SpringTransactionProvider(PlatformTransactionManager transactionManager) {
+ this.transactionManager = transactionManager;
+ }
+
+ @Override
+ public void begin(TransactionContext context) {
+ TransactionDefinition definition = new DefaultTransactionDefinition(
+ TransactionDefinition.PROPAGATION_NESTED);
+ TransactionStatus status = this.transactionManager.getTransaction(definition);
+ context.transaction(new SpringTransaction(status));
+ }
+
+ @Override
+ public void commit(TransactionContext ctx) {
+ this.transactionManager.commit(getTransactionStatus(ctx));
+ }
+
+ @Override
+ public void rollback(TransactionContext ctx) {
+ this.transactionManager.rollback(getTransactionStatus(ctx));
+ }
+
+ private TransactionStatus getTransactionStatus(TransactionContext ctx) {
+ SpringTransaction transaction = (SpringTransaction) ctx.transaction();
+ return transaction.getTxStatus();
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/package-info.java
new file mode 100644
index 0000000000..0ee259b983
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2015 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.
+ */
+
+/**
+ * Auto-configuration for JOOQ.
+ */
+package org.springframework.boot.autoconfigure.jooq;
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
index 05834600d2..8fe06c5c4c 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -39,6 +39,7 @@ org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchDataAutoConfig
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
+org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfigurationTests.java
new file mode 100644
index 0000000000..b2003bbf9b
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfigurationTests.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-2015 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.boot.autoconfigure.jooq;
+
+import javax.sql.DataSource;
+
+import org.hamcrest.Matcher;
+import org.jooq.DSLContext;
+import org.jooq.ExecuteListener;
+import org.jooq.ExecuteListenerProvider;
+import org.jooq.Record;
+import org.jooq.RecordListener;
+import org.jooq.RecordListenerProvider;
+import org.jooq.RecordMapper;
+import org.jooq.RecordMapperProvider;
+import org.jooq.RecordType;
+import org.jooq.SQLDialect;
+import org.jooq.TransactionalRunnable;
+import org.jooq.VisitListener;
+import org.jooq.VisitListenerProvider;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
+import org.springframework.boot.test.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests for {@link JooqAutoConfiguration}.
+ *
+ * @author Andreas Ahlenstorf
+ * @author Phillip Webb
+ */
+public class JooqAutoConfigurationTests {
+
+ private static final String[] NO_BEANS = {};
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+
+ @Before
+ public void init() {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.datasource.name:jooqtest");
+ EnvironmentTestUtils.addEnvironment(this.context, "spring.jooq.sql-dialect:H2");
+ }
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void noDataSource() throws Exception {
+ registerAndRefresh(JooqAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ assertEquals(0, this.context.getBeanNamesForType(DSLContext.class).length);
+ }
+
+ @Test
+ public void jooqWithoutTx() throws Exception {
+ registerAndRefresh(JooqDataSourceConfiguration.class,
+ JooqAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
+ assertThat(getBeanNames(PlatformTransactionManager.class), equalTo(NO_BEANS));
+ assertThat(getBeanNames(SpringTransactionProvider.class), equalTo(NO_BEANS));
+ DSLContext dsl = this.context.getBean(DSLContext.class);
+ dsl.execute("create table jooqtest (name varchar(255) primary key);");
+ dsl.transaction(new AssertFetch(dsl, "select count(*) as total from jooqtest;",
+ equalTo("0")));
+ dsl.transaction(new ExecuteSql(dsl, "insert into jooqtest (name) values ('foo');"));
+ dsl.transaction(new AssertFetch(dsl, "select count(*) as total from jooqtest;",
+ equalTo("1")));
+ try {
+ dsl.transaction(new ExecuteSql(dsl,
+ "insert into jooqtest (name) values ('bar');",
+ "insert into jooqtest (name) values ('foo');"));
+ fail("An DataIntegrityViolationException should have been thrown.");
+ }
+ catch (DataIntegrityViolationException ex) {
+ }
+ dsl.transaction(new AssertFetch(dsl, "select count(*) as total from jooqtest;",
+ equalTo("2")));
+ }
+
+ @Test
+ public void jooqWithTx() throws Exception {
+ registerAndRefresh(JooqDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class, TxManagerConfiguration.class,
+ JooqAutoConfiguration.class);
+ this.context.getBean(PlatformTransactionManager.class);
+ DSLContext dsl = this.context.getBean(DSLContext.class);
+ assertEquals(SQLDialect.H2, dsl.configuration().dialect());
+ dsl.execute("create table jooqtest_tx (name varchar(255) primary key);");
+ dsl.transaction(new AssertFetch(dsl,
+ "select count(*) as total from jooqtest_tx;", equalTo("0")));
+ dsl.transaction(new ExecuteSql(dsl,
+ "insert into jooqtest_tx (name) values ('foo');"));
+ dsl.transaction(new AssertFetch(dsl,
+ "select count(*) as total from jooqtest_tx;", equalTo("1")));
+ try {
+ dsl.transaction(new ExecuteSql(dsl,
+ "insert into jooqtest (name) values ('bar');",
+ "insert into jooqtest (name) values ('foo');"));
+ fail("A DataIntegrityViolationException should have been thrown.");
+ }
+ catch (DataIntegrityViolationException ex) {
+ }
+ dsl.transaction(new AssertFetch(dsl,
+ "select count(*) as total from jooqtest_tx;", equalTo("1")));
+ }
+
+ @Test
+ public void customProvidersArePickedUp() {
+ registerAndRefresh(JooqDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class, TxManagerConfiguration.class,
+ TestRecordMapperProvider.class, TestRecordListenerProvider.class,
+ TestExecuteListenerProvider.class, TestVisitListenerProvider.class,
+ JooqAutoConfiguration.class);
+ DSLContext dsl = this.context.getBean(DSLContext.class);
+ assertEquals(TestRecordMapperProvider.class, dsl.configuration()
+ .recordMapperProvider().getClass());
+ assertThat(dsl.configuration().recordListenerProviders().length, equalTo(1));
+ assertThat(dsl.configuration().executeListenerProviders().length, equalTo(2));
+ assertThat(dsl.configuration().visitListenerProviders().length, equalTo(1));
+ }
+
+ private void registerAndRefresh(Class>... annotatedClasses) {
+ this.context.register(annotatedClasses);
+ this.context.refresh();
+ }
+
+ private String[] getBeanNames(Class> type) {
+ return this.context.getBeanNamesForType(type);
+ }
+
+ private static class AssertFetch implements TransactionalRunnable {
+
+ private final DSLContext dsl;
+
+ private final String sql;
+
+ private final Matcher super String> matcher;
+
+ public AssertFetch(DSLContext dsl, String sql, Matcher super String> matcher) {
+ this.dsl = dsl;
+ this.sql = sql;
+ this.matcher = matcher;
+ }
+
+ @Override
+ public void run(org.jooq.Configuration configuration) throws Exception {
+ assertThat(this.dsl.fetch(this.sql).getValue(0, 0).toString(), this.matcher);
+ }
+
+ }
+
+ private static class ExecuteSql implements TransactionalRunnable {
+
+ private final DSLContext dsl;
+
+ private final String[] sql;
+
+ public ExecuteSql(DSLContext dsl, String... sql) {
+ this.dsl = dsl;
+ this.sql = sql;
+ }
+
+ @Override
+ public void run(org.jooq.Configuration configuration) throws Exception {
+ for (String statement : this.sql) {
+ this.dsl.execute(statement);
+ }
+ }
+
+ }
+
+ @Configuration
+ protected static class JooqDataSourceConfiguration {
+
+ @Bean
+ public DataSource jooqDataSource() {
+ return DataSourceBuilder.create().url("jdbc:hsqldb:mem:jooqtest")
+ .username("sa").build();
+ }
+
+ }
+
+ @Configuration
+ protected static class TxManagerConfiguration {
+
+ @Bean
+ public PlatformTransactionManager transactionManager(DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
+
+ }
+
+ protected static class TestRecordMapperProvider implements RecordMapperProvider {
+
+ @Override
+ public RecordMapper provide(RecordType recordType,
+ Class extends E> aClass) {
+ return null;
+ }
+
+ }
+
+ protected static class TestRecordListenerProvider implements RecordListenerProvider {
+
+ @Override
+ public RecordListener provide() {
+ return null;
+ }
+
+ }
+
+ protected static class TestExecuteListenerProvider implements ExecuteListenerProvider {
+
+ @Override
+ public ExecuteListener provide() {
+ return null;
+ }
+
+ }
+
+ protected static class TestVisitListenerProvider implements VisitListenerProvider {
+
+ @Override
+ public VisitListener provide() {
+ return null;
+ }
+
+ }
+
+}
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 27afee588a..f686060fb7 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -100,6 +100,7 @@
2.8.1
1.3.1
20141113
+ 3.6.2
2.0.0
1.2
4.12
@@ -318,6 +319,11 @@
spring-boot-starter-jetty
1.3.0.BUILD-SNAPSHOT
+
+ org.springframework.boot
+ spring-boot-starter-jooq
+ 1.3.0.BUILD-SNAPSHOT
+
org.springframework.boot
spring-boot-starter-jta-atomikos
@@ -1477,6 +1483,21 @@
json
${json.version}
+
+ org.jooq
+ jooq
+ ${jooq.version}
+
+
+ org.jooq
+ jooq-meta
+ ${jooq.version}
+
+
+ org.jooq
+ jooq-codegen
+ ${jooq.version}
+
org.liquibase
liquibase-core
@@ -1836,6 +1857,11 @@
+
+ org.jooq
+ jooq-codegen-maven
+ ${jooq.version}
+
org.springframework.boot
spring-boot-maven-plugin
diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml
index c683196be9..d43c5dc262 100644
--- a/spring-boot-starters/pom.xml
+++ b/spring-boot-starters/pom.xml
@@ -41,6 +41,7 @@
spring-boot-starter-jdbc
spring-boot-starter-jersey
spring-boot-starter-jetty
+ spring-boot-starter-jooq
spring-boot-starter-jta-atomikos
spring-boot-starter-jta-bitronix
spring-boot-starter-logging
diff --git a/spring-boot-starters/spring-boot-starter-jooq/pom.xml b/spring-boot-starters/spring-boot-starter-jooq/pom.xml
new file mode 100644
index 0000000000..40cf8f370c
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-jooq/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starters
+ 1.3.0.BUILD-SNAPSHOT
+
+ spring-boot-starter-jooq
+ Spring Boot JOOQ Starter
+ Spring Boot JOOQ Starter
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.springframework
+ spring-tx
+
+
+ org.jooq
+ jooq
+
+
+
diff --git a/spring-boot-starters/spring-boot-starter-jooq/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-jooq/src/main/resources/META-INF/spring.provides
new file mode 100644
index 0000000000..062b6d60d2
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-jooq/src/main/resources/META-INF/spring.provides
@@ -0,0 +1 @@
+provides: jooq
\ No newline at end of file