Missed PreDestroy calls
If EJB instance, other than Singleton, throws system exception, which is non application runtime exception, then EJB Container immediately discards the instance without calling @PreDestroy method.
This is not a problem if calling @PreDestroy is not essential to an application. If it is, then it was proposed to provide additional application pool of resources or beans and periodically clean up abandoned resources or beans. We do it other way.
We augment EJB class with a kind of ExeptionHandler
@Stateless public class BeanWithCleanupMechanism { ... @PreDestroy private void destroy(){ //clean up } ... @AroundInvoke private Object exceptionHandling(InvocationContext ctx){ try { return ctx.proceed(); } catch ( ... e ) { //catch all expected application runtime exceptions //and just rethrow it throw e; } catch ( RuntimeException e ) { //e is a system exception destroy(); //rethrow exception, instance will be discarded //but instance is already clean throw e; } } ... }
It is just Interceptor listening for system exceptions.
Catching all expected runtime application exceptions requires knowing these exceptions. Instead of it, all runtime exceptions can be caught and checked via reflection if annotation @ApplicationException is present in an exception’s class.
This @AroundInvoke can be part of a separate Interceptor class as well. Remember though: this @AroundInvoke method should be called as the last in a chain of interceptors