Question

Sometimes when I use multiple Modeshape actions inside one function I get this error:

javax.jcr.RepositoryException: The session with an ID of '060742fc6' has been closed and can no longer be used.

I couldn't find any explanations of this on the web. Here is what I call:

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

Why is this happening please? What am I doing wrong?

Was it helpful?

Solution

That error message means one of two thing: either the repository is being shutdown, or the Session.logout() method is being called.

None of the above code shows how your sessions are being managed, and you don't say whether you are using a framework. But I suspect that somehow you are holding onto a Session too long (perhaps after your framework is closing the session), or the Session is leaking to multiple threads, and one thread is attempting to use it after the other has closed it.

The latter could be a real problem: while passing a single Session instance from one thread to another is okay (as long as the original thread no longer uses it), but per the JCR 2.0 specification Session instances are not threadsafe and should not be concurrently used by multiple threads.

If you're creating the Session in your code, it's often good to use a try-finally block:

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

Note that logout() does not throw a RepositoryException, so the above form usually works well. Of course, if you know you're not using session later on in the method, you don't need the inner try-finally to null the session reference:

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

This kind of logic can easily be encapsulated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top