From fd7d35a826bec6b42688c39e330b2f88b33ccb1f Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Thu, 18 Jun 2015 11:08:52 +0200 Subject: [PATCH] #106 - Add example with CompletableFuture and Java 8 for JPA. Simple test case that demonstrates CompletableFuture. Original pull request: #106. --- jpa/java8/pom.xml | 6 ++- .../jpa/java8/AuditingConfiguration.java | 2 + .../springdata/jpa/java8/Customer.java | 15 ++++++-- .../jpa/java8/CustomerRepository.java | 6 +++ .../jpa/java8/Java8IntegrationTests.java | 38 ++++++++++++++++++- .../src/test/resources/application.properties | 4 ++ jpa/java8/src/test/resources/logback.xml | 18 --------- jpa/pom.xml | 5 +++ 8 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 jpa/java8/src/test/resources/application.properties delete mode 100644 jpa/java8/src/test/resources/logback.xml diff --git a/jpa/java8/pom.xml b/jpa/java8/pom.xml index 9685749f..5f97c95d 100644 --- a/jpa/java8/pom.xml +++ b/jpa/java8/pom.xml @@ -8,7 +8,11 @@ 1.0.0.BUILD-SNAPSHOT + + 4.2.0.BUILD-SNAPSHOT + Gosling-BUILD-SNAPSHOT + + spring-data-jpa-java8 Spring Data JPA - Java 8 specific features - \ No newline at end of file diff --git a/jpa/java8/src/main/java/example/springdata/jpa/java8/AuditingConfiguration.java b/jpa/java8/src/main/java/example/springdata/jpa/java8/AuditingConfiguration.java index d4b412bc..528449b7 100644 --- a/jpa/java8/src/main/java/example/springdata/jpa/java8/AuditingConfiguration.java +++ b/jpa/java8/src/main/java/example/springdata/jpa/java8/AuditingConfiguration.java @@ -20,8 +20,10 @@ import org.springframework.boot.orm.jpa.EntityScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableAsync; @Configuration +@EnableAsync @EnableAutoConfiguration @EntityScan(basePackageClasses = { AuditingConfiguration.class, Jsr310JpaConverters.class }) @EnableJpaAuditing diff --git a/jpa/java8/src/main/java/example/springdata/jpa/java8/Customer.java b/jpa/java8/src/main/java/example/springdata/jpa/java8/Customer.java index 72b38c92..05f47919 100644 --- a/jpa/java8/src/main/java/example/springdata/jpa/java8/Customer.java +++ b/jpa/java8/src/main/java/example/springdata/jpa/java8/Customer.java @@ -15,19 +15,26 @@ */ package example.springdata.jpa.java8; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + import javax.persistence.Entity; /** * @author Oliver Gierke + * @author Thomas Darimont */ @Entity +@Getter +@ToString +@AllArgsConstructor public class Customer extends AbstractEntity { String firstname, lastname; - public Customer(String firstname, String lastname) { - - this.firstname = firstname; - this.lastname = lastname; + protected Customer() { + this.firstname = null; + this.lastname = null; } } diff --git a/jpa/java8/src/main/java/example/springdata/jpa/java8/CustomerRepository.java b/jpa/java8/src/main/java/example/springdata/jpa/java8/CustomerRepository.java index 4231e518..008e4150 100644 --- a/jpa/java8/src/main/java/example/springdata/jpa/java8/CustomerRepository.java +++ b/jpa/java8/src/main/java/example/springdata/jpa/java8/CustomerRepository.java @@ -15,12 +15,15 @@ */ package example.springdata.jpa.java8; +import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.Repository; +import org.springframework.scheduling.annotation.Async; /** * Repository to manage {@link Customer} instances. @@ -80,4 +83,7 @@ public interface CustomerRepository extends Repository { * @return */ Stream findAllByLastnameIsNotNull(); + + @Async + CompletableFuture> readAllBy(); } diff --git a/jpa/java8/src/test/java/example/springdata/jpa/java8/Java8IntegrationTests.java b/jpa/java8/src/test/java/example/springdata/jpa/java8/Java8IntegrationTests.java index 576fdc88..2e59c7a9 100644 --- a/jpa/java8/src/test/java/example/springdata/jpa/java8/Java8IntegrationTests.java +++ b/jpa/java8/src/test/java/example/springdata/jpa/java8/Java8IntegrationTests.java @@ -19,14 +19,17 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** @@ -36,7 +39,7 @@ import org.springframework.transaction.annotation.Transactional; * @author Thomas Darimont */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = AuditingConfiguration.class) +@SpringApplicationConfiguration(classes = AuditingConfiguration.class) @Transactional public class Java8IntegrationTests { @@ -99,4 +102,35 @@ public class Java8IntegrationTests { assertThat(stream.collect(Collectors.toList()), hasItems(customer1, customer2)); } } + + /** + * Here we demonstrate the usage of CompletableFuture as a result wrapper for asynchronous + * Repository query methods. + * + * Note that we need to disable the surrounding TX to be able to asynchronously read the wirtten + * data from from another thread within the same test method. + */ + @Test + @Transactional(propagation = Propagation.NOT_SUPPORTED) + public void supportsCompletableFuturesAsReturnTypeWrapper() throws Exception { + + repository.save(new Customer("Customer1", "Foo")); + repository.save(new Customer("Customer2", "Bar")); + + CompletableFuture future = repository.readAllBy().thenAccept(customers -> { + + assertThat(customers, hasSize(2)); + + customers.forEach(System.out::println); + System.out.println("Completed!"); + }); + + while (!future.isDone()) { + System.out.println("waiting..."); + TimeUnit.MILLISECONDS.sleep(500); + } + + future.get(); + System.out.println("Done"); + } } diff --git a/jpa/java8/src/test/resources/application.properties b/jpa/java8/src/test/resources/application.properties new file mode 100644 index 00000000..f1e8a3d1 --- /dev/null +++ b/jpa/java8/src/test/resources/application.properties @@ -0,0 +1,4 @@ +#logging.level.org.springframework=INFO +#logging.level.org.springframework.orm=TRACE +#logging.level.org.springframework.transaction=TRACE +#logging.level.org.hsqldb=TRACE \ No newline at end of file diff --git a/jpa/java8/src/test/resources/logback.xml b/jpa/java8/src/test/resources/logback.xml deleted file mode 100644 index b48bf208..00000000 --- a/jpa/java8/src/test/resources/logback.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - %d %5p %40.40c:%4L - %m%n - - - - - - - - - - - - \ No newline at end of file diff --git a/jpa/pom.xml b/jpa/pom.xml index f5a0818a..c3f827ef 100644 --- a/jpa/pom.xml +++ b/jpa/pom.xml @@ -39,6 +39,11 @@ joda-time + + + + + org.hsqldb hsqldb