given the following code, I wonder why the CacheManager is still "alive" after the call to the @PreDestroy annotated method (CacheManager#doCleanup) (see output at the end of this post). Isn't Weld aware of the fact that it's still referenced ? And how to get this method called when the object is really not used anymore ?
Main class
public class Main {
public static void main(String[] parameters) {
//Init weld container
Weld weld = new Weld();
WeldContainer container = weld.initialize();
container.select(MyLauncher.class).get().startScanner();
weld.shutdown();
}
}
MyLaucher class
@Singleton
public class MyLauncher {
@Inject
private Logger logger;
@Inject
private PeriodicScanner periodicScanner;
public Future startScanner() {
logger.info("Starting file producers...");
return periodicScanner.doScan();
}
}
PeriodicScanner class...
@Singleton
public class PeriodicScanner {
@Inject
private Logger logger;
@Inject
private CacheManager myCacheMgr;
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
.setNameFormat("periodic-%d")
.build());
public Future doScan() {
return scheduledExecutorService.scheduleAtFixedRate(() -> {
myCacheMgr.doStuff();
logger.info("Hello from PeriodicScanner");
}, 1, 15, TimeUnit.SECONDS);
}
}
And the CacheManager class:
@Singleton
public class CacheManager {
@Inject
Logger logger;
@PostConstruct
private void doInit(){
logger.info("PostConstruct called for ID {}", this.hashCode());
}
@PreDestroy
private void doCleanup(){
logger.info("Cleaning up for ID {}", this.hashCode());
}
public int doStuff(){
logger.info("Doing stuff from instance ID {}", this.hashCode());
return 1;
}
}
The output is:
Sep 06, 2017 3:47:51 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 2.4.4 (Final)
Sep 06, 2017 3:47:51 PM org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Sep 06, 2017 3:47:52 PM org.jboss.weld.environment.se.WeldContainer fireContainerInitializedEvent
INFO: WELD-ENV-002003: Weld SE container 2d18aac9-f66d-4373-b581-9c5cababd65a initialized
[main] INFO com.mycompany.cdiplayground.CacheManager - PostConstruct called for ID 611572016
[main] INFO com.mycompany.cdiplayground.MyLauncher - Starting file producers...
[main] INFO com.mycompany.cdiplayground.CacheManager - Cleaning up for ID 611572016
Sep 06, 2017 3:47:52 PM org.jboss.weld.environment.se.WeldContainer shutdown
INFO: WELD-ENV-002001: Weld SE container 2d18aac9-f66d-4373-b581-9c5cababd65a shut down
[periodic-0] INFO com.mycompany.cdiplayground.CacheManager - Doing stuff from instance ID 611572016
[periodic-0] INFO com.mycompany.cdiplayground.PeriodicScanner - Hello from PeriodicScanner
[periodic-0] INFO com.mycompany.cdiplayground.CacheManager - Doing stuff from instance ID 611572016
[periodic-0] INFO com.mycompany.cdiplayground.PeriodicScanner - Hello from PeriodicScanner
As you can see, the periodic scanner is still alive after the container shutdown. For the moment, the only way for me to prevent doCleanup() to be called too early is to call get() on the Future object returned by startScanner():
container.select(MyLauncher.class).get().startScanner().get();
This way, the main application thread won't exit.
Does anybody know a better way to do that?
Thanks
I