diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index dd0f773bf8..84eb9a2e64 100755
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -329,6 +329,11 @@
spring-integration-core
true
+
+ org.springframework.integration
+ spring-integration-jdbc
+ true
+
org.springframework.integration
spring-integration-jmx
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java
index 0241676b84..bdf301d8c2 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-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.
@@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.integration;
import javax.management.MBeanServer;
+import javax.sql.DataSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
@@ -25,17 +26,21 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.bind.RelaxedPropertyResolver;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
+import org.springframework.core.io.ResourceLoader;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.config.EnableIntegrationManagement;
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
+import org.springframework.integration.jdbc.store.JdbcMessageStore;
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.integration.support.management.IntegrationManagementConfigurer;
@@ -48,10 +53,12 @@ import org.springframework.util.StringUtils;
* @author Artem Bilan
* @author Dave Syer
* @author Stephane Nicoll
+ * @author Vedran Pavic
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass(EnableIntegration.class)
+@EnableConfigurationProperties(IntegrationProperties.class)
@AutoConfigureAfter(JmxAutoConfiguration.class)
public class IntegrationAutoConfiguration {
@@ -131,4 +138,24 @@ public class IntegrationAutoConfiguration {
}
+ /**
+ * Integration JDBC configuration.
+ */
+ @Configuration
+ @ConditionalOnClass(JdbcMessageStore.class)
+ @ConditionalOnSingleCandidate(DataSource.class)
+ protected static class IntegrationJdbcConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnProperty(prefix = "spring.integration.jdbc.initializer", name = "enabled")
+ public IntegrationDatabaseInitializer integrationDatabaseInitializer(
+ DataSource dataSource, ResourceLoader resourceLoader,
+ IntegrationProperties properties) {
+ return new IntegrationDatabaseInitializer(dataSource, resourceLoader,
+ properties);
+ }
+
+ }
+
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationDatabaseInitializer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationDatabaseInitializer.java
new file mode 100644
index 0000000000..29d4d8f306
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationDatabaseInitializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-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.boot.autoconfigure.integration;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.autoconfigure.AbstractDatabaseInitializer;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.Assert;
+
+/**
+ * Initializer for Spring Integration schema.
+ *
+ * @author Vedran Pavic
+ * @since 2.0.0
+ */
+public class IntegrationDatabaseInitializer extends AbstractDatabaseInitializer {
+
+ private final IntegrationProperties.Jdbc properties;
+
+ public IntegrationDatabaseInitializer(DataSource dataSource,
+ ResourceLoader resourceLoader, IntegrationProperties properties) {
+ super(dataSource, resourceLoader);
+ Assert.notNull(properties, "IntegrationProperties must not be null");
+ this.properties = properties.getJdbc();
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return this.properties.getInitializer().isEnabled();
+ }
+
+ @Override
+ protected String getSchemaLocation() {
+ return this.properties.getSchema();
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationProperties.java
new file mode 100644
index 0000000000..3ebab5508d
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationProperties.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012-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.boot.autoconfigure.integration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Configuration properties for Spring Integration.
+ *
+ * @author Vedran Pavic
+ * @author Stephane Nicoll
+ * @since 2.0.0
+ */
+@ConfigurationProperties(prefix = "spring.integration")
+public class IntegrationProperties {
+
+ private final Jdbc jdbc = new Jdbc();
+
+ public Jdbc getJdbc() {
+ return this.jdbc;
+ }
+
+ public static class Jdbc {
+
+ private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
+ + "integration/jdbc/schema-@@platform@@.sql";
+
+ /**
+ * Path to the SQL file to use to initialize the database schema.
+ */
+ private String schema = DEFAULT_SCHEMA_LOCATION;
+
+ private final Initializer initializer = new Initializer();
+
+ public String getSchema() {
+ return this.schema;
+ }
+
+ public void setSchema(String schema) {
+ this.schema = schema;
+ }
+
+ public Initializer getInitializer() {
+ return this.initializer;
+ }
+
+ public class Initializer {
+
+ /**
+ * Create the required integration tables on startup.
+ */
+ private boolean enabled = false;
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java
index 381b945f8e..04840221a9 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-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.
@@ -22,10 +22,16 @@ import java.util.List;
import javax.management.MBeanServer;
import org.junit.After;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration.IntegrationComponentScanAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -36,6 +42,8 @@ import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.gateway.RequestReplyExchanger;
import org.springframework.integration.support.channel.HeaderChannelRegistry;
import org.springframework.integration.support.management.IntegrationManagementConfigurer;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jmx.export.MBeanExporter;
import org.springframework.test.context.support.TestPropertySourceUtils;
@@ -47,9 +55,13 @@ import static org.mockito.Mockito.mock;
*
* @author Artem Bilan
* @author Stephane Nicoll
+ * @author Vedran Pavic
*/
public class IntegrationAutoConfigurationTests {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
private AnnotationConfigApplicationContext context;
@After
@@ -126,12 +138,62 @@ public class IntegrationAutoConfigurationTests {
@Test
public void primaryExporterIsAllowed() {
- load(CustomMBeanExporter.class);
+ load(new Class[] { CustomMBeanExporter.class });
assertThat(this.context.getBeansOfType(MBeanExporter.class)).hasSize(2);
assertThat(this.context.getBean(MBeanExporter.class))
.isSameAs(this.context.getBean("myMBeanExporter"));
}
+ @Test
+ public void integrationJdbcDatabaseInitializerEnabled() {
+ load(new Class[] { EmbeddedDataSourceConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ JdbcTemplateAutoConfiguration.class,
+ IntegrationAutoConfiguration.class},
+ "spring.datasource.generate-unique-name=true",
+ "spring.integration.jdbc.initializer.enabled=true");
+ assertThat(this.context.getBean(IntegrationProperties.class).getJdbc()
+ .getInitializer().isEnabled()).isTrue();
+ JdbcOperations jdbcOperations = this.context.getBean(JdbcOperations.class);
+ assertThat(jdbcOperations.queryForList("select * from INT_MESSAGE")).isEmpty();
+ assertThat(jdbcOperations.queryForList("select * from INT_GROUP_TO_MESSAGE"))
+ .isEmpty();
+ assertThat(jdbcOperations.queryForList("select * from INT_MESSAGE_GROUP"))
+ .isEmpty();
+ assertThat(jdbcOperations.queryForList("select * from INT_LOCK")).isEmpty();
+ assertThat(jdbcOperations.queryForList("select * from INT_CHANNEL_MESSAGE"))
+ .isEmpty();
+ }
+
+ @Test
+ public void integrationJdbcDatabaseInitializerDisabled() {
+ load(new Class[] { EmbeddedDataSourceConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ JdbcTemplateAutoConfiguration.class,
+ IntegrationAutoConfiguration.class },
+ "spring.datasource.generate-unique-name=true",
+ "spring.integration.jdbc.initializer.enabled=false");
+ assertThat(this.context.getBean(IntegrationProperties.class).getJdbc()
+ .getInitializer().isEnabled()).isFalse();
+ JdbcOperations jdbcOperations = this.context.getBean(JdbcOperations.class);
+ this.thrown.expect(BadSqlGrammarException.class);
+ jdbcOperations.queryForList("select * from INT_MESSAGE");
+ }
+
+ @Test
+ public void integrationJdbcDatabaseInitializerDisabledByDefault() {
+ load(new Class[] { EmbeddedDataSourceConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ JdbcTemplateAutoConfiguration.class,
+ IntegrationAutoConfiguration.class },
+ "spring.datasource.generate-unique-name=true");
+ assertThat(this.context.getBean(IntegrationProperties.class).getJdbc()
+ .getInitializer().isEnabled()).isFalse();
+ JdbcOperations jdbcOperations = this.context.getBean(JdbcOperations.class);
+ this.thrown.expect(BadSqlGrammarException.class);
+ jdbcOperations.queryForList("select * from INT_MESSAGE");
+ }
+
private static void assertDomains(MBeanServer mBeanServer, boolean expected,
String... domains) {
List actual = Arrays.asList(mBeanServer.getDomains());
@@ -144,12 +206,12 @@ public class IntegrationAutoConfigurationTests {
load(null, environment);
}
- private void load(Class> config, String... environment) {
+ private void load(Class>[] configs, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- if (config != null) {
- ctx.register(config);
+ EnvironmentTestUtils.addEnvironment(ctx, environment);
+ if (configs != null) {
+ ctx.register(configs);
}
- TestPropertySourceUtils.addInlinedPropertiesToEnvironment(ctx, environment);
ctx.register(JmxAutoConfiguration.class, IntegrationAutoConfiguration.class);
ctx.refresh();
this.context = ctx;
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index 591be0d4e4..3e5bb1617c 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -890,6 +890,10 @@ content into your application; rather pick only the properties that you need.
spring.batch.schema=classpath:org/springframework/batch/core/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
spring.batch.table-prefix= # Table prefix for all the batch meta-data tables.
+ # SPRING INTEGRATION ({sc-spring-boot-autoconfigure}/integration/IntegrationProperties.{sc-ext}[IntegrationProperties])
+ spring.integration.jdbc.initializer.enabled=false # Create the required integration tables on startup.
+ spring.integration.jdbc.schema=classpath:org/springframework/integration/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
+
# JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties])
spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations.
spring.jms.listener.acknowledge-mode= # Acknowledge mode of the container. By default, the listener is transacted with automatic acknowledgment.
diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index 9a159859b5..e162a9edd1 100644
--- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -5113,10 +5113,23 @@ Spring Boot offers several conveniences for working with Spring Integration, inc
the `spring-boot-starter-integration` '`Starter`'. Spring Integration provides
abstractions over messaging and also other transports such as HTTP, TCP etc. If Spring
Integration is available on your classpath it will be initialized through the
-`@EnableIntegration` annotation. Message processing statistics will be published over JMX
-if `'spring-integration-jmx'` is also on the classpath. See the
+`@EnableIntegration` annotation.
+
+Spring Boot will also configure some features that are triggered by the presence of
+additional Spring Integration modules. Message processing statistics will be published
+over JMX if `'spring-integration-jmx'` is also on the classpath. If
+`'spring-integration-jdbc'` is available, the default database schema can be created
+on startup:
+
+[source,properties,indent=0]
+----
+ spring.integration.jdbc.initializer.enabled=true
+----
+
+See the
{sc-spring-boot-autoconfigure}/integration/IntegrationAutoConfiguration.{sc-ext}[`IntegrationAutoConfiguration`]
-class for more details.
+and {sc-spring-boot-autoconfigure}/integration/IntegrationProperties.{sc-ext}[`IntegrationProperties`]
+classes for more details.