Tables not created when running unit tests with test profile - spring

For an unknown reason, my unit tests do not work anymore. All of a sudden the tables for my test database are not being created anymore.
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString(SchemaDropperImpl.java:375) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings(SchemaDropperImpl.java:359) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applyConstraintDropping(SchemaDropperImpl.java:331) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata(SchemaDropperImpl.java:230) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop(SchemaDropperImpl.java:154) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:126) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
...
Caused by: org.postgresql.util.PSQLException: ERROR: relation "app_user__user_group" does not exist
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2284) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2003) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:200) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:424) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
..
Let's just say that I didn't change anything, at least not to my best knowledge that should've changed that behavior, but that's just me and my relation with Spring.
So let's dump the necessary information:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT, properties = "spring.profiles.active=test")
public class AppUserRepositoryTest {
private final static Logger LOGGER = LogManager.getLogger(AppUserRepositoryTest.class);
#Autowired
private TestRestTemplate template;
private static String USERS_ENDPOINT = "http://localhost:8080/users/";
private static String GROUPS_ENDPOINT = "http://localhost:8080/groups/";
private static String USER_LOGIN = "http://localhost:8080/oauth/token/";
#Autowired
private WebApplicationContext wac;
#Autowired
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
LOGGER.info("Setup done.");
}
#Test
#DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
public void whenCreateAppUser() {
Client client = new Client();
AppUser appUser = client.registerUser("test#example.com", "password");
ResponseEntity<AppUser> appUserResponse = template.getForEntity(USERS_ENDPOINT + "1/", AppUser.class);
assertEquals("Username is incorrect. AppUser not created?",
appUser.getUsername(), appUserResponse.getBody().getUsername());
}
}
Here's application-test.properties - or at least the relevant part:
# Disable feature detection by this undocumented parameter. Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# Because detection is disabled you have to set correct dialect by hand.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.datasource.url=jdbc:postgresql://localhost/mahlzeit-test
spring.datasource.username=postgres
spring.datasource.password=root
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=create-drop
Any idea what the problem could be? Please let me know if you need further information and/or code.

Related

Integration test for springboot with initalize query

I am going use an integration test in spring boot with in memory mysql database.But my test component in repository part query like:
#Query(
value = "SELECT order_id,title,description,requirement,salary,user_info.name,user_info.contact,date"+
" FROM job_order " +
" FULL JOIN user_info " +
" ON sender_id=user_info.id" +
" WHERE order_id= ?1 ;",nativeQuery = true
)
Response singlejob(int order_id);
My entrypoint is doing stuff on the job_order table.The query require two tables ,so i am trying to insert the user_info table and then test for the job_order.Then a write test like this:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#TestExecutionListeners(listeners = { SqlScriptsTestExecutionListener.class })
class OrderServiceApplicationTests {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
#Autowired
private JobRepository jobRepository;
//#Sql("INSERT INTO user_info(name) VALUES \"alex\" ")
#Test
#Sql("{/resources/schema.sql}")
void shouldCreatePost() throws Exception {
JobOrder job=jobRepository.save(createjob());
String request=objectMapper.writeValueAsString(job);
mockMvc.perform(MockMvcRequestBuilders.post("/Job/Joborder")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andExpect(status().is2xxSuccessful());
}
JobOrder createjob(){
JobOrder job=new JobOrder();
job.setTitle("Hiring software engineer");
job.setDescription("responsible for developing and maintaining mobile app");
job.setRequirement("Need to know basic sql springboot,2 years exp");
job.setSalary(234);
job.setOrder_id(1);
return job;
}
}
schema.sql:
INSERT INTO user_info (name) VALUES ('India');
and i got an error:
org.springframework.jdbc.datasource.init.CannotReadScriptException: Cannot read SQL script from class path resource [com/example/OrderService/{/resources/schema.sql}]
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:239)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:254)
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:54)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.execute(ResourceDatabasePopulator.java:269)
at org.springframewo
My properties:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=***
spring.datasource.password=*******
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.defer-datasource-initialization=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.sql.init.mode=always
My Path:
I dont know what is the problem on my path.And i am wondering if there are problem on my test script or strategy
Path resource semantics should be followed when #Sql annotation is used. If you want to load the script file from the resources folder you should use classpath: reference:
#Sql(value = {"classpath:schema.sql"})

