我们正在运行后台作业,要求用户处于活动状态。以下方式工作正常,但我们必须硬编码不理想的密码。
try {
session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
} catch (RepositoryException ex) {
log.error("SessionHelper - login issue", ex);
}
我们尝试更好的方法来设置活动用户而不设置密码,如下所示:
Map<String, Object> params = new HashMap<String, Object>();
params.put(ResourceResolverFactory.SUBSERVICE, "theService");
ResourceResolver resolver = null;
try {
resolver = resolverFactory.getServiceResourceResolver(params);
} catch (LoginException e) {
log.error("LoginException", e);
}
Session session = resolver.adaptTo(Session.class);
// Next, create pages and add properties ...
然后我们尝试创建页面并设置属性。这可以正常工作几毫秒,其中一些页面被创建,但然后抛出异常以指示会话已关闭,但从未关闭,并且异常被抛出的位置是不可预测的。
javax.jcr.RepositoryException: This session has been closed. See the chained exception for a trace of where the session was closed.
...
Caused by: java.lang.Exception: Stack trace of where session-admin-20077 was originally closed
我们想知道是否有办法设置超时?任何建议都赞赏。
答案 0 :(得分:3)
您应该始终通过ResourceResolverFactory使用getServiceResourceResolver方法获取会话(getAdministrativeResourceResolver方法实际上已被弃用且应该避免),执行比同一个try / catch块中的代码并定义finally块,您可以确保获得的解析器/会话正确关闭。如果您遵循此原则,您可能永远不会遇到关闭或未关闭会话的问题。
@org.apache.felix.scr.annotations.Component(...)
public class MyComponent {
@org.apache.felix.scr.annotations.Reference
private org.apache.sling.api.resource.ResourceResolverFactory resourceResolverFactory;
public void myaction() {
org.apache.sling.api.resource.ResourceResolver resolver = null;
try {
Map<String, Object> authInfo = new HashMap<String, Object>();
authInfo.put(ResourceResolverFactory.SUBSERVICE, getClass.getName());
resolver = resourceResolverFactory.getServiceResourceResolver(authInfo);
javax.jcr.Session session = resolver.adaptTo(javax.jcr.Session.class);
javax.jcr.Node node = session.getNode("/jcr/path/to/the-node");
// do something with the node
session.save();
} catch(LoginException e) {
// Handle cannot obtain instance of the resource resolver
} catch(RepositoryException e) {
//handle the repository exception
} finally {
//do not forget to close the resolver, otherwise this can cause huge performance problems
if(resolver != null) {
resolver.close();
}
}
}
}
为了获得服务资源解析器,您还需要在OSGI-Service org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl中配置user.mapping,例如如下所示。:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:OsgiConfig"
user.mapping="[tld.mycompany.mypackage=admin]"
user.default="admin"/>
通过这种方式,您可以为您的服务设置并提供非常高级的访问控制策略。
如果您使用的是吊索servlet,请注意您正在使用的资源解析程序。在正常情况下,您不需要具有管理权限的资源解析程序,而是使用SlingHttpServletRequest提供的资源解析程序。资源解析器在请求结束时通过吊索关闭,不要手动关闭它。
答案 1 :(得分:0)
如果你正在使用管理员会话,我建议不要像你那样登录,但是使用以下方法(从你的代码中得知你已经注入了@Reference的SlingRepository):
repository.loginAdministrative(null);
为了防止错误,我会使用以下模式:
Session session = null;
try {
session = repository.loginAdministrative(null);
//do what you need to do
} catch (RepositoryException e) {
//handle exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
}
最后一点,在同一个线程中打开和关闭会话,这样就不会在会话中保持会话活动,除非它是一个EventListener。