Currently there are 4 classes Service, ServiceHandler(Runnable), SessionManager and Session(Runnable). All the scheduling was carried out by Tibco’s AST product previously which needs to be replaced. Need help implementing below functionality with the help of Spring Boot, ScheduledThreadPoolExecutor which will run for the application lifetime.
@Service
class Service implements ApplicationListener<ContextRefreshedEvent> {
private SessionManager sessionManager;
public Service(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
sessionManager.start();
}
@PreDestroy
public void stop() {
sessionManager.stop();
}
}
@Component
class ServiceHandler implements Runnable {
@Override
public void run() {
//existing tibco class used to create a call sessionManager's checkForWork() so it was being initialized in the constructor as well. Can't do that here as if I inject SessionManager here then there'll be circular dependency.
}
}
@Component
class SessionManager {
private ServiceHandler handler;
private ScheduledThreadPoolExecutor checkForWorkScheduler;
private ScheduledThreadPoolExecutor sessionScheduler;
public SessionManager(ServiceHandler handler) {
this.handler = handler;
checkForWorkScheduler = new ScheduledThreadPoolExecutor(1);
sessionScheduler = new ScheduledThreadPoolExecutor(10);
}
public void checkForWork() {
File[] entries = path.listFiles();
if(entries != null) {
for(File entry : entries) {
if(entry.isDirectory()) {
Session session = new Session(this, entry);
sessionScheduler.scheduleAtFixedRate(session, 0, 10, TimeUnit.SECONDS);
}
}
}
public void start() {
String path = "/MAIN/DIRECTORY/PATH";
File file = new File(path);
checkForWorkScheduler.scheduleAtFixedRate(serviceHandler, 5, 300, TimeUnit.SECONDS);
}
public void stop() {
sessionScheduler.shutdown();
try {
if(!sessionScheduler.awaitTermination(/*CalculateKeepAliveTime*/ , TimeUnit.SECONDS) {
sessionScheduler.shutdownNow();
}
} catch(InterruptedException e) {
log.error(e);
}
checkForWorkScheduler.shutdown();
}
}
class Session implements Runnable {
@Override
public void run() {
//complex logic to process each file in the directory
}
}
Creating 1 scheduler with 1 thread which will run forever and checkForWork every 5 minutes if there are new directores in the Path. The other Scheduler will be scheduling 10 threads for 10 different directories which will each process files under their respective directory. Trying to get rid of Thread.sleep as well so using scheduler and Awaitility library for sleeping the thread where required (haven’t used it as didn’t find the need)
This is mostly refactored code and the design is kinda poor, so want to improve and understand how to call the checkForWork() method in ServiceHandler class without creating a Circular dependency in spring.