Modeshape中无法使用的会话 - JCR异常

时间:2013-10-31 07:07:16

标签: java session jboss jcr modeshape

有时当我在一个函数中使用多个Modeshape动作时,我会收到此错误:

  

javax.jcr.RepositoryException:ID为“060742fc6”的会话已关闭,无法再使用。

我在网上找不到任何解释。这就是我所说的:

myFunction( service.doSomething ( service.getStuff ( id, "en_EN" ).getPath() ) );

doSomething,getStuff:

@Interceptors({Foo.class, TraceInterceptor.class})
@Override
public Node doSomething(final String bar) throws RepositoryException {

    return modeshape.execute(new JcrHandler<Node>() {

        @Override
        public Node execute(Session session) throws RepositoryException {
            return session.getNode(bar);
        }
    });
}    

@Interceptors(TraceInterceptor.class)
@Override
public ObjectExtended getStuff(final String query, final String language)
    throws RepositoryException {
    return modeshape.execute(new JcrHandler<ObjectExtended>() {

    @Override
    public ObjectExtendedexecute(Session session) 
        throws RepositoryException {
        QueryManager queryManager = session.getWorkspace().getQueryManager();

        ObjectExtendeditem = null;

        String queryWrapped = 
            "select * from [th:this] as c where name(c)='lang_" 
            + language + "' and c.[th:mylabel] "
                    + "= '" + queryStr + "'";
        LOGGER.debug("Query: " + queryWrapped);
        Query query =
            queryManager.createQuery(queryWrapped,Query.JCR_SQL2);

        QueryResult result = query.execute();
        NodeIterator iter = result.getNodes();
        while (iter.hasNext()) {
            Node node = iter.nextNode().getParent();

            if (node.isNodeType("th:term")) {
                item = new ObjectExtended();
                item.setLabel(getLabel(language, node));
                item.setPath(node.getPath());
            }
        }
        return item;
    }
    });
}

为什么会这样?我做错了什么?

1 个答案:

答案 0 :(得分:1)

该错误消息意味着两件事之一:存储库正在关闭,或者正在调用Session.logout()方法。

以上代码均未显示您的会话是如何管理的,并且您没有说明您是否正在使用框架。但是我怀疑你在某种程度上持有会话太长时间(可能在你的框架关闭会话之后),或者会话泄漏到多个线程,并且一个线程试图在另一个线程关闭它之后使用它。

后者可能是一个真正的问题:将一个Session实例从一个线程传递到另一个线程是可以的(只要原始线程不再使用它),但是根据JCR 2.0规范{{1实例不是线程安全的,不应该由多个线程同时使用。

如果您在代码中创建会话,那么使用Session块通常会很好:

try-finally

请注意Session session = null; try { session = ... // acquire the session // use the session, including 0 or more calls to 'save()' } catch ( RepositoryException e ) { // handle it } finally { if ( session != null ) { try { session.logout(); } finally { session = null; } } } 不会抛出logout(),因此上述表单通常效果很好。当然,如果您知道以后在方法中没有使用RepositoryException,则不需要内部session来清空try-finally引用:

session

这种逻辑很容易被封装。