Integration test in spring boot cant found the path of sql file

I am writing a integration test for rest api entry.The api require to initialize database before the test.However it gives an error which showing it cant find any path to my sql file.
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#TestExecutionListeners(listeners = { SqlScriptsTestExecutionListener.class })
class OrderServiceApplicationTests {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
#Autowired
private JobRepository jobRepository;
//#Sql("INSERT INTO user_info(name) VALUES \"alex\" ")
#Test
#Sql("{/resources/schema.sql}")
void shouldCreatePost() throws Exception {
JobOrder job=jobRepository.save(createjob());
String request=objectMapper.writeValueAsString(job);
mockMvc.perform(MockMvcRequestBuilders.post("/Job/Joborder")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andExpect(status().is2xxSuccessful());
}
JobOrder createjob(){
JobOrder job=new JobOrder();
job.setTitle("Hiring software engineer");
job.setDescription("responsible for developing and maintaining mobile app");
job.setRequirement("Need to know basic sql springboot,2 years exp");
job.setSalary(234);
job.setOrder_id(1);
return job;
}
}
schema.sql:
INSERT INTO user_info (name) VALUES ('India');
and i got an error:
org.springframework.jdbc.datasource.init.CannotReadScriptException: Cannot read SQL script from class path resource [com/example/OrderService/{/resources/schema.sql}]
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:239)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:254)
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:54)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.execute(ResourceDatabasePopulator.java:269)
at org.springframewo
My properties:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=***
spring.datasource.password=*******
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.defer-datasource-initialization=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.sql.init.mode=always
My Path:
I dont know what is the problem on my path.And i am wondering if there are problem on my test script or strategy
Several things are wrong with your #Sql("{/resources/schema.sql}").
the { and } do not belong into the path, why did you add it in the first place?
You don't need to include the /resources directory in the path. To find out what the path of your file is, open the target/test-classes and have a look. Everything that resides in the resources directory will be placed in the root directory. If your file was in resources/sql/test.sql it would be available under sql/test.sql.
Solution
#Sql("schema.sql")

Hibernate statistic different at runtime as on test

At runtime i'am sending get-request to my api and i can see, that hibernate executes 4 jdbc statements. One statement is a sql-join and second one is select-count for page-element and two other statements "hibernate fetch.subselects", which are for persistence-bag.
When I'am sending with MockMVC under WebapplicationContext get-request to my api to test, that it will be everytime 4 jdbc statements and not more, I am getting only two first jdbc-statements which I've described.
So how can I get during test-time the same amount of jdbc's like on runtime?
Controller:
#GetMapping({"/"})
public String links(#PageableDefault Pageable page,
Model model) {
Page<MyEntity> entity = service.fetchAllEntities(page);
List<Integer> totalPages = Arrays.asList(1,2)
model.addAttribute("entity",entity);
model.addAttribute("numbers",totalPages);
return "object/object_list";
}
Test-Controller
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#Transactional
public class AllControllersTransactionTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext context;
private Statistics hibernateStatistic;
Session hibernateSession;
private EntityManager entityManager;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.build();
entityManager = BeanUtil.getBeanFromContext(EntityManager.class);
hibernateSession = entityManager.unwrap(Session.class);
hibernateStatistic = hibernateSession.getSessionFactory().getStatistics();
hibernateStatistic.clear();
}
#Test
public void shouldReturnAllLinksWith5JDBCStatmentsAsAutheticated() throws Exception {
List<Integer> pages = Arrays.asList(new Integer[] {1,2});
MvcResult result = this.mockMvc.perform(get("/"))
.andDo(print())
.andExpect(status().isOk());
LOGGER.info("QUERIES: ", hibernateStatistic.getQueries());
assertEquals("SHOULD EXECUTED ONLY 4 JDBC STATMENTS", 4, hibernateStatistic.getQueryExecutionCount()); //At test-time, they are only two statments
}
}
UPDATE
I've switched off open-session-in-view in spring:
spring.jpa.open-in-view=false
Next point is, that i'am mapping my model into dto-object in my service-bean:
public Page<UserDTO> fetchAllLinksWithUsersCommentsVotes(Pageable pageable){
Page<Link> ln = linkRepository.findAll(pageable);
UserDTO.getMapDto(ln.getContent().get(0)); //additional two queries will be execued
UserDTO.getMapDto(ln.getContent().get(1)); //no queries will be executed
UserDTO.getMapDto(ln.getContent().get(2)); //no queries will be executed
ArrayList<UserDTO> users = ..//get users;
return new PageImpl<>(users, pageable, ln.getTotalElements());
}
When i'am executing
UserDTO.getMapDto(ln.getContent().get(0));
so i can see at runtime and during testtime,
that last two queries (persistence-bag with lazy-loading) will be executed.
Difference between runtime and testtime is, that during runtime hibernate shows 4 JDBC-Statments and on testtime only 2 JDBC-Statments by same-entries in the log (4 select-statments) .
So, why i can see 4 JDBC-Statments within log and runtime and testtime but i have different result within hibernate statistic on runtime and testtime.

