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