diff --git a/src/main/java/sample/endless/SampleEndlessApplication.java b/src/main/java/sample/endless/SampleEndlessApplication.java index 2ce8f7d..e1f09fe 100644 --- a/src/main/java/sample/endless/SampleEndlessApplication.java +++ b/src/main/java/sample/endless/SampleEndlessApplication.java @@ -16,73 +16,21 @@ package sample.endless; -import java.util.concurrent.CountDownLatch; - -import javax.annotation.PreDestroy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.stereotype.Service; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; @SpringBootApplication +@EnableScheduling public class SampleEndlessApplication { - // This simple example shows how a spring application can start and continuously does - // "something" until the application is stopped or interrupted. - // In this example a scheduled, non-blocking thread is logging. - - private static final Logger LOG = LoggerFactory.getLogger(SampleEndlessApplication.class); - - /** - * A waiting repositories to keep the application alive as long as no shutdown was initiated. - */ - @Service - public class ShutdownService { - - private final CountDownLatch countDownLatch; - - public ShutdownService() { - this.countDownLatch = new CountDownLatch(1); - } - - /** - * Will release the blocking {@link #await()}. - */ - @PreDestroy - void countDown() { - this.countDownLatch.countDown(); - } - - /** - * This method is blocking until the application is shutting down. - * - * @throws InterruptedException if the waiting thread got interrupted - */ - void await() throws InterruptedException { - this.countDownLatch.await(); - } + @Scheduled(fixedDelay = 60000L) + public void doNothing() { + // nothing to do here - prevents the application from shutting down } public static void main(final String[] args) { - final ConfigurableApplicationContext ctx = SpringApplication.run(SampleEndlessApplication.class, args); - - // keep the application from exiting the main thread, the running logic is non-blocking - try { - // If the shutdown (hook) is triggered, the Spring Application will close its context and all - // "@PreDestroy" methods will be called. - // Thus leading to the ShutdownService releasing the waiting thread and the application shuts down. - final ShutdownService shutdownService = ctx.getBean(ShutdownService.class); - shutdownService.await(); - - LOG.info("Application shutting down."); - } catch (final InterruptedException e) { - // The main thread was interrupted. Close the context gracefully. - LOG.info("Application thread interrupted. Shutting down."); - ctx.close(); - Thread.currentThread().interrupt(); - } + SpringApplication.run(SampleEndlessApplication.class, args); } } diff --git a/src/main/java/sample/endless/repositories/RecordRepository.java b/src/main/java/sample/endless/repositories/RecordRepository.java index 0b162ea..9fc8d44 100644 --- a/src/main/java/sample/endless/repositories/RecordRepository.java +++ b/src/main/java/sample/endless/repositories/RecordRepository.java @@ -18,15 +18,8 @@ import sample.endless.entities.Record; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - import org.springframework.data.repository.CrudRepository; public interface RecordRepository extends CrudRepository { diff --git a/src/test/java/sample/endless/repositories/RecordRepositoryTest.java b/src/test/java/sample/endless/repositories/RecordRepositoryTest.java index d4b2d34..b8bc89d 100644 --- a/src/test/java/sample/endless/repositories/RecordRepositoryTest.java +++ b/src/test/java/sample/endless/repositories/RecordRepositoryTest.java @@ -17,17 +17,21 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import static org.hamcrest.Matchers.is; @RunWith(SpringRunner.class) @SpringBootTest() public class RecordRepositoryTest { - static final int NUMBER_OF_RECORDS = 20000; + static final int NUMBER_OF_RECORDS = 100000; @Autowired RecordRepository recordRepository; @Test + @Transactional public void readAll_the_object_is_already_closed() { // setup System.out.println("Prepare all data."); @@ -40,7 +44,7 @@ public void readAll_the_object_is_already_closed() { // -- SHOULD NOT FAIL try (final Stream stream = recordRepository.readAllByIdNotNull()) { stream.forEach(record -> { - if (record.getId() % 250 == 0) { + if (record.getId() % 1000L == 0L) { System.out.println("Handling Record No: " + record.getId()); } final long sum = record.getWrappedValues().stream() @@ -51,7 +55,7 @@ public void readAll_the_object_is_already_closed() { } // then - Assert.assertEquals(15L * NUMBER_OF_RECORDS, counter); + Assert.assertThat(15L * NUMBER_OF_RECORDS, is(counter.get())); } private void prepareAllData() {