0

1 つの関数内で複数の Modeshape アクションを使用すると、次のエラーが発生することがあります。

javax.jcr.RepositoryException: ID が「060742fc6」のセッションは閉じられており、使用できなくなりました。

Web上でこれに関する説明を見つけることができませんでした。これが私が呼ぶものです:

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

なぜこれが起こっているのですか?私は何を間違っていますか?

4

1 に答える 1

1

このエラー メッセージは、リポジトリがシャットダウンされているか、Session.logout()メソッドが呼び出されているかのいずれかを意味します。

上記のコードはどれも、セッションがどのように管理されているかを示しておらず、フレームワークを使用しているかどうかも示していません。しかし、どういうわけか、セッションを長時間保持している (おそらくフレームワークがセッションを閉じた後) か、セッションが複数のスレッドにリークしており、1 つのスレッドが他のスレッドが閉じた後にそれを使用しようとしていると思われます。

後者は実際の問題になる可能性があります。あるスレッドから別のスレッドに単一のSessionインスタンスを渡すことは問題ありませんが (元のスレッドがそれを使用しなくなっている限り)、JCR 2.0 仕様によると、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ため、通常は上記の形式でうまく機能します。もちろん、後でメソッドを使用しないことがわかっている場合は、内部参照を null にするsession必要はありません。try-finallysession

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

この種のロジックは簡単にカプセル化できます。

于 2013-10-31T12:05:47.203 に答える