Let's say that we would like to have an information about current time printed on a console periodically.
The class that prints the time may look like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TimePrinter { | |
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss"); | |
private static final Logger LOGGER = LoggerFactory.getLogger(TimePrinter.class.getName()); | |
public void reportCurrentTime() { | |
LOGGER.info("The time is now " + DATE_FORMAT.format(new Date())); | |
} | |
} |
We need to define a class that will encapsulate the printing task:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ScheduledTask { | |
static final String THREAD_NAME = ScheduledTask.class.getName() + "!"; | |
@Autowired private TimePrinter timePrinter; | |
@Scheduled(fixedRate = 5000) | |
public void reportCurrentTime() { | |
Thread.currentThread().setName(THREAD_NAME); | |
timePrinter.printCurrentTime(); | |
} | |
} |
You can also specify cron expression. You can use fixedRateString parameter if you want to read it from properties file.
Please note setting of the thread name - it will be needed for the test.
Adding production code only for tests is generally not a good practice, but in this case it can also be used for monitoring purposes.
The spring configuration looks as following:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
@EnableScheduling | |
@ComponentScan("pl.mjedynak") | |
public class AppConfig { | |
@Bean | |
public ScheduledTask scheduledTask() { | |
return new ScheduledTask(); | |
} | |
@Bean | |
public TimePrinter timePrinter() { | |
return new TimePrinter(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class App { | |
public static void main(String[] args) { | |
new AnnotationConfigApplicationContext(AppConfig.class); | |
} | |
} |
Let's create a test class:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RunWith(SpringJUnit4ClassRunner.class) | |
@ContextConfiguration(classes = AppConfig.class) | |
public class ScheduledTaskIntegrationTest { | |
@Test | |
public void shouldInvokeTask() { | |
Callable<Boolean> threadWithNameExists = | |
() -> getAllStackTraces().keySet().stream(). | |
anyMatch(t -> t.getName().equals(ScheduledTask.THREAD_NAME)); | |
await().until(threadWithNameExists, is(true)); | |
} | |
} |
When we run the test, the spring context will start and the task will be invoked by scheduler.
We check if the thread with our name exists.
We do it for some time to avoid race condition - it may happen that verification method will be invoked before thread starts.
The whole project alongside with dependencies can be found on github.