Spring Boot Testing with Mockito and ExpectedException - console printing 'null' is normal?

I'm writing some test classes for my services and noticed a weird behavior that happens after test results are returned. The console prints 'null' messages and no other information about tests. The tests work fine as I've tried to fail them to ensure that is the case. Is this the expected behavior?
#RunWith(MockitoJUnitRunner.class)
public class GradeServiceTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Mock
private GradeRepository gradeRepository;
#Mock
private AssignmentService assignmentService;
#InjectMocks
private GradeService gradeService;
private Assignment assignment;
private Grade grade;
#Before
public void init() {
assignment = new Assignment.Builder()
.withId(0L)
.withModuleId(0L)
.withName("Test assignment")
.withWeightEnabled(false)
.withWeight(0)
.build();
grade = new Grade.Builder()
.withId(0L)
.withAssignmentId(0L)
.withGradeType(GradeType.PERCENTAGE)
.withGradeValue("50%")
.build();
}
#Test
public void shouldAddGrade() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(true);
when(gradeRepository.insert(any())).thenReturn(grade);
// WHEN
Grade addedGrade = gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
// THEN
assertThat(addedGrade).isEqualTo(grade);
}
#Test
public void shouldNotAddGradeIfAssignmentDoesNotExist() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(false);
// EXPECT
thrown.expect(AssignmentException.class);
thrown.expectMessage(AssignmentErrorMessages.NOT_FOUND);
// THEN
gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
}
}
I don't think this is normal behavior for each test to be printing 'null' without any other information. Could someone help me understand what is wrong with the code?
Test results:
null
null
Process finished with exit code 0

Tests fail with #Scheduled Task: JdbcSQLSyntaxErrorException Table "USER_ACCOUNT_CREATED_EVENT" not found

