How do I provide my own DateTimeProvider with Spring Data

Viewed 43

I am trying to provide a transactionally consistent set of datetimes

import org.springframework.beans.factory.ObjectFactory
import org.springframework.beans.factory.config.BeanFactoryPostProcessor
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Scope
import org.springframework.data.auditing.DateTimeProvider
import org.springframework.transaction.support.SimpleTransactionScope
import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.util.Optional

@Configuration
open class TransactionScopeTimeConfiguration {

  @Bean
  open fun transactionBFPP(): BeanFactoryPostProcessor =
    BeanFactoryPostProcessor { it.registerScope("transaction", SimpleTransactionScope()) }

  @Bean
  @Scope("transaction")
  open fun nowInstant(): Instant = Instant.now()

  @Bean
  @Scope("transaction")
  open fun nowOffsetDateTime(nowInstant: Instant): OffsetDateTime = nowInstant.atOffset(ZoneOffset.UTC)

  @Bean
  open fun transactionDateTimeProvider(factory: ObjectFactory<OffsetDateTime>): DateTimeProvider =
    DateTimeProvider { Optional.of(factory.`object`) }
}

However, when debugging my test I note that the function inside of transactionDateTimeProvider is never called (the creation of the Bean is)

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest

@DataJpaTest
@Import(TransactionScopeTimeConfiguration)
internal open class ExceptionDaoTest {
  @Test
  fun save(@Autowired exceptionDao: ExceptionJpaDao) {
    val toCreate = ExceptionEntity("someid")
    val saved = exceptionDao.save(toCreate)

    assertThat(saved).isInstanceOf(ExceptionEntity::class.java)
      .extracting({ it.id }, { it.businessDivisionId })
      .containsExactly(toCreate.id, "someid")
      .doesNotContainNull()

    assertThat(saved.lastModifiedOn).isSameAs(saved.createdOn)
  }
}

The test actually passes, but I haven't actually exercised this functionality in this test. It's important that any other datetimes are transactionally consistent with the audit traits.

0 Answers
Related