jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Luiz Fernando Teston <feu.tes...@caravelatech.com>
Subject Invalid item state while adding nodes on different sessions on multi thread environment
Date Tue, 08 Dec 2009 17:40:21 GMT

I just found an strange behavior while using multiple sessions on multi
thread environment. I'd like to know if I did something wrong.
My application code do this:
1 - before start to work, it creates a root node inside a new session. It
saves and close this session.
2 - create a bunch of workers. Each worker has its own session.
3 - each worker adds nodes inside the root node retrieved by its session. It
saves and do a logout properly.
4 - fill this workers on a list of Callables to be passed to an java 5
5 - it executes all workers on the ThreadPool.
6 - it do some asserts to verify if it gots some errors or not.

During phase 5 it gots an exception telling this:

javax.jcr.InvalidItemStateException: Item cannot be saved because it has
been modified externally: node /
at org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:245)
at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:939)
at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:915)

I just wrote a test to simulate this behavior. Sometimes it got this error
sometimes not. Also to be easy to simulate this error, just change the
THREAD_SIZE and NODE_SIZE variables.

I'm very thankful for your help!

Fernando Teston

---- test code -----

package org.openspotlight.jcr.provider.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.jcr.Node;
import javax.jcr.Session;

import org.junit.Assert;
import org.junit.Test;

public class MultithreadedSessionTest {

enum Status {

class Worker implements Callable<Status> {

private final Session session;
private final int i;

public Worker(final Session session, final int i) {
this.session = session;
this.i = i;

public Status call() throws Exception {
try {

Node parent1 = session.getRootNode().getNode("root");
for (int j = 0; j < NODES_SIZE; j++) {
parent1 = parent1.addNode("node_" + i + "_" + j);
return Status.OK;
} catch (final Exception e) {
return Status.ERROR;


private final int THREAD_SIZE = 100;

private final int NODES_SIZE = 10;

private Session openSession() {
                // TODO - here opens a new session
public void shouldInsertNodesInParallel() throws Exception {
final Session s = openSession();
final List<Callable<Status>> workers = new ArrayList<Callable<Status>>(

for (int i = 0; i < THREAD_SIZE; i++) {
final Session session = openSession();
workers.add(new Worker(session, i));

final ExecutorService threadPool = Executors.newFixedThreadPool(4);
final List<Future<Status>> resultList = threadPool.invokeAll(workers);
for (final Future<Status> result : resultList) {



  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message