问题
I am trying to close the resource resolver that I opened but I got this error “javax.jcr.RepositoryException: This session has been closed when I close resource resolver. Actually I don’t see any problem if you leave the resource resolver as open but I don’t want to leave the resource resolver open in the code.
serviceParam.put(ResourceResolverFactory.SUBSERVICE, "serviceNew");
ResourceResolver resourceResolver = null;
try
{
resourceResolver = resourceResolverFactory.getServiceResourceResolver(serviceParam);
final Configuration configuration = configurationManagerFactory.getConfigurationManager(resourceResolver)
.getConfiguration(cloudConfigurationType.getServiceName(), services);
if (null != configuration)
{
return configuration.getContentResource().adaptTo(ValueMap.class);
}
} catch (LoginException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} finally
{
if (resourceResolver != null && resourceResolver.isLive())
{
resourceResolver.close();
}
}
Error message:-
org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught SlingException
java.lang.IllegalArgumentException: javax.jcr.RepositoryException: This session has been closed.
at org.apache.sling.jcr.resource.internal.JcrValueMap.read(JcrValueMap.java:337) [org.apache.sling.jcr.resource:3.0.16]
at org.apache.sling.jcr.resource.internal.JcrValueMap.get(JcrValueMap.java:101) [org.apache.sling.jcr.resource:3.0.16]
Observing many error messages like below in logs If I dont close a resource resolver in code
23.12.2020 11:56:30.481 [Apache Sling Resource Resolver Finalizer Thread] INFO o.a.s.r.i.CommonResourceResolverFactoryImpl Unclosed ResourceResolver was created here:
java.lang.Exception: Opening Stacktrace
at org.apache.sling.resourceresolver.impl.CommonResourceResolverFactoryImpl$ResolverReference.<init>(CommonResourceResolverFactoryImpl.java:540)
The real problem is, session getting closed as soon as we close resource resolver. Is this an issue with AEM code? or Any other way to handle this case?
回答1:
Well, basically the problem is the code. Closing a ResourceResolver by definition closes the session it is based on as well. The trick is to close it after you don't need all the depending objects any more (like the ValueMap for example).
HTH.
回答2:
The problem is returned ValueMap object tries to dynamically access repository using internally-created ResourceResolver, but that Resolver is already closed immediately on exit from your method (in finally block).
There are different solutions to overcome this, more/less efficient:
SOLUTION 1) When you need only read-only access to ValueMap properties, you may return the copy of that map:
...
ValueMap props = configuration.getContentResource().adaptTo(ValueMap.class)
return (props != null) ? new HashMap<>(props) // create the copy Map of props
: new HashMap<String, Object>(0);
SOLUTION 2) Don't use internally-created "service-user" ResourceResolver, but pass current user's ResourceResolver into your method, and make sure user has privileges to access Configuration nodes.
SOLUTION 3)
Create the get(propertyName)
and set(propertyName, value)
methods to read/write specific Configuration property, they would create internal ResourceResolver and immediate close it after the get/set operation:
public Object getProp(String name) {
try(ResourceResolver resolver = resourceResolverFactory.getServiceResourceResolver(serviceParam)) {
Configuration configuration = configurationManagerFactory.getConfigurationManager(resolver)
.getConfiguration(cloudConfigurationType.getServiceName(), services);
if (null != configuration){
return configuration.getContentResource().adaptTo(ValueMap.class).get(name);
}
}
}
SOLUTION 4) Create service ResourceResolver in some upper method, and pass it through until ValueMap is not needed:
...
try(ResourceResolver resolver = resourceResolverFactory.getServiceResourceResolver(serviceParam)) {
...
ValueMap confProps = getConfigProps(resolver, ...); // call your method
// use confProps as you wish safely
...
} // at this place, Resolver is closed and you cannot use confProps any more
}
...
SOLUTION 5) (extreme variant of SOLUTION #4) Create the service ResourceResolver once at your class/bundle startup, and let it lives until application shutdown, passing it to your method(s). Though, this variant is not quite recommended by Sling documentation..
I can provide more samples on need.
来源:https://stackoverflow.com/questions/65593644/session-has-been-closed-after-closing-resource-resolver-object-in-aem