diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 39a264756b6..d2b1de82797 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -167,6 +167,11 @@
jedis
true
+
+ org.liquibase
+ liquibase-core
+ true
+
org.springframework.security
spring-security-acl
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java
new file mode 100644
index 00000000000..06d1b6fe8d1
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-2014 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.liquibase;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+
+import liquibase.integration.spring.SpringLiquibase;
+
+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.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.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.Assert;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for Liquibase.
+ *
+ * @author Marcel Overdijk
+ */
+@Configuration
+@ConditionalOnClass(SpringLiquibase.class)
+@AutoConfigureAfter(DataSourceAutoConfiguration.class)
+public class LiquibaseAutoConfiguration {
+
+ @Configuration
+ @ConditionalOnMissingBean(SpringLiquibase.class)
+ @EnableConfigurationProperties(LiquibaseProperties.class)
+ public static class LiquibaseConfiguration {
+
+ @Autowired
+ private LiquibaseProperties properties = new LiquibaseProperties();
+
+ @Autowired
+ private ResourceLoader resourceLoader = new DefaultResourceLoader();
+
+ @Autowired
+ private DataSource dataSource;
+
+ @PostConstruct
+ public void checkChangelogExists() {
+ if (this.properties.isCheckChangeLogLocation()) {
+ Resource resource = this.resourceLoader.getResource(this.properties.getChangeLog());
+ Assert.state(resource.exists(), "Cannot find changelog location: "
+ + resource + " (please add changelog or check your Liquibase configuration)");
+ }
+ }
+
+ @Bean
+ public SpringLiquibase liquibase() {
+ SpringLiquibase liquibase = new SpringLiquibase();
+ liquibase.setChangeLog(this.properties.getChangeLog());
+ liquibase.setContexts(this.properties.getContexts());
+ liquibase.setDataSource(dataSource);
+ liquibase.setDefaultSchema(this.properties.getDefaultSchema());
+ liquibase.setDropFirst(this.properties.isDropFirst());
+ liquibase.setShouldRun(this.properties.isShouldRun());
+ return liquibase;
+ }
+ }
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseProperties.java
new file mode 100644
index 00000000000..611e7488b56
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseProperties.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-2014 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.liquibase;
+
+import javax.validation.constraints.NotNull;
+
+import liquibase.integration.spring.SpringLiquibase;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Configuration properties to configure {@link SpringLiquibase}.
+ *
+ * @author Marcel Overdijk
+ */
+@ConfigurationProperties(prefix = "spring.liquibase", ignoreUnknownFields = false)
+public class LiquibaseProperties {
+
+ @NotNull
+ private String changeLog = "classpath:/db/changelog/db.changelog-master.yaml";
+
+ private boolean checkChangeLogLocation = true;
+
+ private String contexts;
+
+ private String defaultSchema;
+
+ private boolean dropFirst = false;
+
+ private boolean shouldRun = true;
+
+ public String getChangeLog() {
+ return changeLog;
+ }
+
+ public void setChangeLog(String changeLog) {
+ this.changeLog = changeLog;
+ }
+
+ public boolean isCheckChangeLogLocation() {
+ return checkChangeLogLocation;
+ }
+
+ public void setCheckChangeLogLocation(boolean checkChangeLogLocation) {
+ this.checkChangeLogLocation = checkChangeLogLocation;
+ }
+
+ public String getContexts() {
+ return contexts;
+ }
+
+ public void setContexts(String contexts) {
+ this.contexts = contexts;
+ }
+
+ public String getDefaultSchema() {
+ return defaultSchema;
+ }
+
+ public void setDefaultSchema(String defaultSchema) {
+ this.defaultSchema = defaultSchema;
+ }
+
+ public boolean isDropFirst() {
+ return dropFirst;
+ }
+
+ public void setDropFirst(boolean dropFirst) {
+ this.dropFirst = dropFirst;
+ }
+
+ public boolean isShouldRun() {
+ return shouldRun;
+ }
+
+ public void setShouldRun(boolean shouldRun) {
+ this.shouldRun = shouldRun;
+ }
+}
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 14dda161661..d6ae3f7b989 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -19,6 +19,7 @@ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
+org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration,\
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java
new file mode 100644
index 00000000000..bd854539a3d
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-2014 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.liquibase;
+
+import liquibase.integration.spring.SpringLiquibase;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.boot.test.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link LiquibaseAutoConfiguration}.
+ *
+ * @author Marcel Overdijk
+ */
+public class LiquibaseAutoConfigurationTests {
+
+ @Rule
+ public ExpectedException expected = ExpectedException.none();
+
+ private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void testNoDataSource() throws Exception {
+ this.context.register(LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.expected.expect(BeanCreationException.class);
+ this.expected.expectMessage("No qualifying bean");
+ this.expected.expectMessage("DataSource");
+ this.context.refresh();
+ }
+
+ @Test
+ public void testDefaultSpringLiquibase() throws Exception {
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
+ assertEquals("classpath:/db/changelog/db.changelog-master.yaml", liquibase.getChangeLog());
+ assertNull(liquibase.getContexts());
+ assertNull(liquibase.getDefaultSchema());
+ assertFalse(liquibase.isDropFirst());
+ }
+
+ @Test
+ public void testOverrideChangeLog() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.liquibase.change-log:classpath:/db/changelog/db.changelog-override.xml");
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
+ assertEquals("classpath:/db/changelog/db.changelog-override.xml", liquibase.getChangeLog());
+ }
+
+ @Test
+ public void testOverrideContexts() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.liquibase.contexts:test, production");
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
+ assertEquals("test, production", liquibase.getContexts());
+ }
+
+ @Test
+ public void testOverrideDefaultSchema() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.liquibase.default-schema:public");
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
+ assertEquals("public", liquibase.getDefaultSchema());
+ }
+
+ @Test
+ public void testOverrideDropFirst() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.liquibase.drop-first:true");
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
+ assertTrue(liquibase.isDropFirst());
+ }
+
+ @Test(expected = BeanCreationException.class)
+ public void testChangeLogDoesNotExist() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.liquibase.change-log:classpath:/no-such-changelog.yaml");
+ this.context.register(EmbeddedDataSourceConfiguration.class,
+ LiquibaseAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ }
+}
diff --git a/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-master.yaml b/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-master.yaml
new file mode 100644
index 00000000000..134b17b543e
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-master.yaml
@@ -0,0 +1,20 @@
+databaseChangeLog:
+ - changeSet:
+ id: 1
+ author: marceloverdijk
+ changes:
+ - createTable:
+ tableName: customer
+ columns:
+ - column:
+ name: id
+ type: int
+ autoIncrement: true
+ constraints:
+ primaryKey: true
+ nullable: false
+ - column:
+ name: name
+ type: varchar(50)
+ constraints:
+ nullable: false
diff --git a/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-override.xml b/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-override.xml
new file mode 100644
index 00000000000..2e418cb347d
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/db/changelog/db.changelog-override.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 a9232a8f958..98be7cdedb3 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -158,6 +158,13 @@ content into your application; rather pick only the properties that you need.
spring.jpa.hibernate.naming-strategy= # naming classname
spring.jpa.hibernate.ddl-auto= # defaults to create-drop for embedded dbs
+ # LIQUIBASE ({sc-spring-boot-autoconfigure}/liquibase/LiquibaseProperties.{sc-ext}[LiquibaseProperties])
+ spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml
+ spring.liquibase.contexts= # runtime contexts to use
+ spring.liquibase.default-schema= # default database schema to use
+ spring.liquibase.drop-first=false
+ spring.liquibase.should-run=true
+
# JMX
spring.jmx.enabled=true # Expose MBeans from Spring
@@ -170,7 +177,6 @@ content into your application; rather pick only the properties that you need.
spring.rabbitmq.virtualhost=
spring.rabbitmq.dynamic=
-
# REDIS ({sc-spring-boot-autoconfigure}/redis/RedisProperties.{sc-ext}[RedisProperties])
spring.redis.host=localhost # server host
spring.redis.password= # server password
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc b/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc
index 1a81322ee4b..3aef5ae8395 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc
@@ -56,6 +56,9 @@ The following auto-configuration classes are from the `spring-boot-autoconfigure
|{sc-spring-boot-autoconfigure}/data/JpaRepositoriesAutoConfiguration.{sc-ext}[JpaRepositoriesAutoConfiguration]
|{dc-spring-boot-autoconfigure}/data/JpaRepositoriesAutoConfiguration.{dc-ext}[javadoc]
+|{sc-spring-boot-autoconfigure}/liquibase/LiquibaseAutoConfiguration.{sc-ext}[LiquibaseAutoConfiguration]
+|{dc-spring-boot-autoconfigure}/liquibase/LiquibaseAutoConfiguration.{dc-ext}[javadoc]
+
|{sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration]
|{dc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{dc-ext}[javadoc]
diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc
index de13c412f12..e7ca6d215c9 100644
--- a/spring-boot-docs/src/main/asciidoc/howto.adoc
+++ b/spring-boot-docs/src/main/asciidoc/howto.adoc
@@ -1097,6 +1097,21 @@ independence: usually only one or at most couple of platforms is needed.
+[[howto-execute-liquibase-database-migrations-on-startup]]
+==== Execute Liquibase database migrations on startup
+To automatically run Liquibase database migrations on startup, add the
+`spring-boot-starter-liquibase` to your classpath.
+
+The master change log is by default read from `db/changelog/db.changelog-master.yaml` but
+can be set using `spring.liquibase.change-log`. See
+{sc-spring-boot-autoconfigure}/liquibase/LiquibaseProperties.{sc-ext}[`LiquibaseProperties`]
+for details of available settings like contexts, default schema etc.
+
+There is a {github-code}/spring-boot-samples/spring-boot-sample-liquibase[Liquibase sample] so
+you can see how to set things up.
+
+
+
[[howto-batch-applications]]
== Batch applications
diff --git a/spring-boot-docs/src/main/asciidoc/index.adoc b/spring-boot-docs/src/main/asciidoc/index.adoc
index e7d603074f2..e6f5d977c2e 100644
--- a/spring-boot-docs/src/main/asciidoc/index.adoc
+++ b/spring-boot-docs/src/main/asciidoc/index.adoc
@@ -1,5 +1,5 @@
= Spring Boot Reference Guide
-Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
+Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson; Marcel Overdijk;
:doctype: book
:toc:
:toclevels: 4
diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
index 9feef384d5a..88096747841 100644
--- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
+++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
@@ -238,6 +238,9 @@ and Hibernate.
|`spring-boot-starter-jdbc`
|JDBC Database support.
+|`spring-boot-starter-liquibase`
+|Support for Liquibase database migrations.
+
|`spring-boot-starter-mobile`
|Support for `spring-mobile`
diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml
index 83e0f326365..9def9bce5e6 100644
--- a/spring-boot-samples/pom.xml
+++ b/spring-boot-samples/pom.xml
@@ -34,6 +34,7 @@
spring-boot-sample-data-rest
spring-boot-sample-integration
spring-boot-sample-jetty
+ spring-boot-sample-liquibase
spring-boot-sample-profile
spring-boot-sample-secure
spring-boot-sample-servlet
diff --git a/spring-boot-samples/spring-boot-sample-liquibase/pom.xml b/spring-boot-samples/spring-boot-sample-liquibase/pom.xml
new file mode 100644
index 00000000000..f0522496bee
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-liquibase/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-samples
+ 1.0.2.BUILD-SNAPSHOT
+
+ spring-boot-sample-liquibase
+ Spring Boot Liquibase Sample
+ Spring Boot Liquibase Sample
+ 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-liquibase
+
+
+ org.hsqldb
+ hsqldb
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-boot-samples/spring-boot-sample-liquibase/src/main/java/sample/liquibase/SampleLiquibaseApplication.java b/spring-boot-samples/spring-boot-sample-liquibase/src/main/java/sample/liquibase/SampleLiquibaseApplication.java
new file mode 100644
index 00000000000..7fc1fd02644
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-liquibase/src/main/java/sample/liquibase/SampleLiquibaseApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012-2013 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 sample.liquibase;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan
+@EnableAutoConfiguration
+public class SampleLiquibaseApplication {
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(SampleLiquibaseApplication.class, args);
+ }
+}
diff --git a/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/application.properties
new file mode 100644
index 00000000000..bb3f2d169b4
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.jpa.hibernate.ddl-auto: none
diff --git a/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml b/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml
new file mode 100644
index 00000000000..b0ecfe9a25c
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml
@@ -0,0 +1,38 @@
+databaseChangeLog:
+ - changeSet:
+ id: 1
+ author: marceloverdijk
+ changes:
+ - createTable:
+ tableName: person
+ columns:
+ - column:
+ name: id
+ type: int
+ autoIncrement: true
+ constraints:
+ primaryKey: true
+ nullable: false
+ - column:
+ name: first_name
+ type: varchar(255)
+ constraints:
+ nullable: false
+ - column:
+ name: last_name
+ type: varchar(255)
+ constraints:
+ nullable: false
+ - changeSet:
+ id: 2
+ author: marceloverdijk
+ changes:
+ - insert:
+ tableName: person
+ columns:
+ - column:
+ name: first_name
+ value: Marcel
+ - column:
+ name: last_name
+ value: Overdijk
diff --git a/spring-boot-samples/spring-boot-sample-liquibase/src/test/java/sample/liquibase/SampleLiquibaseApplicationTests.java b/spring-boot-samples/spring-boot-sample-liquibase/src/test/java/sample/liquibase/SampleLiquibaseApplicationTests.java
new file mode 100644
index 00000000000..f6337dc0a5f
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-liquibase/src/test/java/sample/liquibase/SampleLiquibaseApplicationTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-2014 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 sample.liquibase;
+
+import java.net.ConnectException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.boot.test.OutputCapture;
+import org.springframework.core.NestedCheckedException;
+
+import static org.junit.Assert.assertTrue;
+
+public class SampleLiquibaseApplicationTests {
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ @Test
+ public void testDefaultSettings() throws Exception {
+ try {
+ SampleLiquibaseApplication.main(new String[0]);
+ }
+ catch (IllegalStateException ex) {
+ if (serverNotRunning(ex)) {
+ return;
+ }
+ }
+ String output = this.outputCapture.toString();
+ assertTrue("Wrong output: " + output,
+ output.contains("Successfully acquired change log lock") &&
+ output.contains("Creating database history table with name: PUBLIC.DATABASECHANGELOG") &&
+ output.contains("Table person created") &&
+ output.contains("ChangeSet classpath:/db/changelog/db.changelog-master.yaml::1::marceloverdijk ran successfully") &&
+ output.contains("New row inserted into person") &&
+ output.contains("ChangeSet classpath:/db/changelog/db.changelog-master.yaml::2::marceloverdijk ran successfully") &&
+ output.contains("Successfully released change log lock"));
+ }
+
+ private boolean serverNotRunning(IllegalStateException ex) {
+ @SuppressWarnings("serial")
+ NestedCheckedException nested = new NestedCheckedException("failed", ex) {
+ };
+ if (nested.contains(ConnectException.class)) {
+ Throwable root = nested.getRootCause();
+ if (root.getMessage().contains("Connection refused")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml
index 5db4ec71f42..f8067c5defc 100644
--- a/spring-boot-starters/pom.xml
+++ b/spring-boot-starters/pom.xml
@@ -33,6 +33,7 @@
spring-boot-starter-integration
spring-boot-starter-jdbc
spring-boot-starter-jetty
+ spring-boot-starter-liquibase
spring-boot-starter-logging
spring-boot-starter-log4j
spring-boot-starter-mobile
diff --git a/spring-boot-starters/spring-boot-starter-liquibase/pom.xml b/spring-boot-starters/spring-boot-starter-liquibase/pom.xml
new file mode 100644
index 00000000000..c7d48221751
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-liquibase/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starters
+ 1.0.2.BUILD-SNAPSHOT
+
+ spring-boot-starter-liquibase
+ Spring Boot Liquibase Starter
+ Spring Boot Liquibase Starter
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ ${project.groupId}
+ spring-boot-starter-jdbc
+ ${project.version}
+
+
+ org.liquibase
+ liquibase-core
+
+
+
diff --git a/spring-boot-starters/spring-boot-starter-liquibase/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-liquibase/src/main/resources/META-INF/spring.provides
new file mode 100644
index 00000000000..cec4231369a
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-liquibase/src/main/resources/META-INF/spring.provides
@@ -0,0 +1 @@
+provides: liquibase-core
\ No newline at end of file
diff --git a/spring-boot-starters/spring-boot-starter-parent/pom.xml b/spring-boot-starters/spring-boot-starter-parent/pom.xml
index a18cfc637a8..7ffc194cec1 100644
--- a/spring-boot-starters/spring-boot-starter-parent/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-parent/pom.xml
@@ -121,6 +121,11 @@
spring-boot-starter-jetty
${spring-boot.version}
+
+ org.springframework.boot
+ spring-boot-starter-liquibase
+ ${spring-boot.version}
+
org.springframework.boot
spring-boot-starter-logging