在关闭AEM中的资源解析程序对象后,会话已关闭



我正试图关闭我打开的资源解析程序,但我收到了这个错误"javax.jcr.RepositoryException:当我关闭资源解析程序时,这个会话已经关闭。实际上,如果你保持资源解析程序打开,我看不到任何问题,但我不想在代码中打开资源解析程序。

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();
}
}

错误消息:-

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]

在日志中观察到许多错误消息,如下所示如果我不关闭代码中的资源解析程序

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)

真正的问题是,一旦关闭资源解析程序,会话就会关闭。这是AEM代码的问题吗?或者有其他办法处理这个案子吗?

返回的问题是ValueMap对象试图使用内部创建的ResourceResolver动态访问存储库,但该Resolver在从方法退出时已立即关闭(在finally块中(。

有不同的解决方案来克服这一点,效率更高/更低:

解决方案1(当您只需要只读访问ValueMap属性时,您可以返回该映射的副本:

...
ValueMap props = configuration.getContentResource().adaptTo(ValueMap.class)
return (props != null) ? new HashMap<>(props)     // create the copy Map of props
: new HashMap<String, Object>(0);

解决方案2(不要使用内部创建的";服务用户";ResourceResolver,但将当前用户的ResourceResolver传递到您的方法中,并确保用户具有访问Configuration节点的权限。

解决方案3(创建get(propertyName)set(propertyName, value)方法来读取/写入特定的Configuration属性,它们将创建内部ResourceResolver,并在获取/设置操作后立即关闭它:

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);
}
}
}

解决方案4(在一些上层方法中创建服务ResourceResolver,并将其传递到不需要ValueMap为止:

...
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
}
...

解决方案5((解决方案4的极端变体(在类/捆绑包启动时创建一次服务ResourceResolver,并让它一直存在到应用程序关闭,然后将它传递给方法。尽管如此,Sling文档并不完全推荐这种变体。。

我可以根据需要提供更多样品。

基本上问题在于代码。根据定义关闭ResourceResolver也会关闭它所基于的会话。诀窍是在之后关闭它,您不再需要所有依赖的对象(例如ValueMap(。

HTH。

最新更新