Summary & first problem
I am trying to test my user registration mechanism. When a new user account is created via my REST API, a UserAccountCreatedEvent is stored in the database. A scheduled task checks the database every 5 seconds for new UserAccountCreatedEvents and if one is present, sends an email to the registered user. When running my tests I encounter the problem that the table for the UserAccountCreatedEvent can't be found (see exception below). I used to send the email in a blocking manner in the service method, but I recently switched to this async approach. All my tests worked perfectly for the blocking approach and the only thing I changed for the async approach is to include Awaitility in the test.
2019-04-23 11:24:51.605 ERROR 7968 --- [taskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select useraccoun0_.id as id1_0_, useraccoun0_.completed_at as complete2_0_, useraccoun0_.created_at as created_3_0_, useraccoun0_.in_process_since as in_proce4_0_, useraccoun0_.status as status5_0_, useraccoun0_.user_id as user_id1_35_ from user_account_created_event useraccoun0_ where useraccoun0_.status=? order by useraccoun0_.created_at asc limit ?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException:
Table "USER_ACCOUNT_CREATED_EVENT" not found; SQL statement:
select useraccoun0_.id as id1_0_, useraccoun0_.completed_at as complete2_0_, useraccoun0_.created_at as created_3_0_, useraccoun0_.in_process_since as in_proce4_0_, useraccoun0_.status as status5_0_, useraccoun0_.user_id as user_id1_35_ from user_account_created_event useraccoun0_ where useraccoun0_.status=? order by useraccoun0_.created_at asc limit ? [42102-199]
Full stack trace
Second problem
As if that were not enough, the tests behave completely different when running them in debug mode. When I set a breakpoint in the method that is called by the method which is annotated with #Scheduled, it is invoked several times althogh #Scheduled is configured with a fixedDelayString (fixed delay) of 5000ms. Thanks to logging I can even see that several mails were sent. Still, my test SMTP sever (GreenMail) does not receive any emails. How is this even possible? I've intentionally set the transaction isolation to Isolation.SERIALIZABLE so that it should be impossible (as far as I understand transaction isolation) that two scheduled methods access the same Event from the database.
Third problem
To cap it all, when I rerun the failed tests, THEY WORK. But, there are different exceptions on the console (see below). But still, the app starts and the tests finish successfully. There are different test results depending on if I run all tests vs. only the class vs. only the method vs. rerun failed tests. I don't understand how such an indeterministic behaviour can be possible.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: Failed to scan classpath for unlisted entity classes
Caused by: java.nio.channels.ClosedByInterruptException: null
Full stack trace
My code
Test class (UserRegistrationTest)
#ActiveProfiles("test")
#AutoConfigureMockMvc
#RunWith(SpringRunner.class)
#SpringBootTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class UserRegistrationTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
#Autowired
private Routes routes;
#Autowired
private TestConfig testConfig;
#Resource(name = "validCustomerDTO")
private CustomerDTO validCustomerDTO;
#Resource(name = "validVendorDTO")
private VendorRegistrationDTO validVendorRegistrationDTO;
#Value("${schedule.sendRegistrationConfirmationEmailTaskDelay}")
private Short registrationConfirmationEmailSenderTaskDelay;
private GreenMail smtpServer;
// Setup & tear down
#Before
public void setUp() {
smtpServer = testConfig.getMailServer();
smtpServer.start();
}
#After
public void tearDown() {
smtpServer.stop();
}
// Tests
#Test
public void testCreateCustomerAccount() throws Exception {
mockMvc.perform(
post(routes.getCustomerPath())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(validCustomerDTO)))
.andExpect(status().isCreated());
// When run normally, I get a timeout from the next line
await().atMost(registrationConfirmationEmailSenderTaskDelay + 10000, MILLISECONDS).until(smtpServerReceivedOneEmail());
// Verify correct registration confirmation email was sent
MimeMessage[] receivedMessages = smtpServer.getReceivedMessages();
assertThat(receivedMessages).hasSize(1);
// other checks
// ...
}
#Test
public void testCreateVendorAccount() throws Exception {
mockMvc.perform(
post(routes.getVendorPath())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(validVendorRegistrationDTO)))
.andExpect(status().isCreated());
// When run normally, I get a timeout from the next line
await().atMost(registrationConfirmationEmailSenderTaskDelay + 10000, MILLISECONDS).until(smtpServerReceivedOneEmail());
// Verify correct registration confirmation email was sent
MimeMessage[] receivedMessages = smtpServer.getReceivedMessages();
assertThat(receivedMessages).hasSize(1);
// other checks
// ...
}
// Helper methods
private Callable<Boolean> smtpServerReceivedOneEmail() {
return () -> smtpServer.getReceivedMessages().length == 1;
}
// Test configuration
#TestConfiguration
static class TestConfig {
private static final int PORT = 3025;
private static final String HOST = "localhost";
private static final String PROTOCOL = "smtp";
GreenMail getMailServer() {
return new GreenMail(new ServerSetup(PORT, HOST, PROTOCOL));
}
#Bean
public JavaMailSender javaMailSender() {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(HOST);
javaMailSender.setPort(PORT);
javaMailSender.setProtocol(PROTOCOL);
javaMailSender.setDefaultEncoding("UTF-8");
return javaMailSender;
}
}
Task scheduler (BusinessTaskScheduler)
#Component
public class BusinessTaskScheduler {
private final RegistrationTask registrationTask;
#Autowired
public BusinessTaskScheduler(RegistrationTask registrationTask) {
this.registrationTask = registrationTask;
}
#Scheduled(fixedDelayString = "${schedule.sendRegistrationConfirmationEmailTaskDelay}")
public void sendRegistrationConfirmationEmail() {
registrationTask.sendRegistrationConfirmationEmail();
}
}
The code that is called by the scheduled method (RegistrationTask)
#Component
#Transactional(isolation = Isolation.SERIALIZABLE)
public class RegistrationTask {
private final EmailHelper emailHelper;
private final EventService eventService;
private final UserRegistrationService userRegistrationService;
#Autowired
public RegistrationTask(EmailHelper emailHelper, EventService eventService, UserRegistrationService userRegistrationService) {
this.emailHelper = emailHelper;
this.eventService = eventService;
this.userRegistrationService = userRegistrationService;
}
public void sendRegistrationConfirmationEmail() {
Optional<UserAccountCreatedEvent> optionalEvent = eventService.getOldestUncompletedUserAccountCreatedEvent();
if (optionalEvent.isPresent()) {
UserAccountCreatedEvent event = optionalEvent.get();
User user = event.getUser();
RegistrationVerificationToken token = userRegistrationService.createRegistrationVerificationTokenForUser(user);
emailHelper.sendRegistrationConfirmationEmail(token);
eventService.completeEvent(event);
}
}
}
The event service (EventServiceImpl)
#Service
#Transactional(isolation = Isolation.SERIALIZABLE)
public class EventServiceImpl implements EventService {
private final ApplicationEventDAO applicationEventDAO;
private final UserAccountCreatedEventDAO userAccountCreatedEventDAO;
#Autowired
public EventServiceImpl(ApplicationEventDAO applicationEventDAO, UserAccountCreatedEventDAO userAccountCreatedEventDAO) {
this.applicationEventDAO = applicationEventDAO;
this.userAccountCreatedEventDAO = userAccountCreatedEventDAO;
}
#Override
public void completeEvent(ApplicationEvent event) {
if (!event.getStatus().equals(COMPLETED) && Objects.isNull(event.getCompletedAt())) {
event.setStatus(COMPLETED);
event.setCompletedAt(LocalDateTime.now());
applicationEventDAO.save(event);
}
}
#Override
public Optional<UserAccountCreatedEvent> getOldestUncompletedUserAccountCreatedEvent() {
Optional<UserAccountCreatedEvent> optionalEvent = userAccountCreatedEventDAO.findFirstByStatusOrderByCreatedAtAsc(NEW);
if (optionalEvent.isPresent()) {
UserAccountCreatedEvent event = optionalEvent.get();
setEventInProcess(event);
return Optional.of(userAccountCreatedEventDAO.save(event));
}
return Optional.empty();
}
#Override
public void publishEvent(ApplicationEvent event) {
applicationEventDAO.save(event);
}
// Helper methods
private void setEventInProcess(ApplicationEvent event) {
event.setStatus(Status.IN_PROCESS);
event.setInProcessSince(LocalDateTime.now());
}
}
The UserAccountCreatedEvent
application.yml
schedule:
sendRegistrationConfirmationEmailTaskDelay: 5000 # delay between tasks in milliseconds
I am new to scheduling with Spring, so any help is greatly appreciated!

Resources