diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml
index e4cddbedf6..6bd30f875a 100644
--- a/spring-boot-samples/pom.xml
+++ b/spring-boot-samples/pom.xml
@@ -38,6 +38,8 @@
spring-boot-sample-hornetq
spring-boot-sample-integration
spring-boot-sample-jetty
+ spring-boot-sample-jta-atomikos
+ spring-boot-sample-jta-bitronix
spring-boot-sample-liquibase
spring-boot-sample-parent-context
spring-boot-sample-profile
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/pom.xml b/spring-boot-samples/spring-boot-sample-jta-atomikos/pom.xml
new file mode 100644
index 0000000000..bc7c05ce6d
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-samples
+ 1.2.0.BUILD-SNAPSHOT
+
+ spring-boot-sample-jta-atomikos
+ Spring Boot Atomikos JTA Sample
+ Spring Boot Atomikos JTA Sample
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ org.springframework
+ spring-jms
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-jta-atomikos
+
+
+ org.springframework.boot
+ spring-boot-starter-hornetq
+
+
+ org.hornetq
+ hornetq-jms-server
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Account.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Account.java
new file mode 100644
index 0000000000..d40c546003
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Account.java
@@ -0,0 +1,43 @@
+/*
+ * 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.atomikos;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Account {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String username;
+
+ Account() {
+ }
+
+ public Account(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountRepository.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountRepository.java
new file mode 100644
index 0000000000..6b88cb4cb4
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountRepository.java
@@ -0,0 +1,23 @@
+/*
+ * 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.atomikos;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface AccountRepository extends JpaRepository {
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountService.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountService.java
new file mode 100644
index 0000000000..5f84d308f2
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/AccountService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.atomikos;
+
+import javax.transaction.Transactional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.stereotype.Service;
+
+@Service
+@Transactional
+public class AccountService {
+
+ private final JmsTemplate jmsTemplate;
+
+ private final AccountRepository accountRepository;
+
+ @Autowired
+ public AccountService(JmsTemplate jmsTemplate, AccountRepository accountRepository) {
+ this.jmsTemplate = jmsTemplate;
+ this.accountRepository = accountRepository;
+ }
+
+ public void createAccountAndNotify(String username) {
+ this.jmsTemplate.convertAndSend("accounts", username);
+ this.accountRepository.save(new Account(username));
+ if ("error".equals(username)) {
+ throw new RuntimeException("Simulated error");
+ }
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Messages.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Messages.java
new file mode 100644
index 0000000000..d6f185f28b
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/Messages.java
@@ -0,0 +1,30 @@
+/*
+ * 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.atomikos;
+
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Messages {
+
+ @JmsListener(destination = "accounts")
+ public void onMessage(String content) {
+ System.out.println("----> " + content);
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/SampleAtomikosApplication.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/SampleAtomikosApplication.java
new file mode 100644
index 0000000000..e0094a3e4a
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/java/sample/atomikos/SampleAtomikosApplication.java
@@ -0,0 +1,50 @@
+/*
+ * 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.atomikos;
+
+import java.io.Closeable;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan
+@EnableAutoConfiguration
+public class SampleAtomikosApplication {
+
+ public static void main(String[] args) throws Exception {
+ ApplicationContext context = SpringApplication.run(
+ SampleAtomikosApplication.class, args);
+ AccountService service = context.getBean(AccountService.class);
+ AccountRepository repository = context.getBean(AccountRepository.class);
+ service.createAccountAndNotify("josh");
+ System.out.println("Count is " + repository.count());
+ try {
+ service.createAccountAndNotify("error");
+ }
+ catch (Exception ex) {
+ System.out.println(ex.getMessage());
+ }
+ System.out.println("Count is " + repository.count());
+ Thread.sleep(100);
+ ((Closeable) context).close();
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/resources/application.properties
new file mode 100644
index 0000000000..62806e0ea8
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+spring.hornetq.mode=embedded
+spring.hornetq.embedded.enabled=true
+spring.hornetq.embedded.queues=accounts
+
+logging.level.com.atomikos=WARN
diff --git a/spring-boot-samples/spring-boot-sample-jta-atomikos/src/test/java/sample/atomikos/SampleAtomikosApplicationTests.java b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/test/java/sample/atomikos/SampleAtomikosApplicationTests.java
new file mode 100644
index 0000000000..3950c3dfa8
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-atomikos/src/test/java/sample/atomikos/SampleAtomikosApplicationTests.java
@@ -0,0 +1,71 @@
+/*
+ * 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.atomikos;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.core.SubstringMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.boot.test.OutputCapture;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Basic integration tests for demo application.
+ *
+ * @author Phillip Webb
+ */
+public class SampleAtomikosApplicationTests {
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ @Test
+ public void testTransactionRollback() throws Exception {
+ SampleAtomikosApplication.main(new String[] {});
+ String expected = "";
+ expected += "----> josh\n";
+ expected += "Count is 1\n";
+ expected += "Simulated error\n";
+ expected += "Count is 1\n";
+ assertThat(this.outputCapture.toString(), containsString(expected));
+ assertThat(this.outputCapture.toString(), containsStringOnce("---->"));
+ }
+
+ private Matcher super String> containsStringOnce(String s) {
+ return new SubstringMatcher(s) {
+
+ @Override
+ protected String relationship() {
+ return "containing once";
+ }
+
+ @Override
+ protected boolean evalSubstringOf(String s) {
+ int i = 0;
+ while (s.contains(this.substring)) {
+ s = s.substring(s.indexOf(this.substring) + this.substring.length());
+ i++;
+ }
+ return i == 1;
+ }
+
+ };
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/pom.xml b/spring-boot-samples/spring-boot-sample-jta-bitronix/pom.xml
new file mode 100644
index 0000000000..a88a235c53
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-samples
+ 1.2.0.BUILD-SNAPSHOT
+
+ spring-boot-sample-jta-bitronix
+ Spring Boot Bitronix JTA Sample
+ Spring Boot Bitronix JTA Sample
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ org.springframework
+ spring-jms
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-jta-bitronix
+
+
+ org.springframework.boot
+ spring-boot-starter-hornetq
+
+
+ org.hornetq
+ hornetq-jms-server
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Account.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Account.java
new file mode 100644
index 0000000000..183e4c595a
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Account.java
@@ -0,0 +1,43 @@
+/*
+ * 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.bitronix;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Account {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String username;
+
+ Account() {
+ }
+
+ public Account(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountRepository.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountRepository.java
new file mode 100644
index 0000000000..53978fa7d0
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountRepository.java
@@ -0,0 +1,23 @@
+/*
+ * 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.bitronix;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface AccountRepository extends JpaRepository {
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountService.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountService.java
new file mode 100644
index 0000000000..752adf7611
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/AccountService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.bitronix;
+
+import javax.transaction.Transactional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.stereotype.Service;
+
+@Service
+@Transactional
+public class AccountService {
+
+ private final JmsTemplate jmsTemplate;
+
+ private final AccountRepository accountRepository;
+
+ @Autowired
+ public AccountService(JmsTemplate jmsTemplate, AccountRepository accountRepository) {
+ this.jmsTemplate = jmsTemplate;
+ this.accountRepository = accountRepository;
+ }
+
+ public void createAccountAndNotify(String username) {
+ this.jmsTemplate.convertAndSend("accounts", username);
+ this.accountRepository.save(new Account(username));
+ if ("error".equals(username)) {
+ throw new RuntimeException("Simulated error");
+ }
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Messages.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Messages.java
new file mode 100644
index 0000000000..cdaddd76b6
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/Messages.java
@@ -0,0 +1,30 @@
+/*
+ * 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.bitronix;
+
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Messages {
+
+ @JmsListener(destination = "accounts")
+ public void onMessage(String content) {
+ System.out.println("----> " + content);
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/SampleBitronixApplication.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/SampleBitronixApplication.java
new file mode 100644
index 0000000000..62fb930224
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/java/sample/bitronix/SampleBitronixApplication.java
@@ -0,0 +1,50 @@
+/*
+ * 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.bitronix;
+
+import java.io.Closeable;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan
+@EnableAutoConfiguration
+public class SampleBitronixApplication {
+
+ public static void main(String[] args) throws Exception {
+ ApplicationContext context = SpringApplication.run(
+ SampleBitronixApplication.class, args);
+ AccountService service = context.getBean(AccountService.class);
+ AccountRepository repository = context.getBean(AccountRepository.class);
+ service.createAccountAndNotify("josh");
+ System.out.println("Count is " + repository.count());
+ try {
+ service.createAccountAndNotify("error");
+ }
+ catch (Exception ex) {
+ System.out.println(ex.getMessage());
+ }
+ System.out.println("Count is " + repository.count());
+ Thread.sleep(100);
+ ((Closeable) context).close();
+ }
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/resources/application.properties
new file mode 100644
index 0000000000..ca501b18cc
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+spring.hornetq.mode=embedded
+spring.hornetq.embedded.enabled=true
+spring.hornetq.embedded.queues=accounts
diff --git a/spring-boot-samples/spring-boot-sample-jta-bitronix/src/test/java/sample/bitronix/SampleBitronixApplicationTests.java b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/test/java/sample/bitronix/SampleBitronixApplicationTests.java
new file mode 100644
index 0000000000..096d1719e2
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-jta-bitronix/src/test/java/sample/bitronix/SampleBitronixApplicationTests.java
@@ -0,0 +1,73 @@
+/*
+ * 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.bitronix;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.core.SubstringMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.boot.test.OutputCapture;
+
+import sample.bitronix.SampleBitronixApplication;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Basic integration tests for demo application.
+ *
+ * @author Phillip Webb
+ */
+public class SampleBitronixApplicationTests {
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ @Test
+ public void testTransactionRollback() throws Exception {
+ SampleBitronixApplication.main(new String[] {});
+ String expected = "";
+ expected += "----> josh\n";
+ expected += "Count is 1\n";
+ expected += "Simulated error\n";
+ expected += "Count is 1\n";
+ assertThat(this.outputCapture.toString(), containsString(expected));
+ assertThat(this.outputCapture.toString(), containsStringOnce("---->"));
+ }
+
+ private Matcher super String> containsStringOnce(String s) {
+ return new SubstringMatcher(s) {
+
+ @Override
+ protected String relationship() {
+ return "containing once";
+ }
+
+ @Override
+ protected boolean evalSubstringOf(String s) {
+ int i = 0;
+ while (s.contains(this.substring)) {
+ s = s.substring(s.indexOf(this.substring) + this.substring.length());
+ i++;
+ }
+ return i == 1;
+ }
+
+ };
+ }
+
+}