Has this happened to you? - You got the JCR session, but at times, you find that "someone" closed the JCR session! And that too - its very inconsistent. Sometimes it works and other times it does not! Well then its that you have hit the Sling / CQ development anti-pattern. And possibly this is what you see in your log:
javax.jcr.RepositoryException: This session has been closed.
As suggested by
Jorg Hoh on his blog on CQ development patterns, you should rely on Sling objects as much as possible, rather than relying directly on the JCR objects. But at those cases (e.g. writing to a repository) when you will have to directly rely on the JCR repository you will have to still use the JCR Session, its recommended that you directly get the JCR session from the Sling repository, and not adapt it from the
ResourceResolver, IF you do not intend to use the
ResourceResolver directly.
@Reference
private ResourceResolverFactory resolverFactory;
// Wrong way of obtaining JCR Session
private Session getSessionAntipattern() throws LoginException {
ResourceResolver resolver = resolverFactory.getServiceResourceResolver(null);
return resolver.adaptTo(Session.class);
}
Code Listing 1: JCR Session Creation Antipattern
@Reference
private SlingRepository slingRepository;
// Correct way of obtaining JCR session
private Session getJCRSession() throws RepositoryException {
return slingRepository.loginService(null, null);
}
Code Listing 2: JCR Session Creation Pattern
You may wonder, what's wrong. Logically thinking, why would you retrieve the
ResourceResolver (and adapt it to JCR Session), if you do not intend to use the
ResourceResolver? This logic has made the Sling developer's to close the underlying JCR Session of the
ResourceResolver when the
ResourceResolver object is Garbage Collected. Although, how this is done is
being changed across the releases, the basic idea of releasing the resources held up (JCR Session) is still valid.
If you observe in the code snippet 1 (antipattern), the scope of the
ResourceResolver object ends as soon as the method returns, which makes it eligible for garbage collection. This means that whenever the garbage collector runs, the JCR Session got through the antipattern would be closed - oops! This explains your JCR Session getting closed inconsistently.
I would like to emphasize that adapting to JCR Session from
ResourceResolver itself is not wrong, if you intend to use the
ResourceResolver along, other than just adapting it to JCR Session.
Hope this post helps someone save some time debugging on the JCR Session getting closed inconsistently.