Re: Lucene JCR Index

2006-01-25 Thread Nicolas Belisle

Hi,

Sorry for my late response.

I took a quick look at Compass documentation.
I think one has to subclass 
org.compassframework.core.lucene.engine.store.AbstractLuceneSearchEngineStore 
if he wishes to add a custom storage mechanism.
They use a connection parameter for configuration. 
LuceneSearchEngineStoreFactory seems to create the appropriate 
AbstractLuceneSearchEngineStore implementation based on the connection 
prefix. One could add, for example, a jcr: prefix that looks in JNDI for a 
repository.
From there, one should be able to use Compass as with other storage 
mechanisms.
I do not know for transactions support. I think can they retrieve JTA 
transaction from JNDI. I suppose the storage implementation is responsible 
for publishing it ?


Regards,

Nicolas


Le 20:25 2006-01-12, vous avez écrit:

Hi

must be lucene-day today
see also:
http://www.theserverside.com/news/thread.tss?thread_id=38478
their main feature:
Being able to store the Lucene indexes in a database [...]
haven't had a deeper look at yours but maybe your project can align nicely 
with compass.
I like compass because it works nicely with spring, so a JCR+Lucene+Spring 
stack would be good.


If it doesn't fit in your strategy just ignore it as a random wild thought.

kind regards
Philipp

Nicolas Belisle wrote:


Hi,

I've contributed a JCR Directory implementation for Lucene.

What it does: allows the storage of indexes in a JCR repository






Re: XML schema to node types

2006-01-25 Thread Nicolas Belisle

Hi Peeter,

(Sorry for the late response)

Many thanks for the contribution.
This is a great addition to Jackrabbit. This will ease the integration of 
existing formats.


I haven't had time to test it yet, but will have a deep look at it in a few 
weeks.


Regards,

Nicolas


Le 21:54 2006-01-09, vous avez écrit:

Hi Mike,

You are right about that bug.

I have intermittent access to a useful computer right now (travelling)
and can't commit stuff (for some mysterious reason) but I have
arranged to have a patch applied by another committer which should fix
tthe specific problem. As for the more general issue of dealing with
the default namespace I will take a look at that when I get a chance.

Of course your are free to fix stuff yourself and send patches to me
or another commiter.

Actually could you clarify exactly what the default namespace issue is
again? I am not quite sure I see what you mean (though I am sure you
are right :-)

Sorry I can't be of more help at the moment,

Cheers,
Peet


On 1/10/06, Michael Daglian [EMAIL PROTECTED] wrote:
 Hello Peeter,

 Apologies if I am misusing the schema converter code you committed but I
 am a bit confused as to how to make use of the NamespaceExtractor class.
 As demonstrated in your test-case for the SchemaConverter I am
 attempting to use an extractor to get the additional namespaces out a
 schema file. However, this does not appear possible due to the use of
 getURI for the mapping property:

 

 if (mapping.getURI(prefix) != null){...

 

 The NamespaceMapping class throws an exception if the prefix is unmapped
 and thus the empty NamespaceMapping created using the default structure
 always generates this exception, which only gets caught and logged.

 On another note, it seems unclear how to best handle the default
 namespace using the NamespaceMapping class. When using the reader and
 explicitly mapping the namespace to be  (i.e
 NamespaceMapping.setMapping(, );), this works fine. But when
 outputting it writes the default namespace in a manner that the reader
 cannot read. Is there a recommended way of handling this case? Thanks!

 Best Regards,

 -- Mike


 On 12/20/05, Peeter Piegaze [EMAIL PROTECTED] wrote:
 
  Hi Nicolas,
 
  Regarding your interest in XML schema to JCR node type conversion: I
  have committed the XSD to JCR node type converter into
  contribs/nt-ns-util
 
  Cheers
  Peeter
 
 
  On 10/31/05, Nicolas Belisle [EMAIL PROTECTED] wrote:
   Great news !
  
   I'm looking forward to this.
  
  
   Many thanks,
  
   Nick
  
  
   Hi Nicholas, Actually, I wrote something that does this. I haven't
  gotten
   around to completely finishing it yet, but I will take your mail as a
   motivator to do just that. Then I will commit to contribs. Cheers,
  Peeter
   On 10/31/05, Nicolas Belisle [EMAIL PROTECTED] wrote: 
   Hi,   I'm currently investigating ways to convert XML schemas to
   Jackrabbit node  types declaration. This way, most metadata formats
   (Dublin Core, MARC21,  etc.) could be integrated easily in a
  Jackrabbit
   repository.   Anyone has done something in that direction and would
  like
   to its share  ideas ? Any other comments on this ?   I would
  certainly
   contribute the result back to Jackrabbit.Regards,   Nick  
  
  
 






Lucene JCR Index

2006-01-11 Thread Nicolas Belisle

Hi,

I've contributed a JCR Directory implementation for Lucene.

What it does: allows the storage of indexes in a JCR repository
Why: single place for content and index storage, transaction support (if 
the JCR implementation support them),
Performance: JCR does not support random access (only plain Inputstreams), 
but my implementation splits the files into fixed-size buffers to help 
performance. It will also depend on the persistence mechanism used with JCR.

Status: beta

You can retrieve the code there:
http://issues.apache.org/jira/browse/LUCENE-484

I welcome your comments.

Regards,


Nicolas Bélisle

Laval University Library










Removing a version

2005-11-18 Thread Nicolas Belisle

Hi,

I'm trying to remove a version of a Node, but the 
VersionHistory.removeVersion() method throws : 
javax.jcr.ReferentialIntegrityException: Unable to remove version. At 
least once referenced..


Secton 8.2.2.10 (Removal of Versions) of the specification indicates that 
the version graph should be automatically repaired upon removal. Then, 
VersionHistory.removeVersion() should take care of references. In fact, a 
user cannot alter the references (jcr:predecessors and jcr:successors), 
since they are protected properties.


Here's the example :

Node root1 = session.getRootNode() ;
Node test1 = root1.addNode(test) ;
test1.addMixin(mix:versionable);
test1.setProperty(test, 1);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 2);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 3);
session.save();
test1.checkin();

VersionHistory vh = test1.getVersionHistory();
for (VersionIterator vi = vh.getAllVersions(); vi.hasNext(); ) {
Version currenVersion = vi.nextVersion();
String versionName = currenVersion.getName();
if (!versionName.equals(jcr:rootVersion)) {
String propertyValue = 
currenVersion.getNode(jcr:frozenNode).getProperty(test).getString();
System.out.println(Removing version :  + versionName +  
with value:  + propertyValue);

vh.removeVersion(versionName);
}
}

Something I do wrong ?


Many thanks,


Nicolas



Re: Removing a version

2005-11-18 Thread Nicolas Belisle

Hi,

I have already verified that.

The error is for removal of version name : 1.0 and the base version name 
is 1.2.


I've updated the example to make sure it never tries to remove the base 
version :


Node root1 = session.getRootNode() ;
Node test1 = root1.addNode(test) ;
test1.addMixin(mix:versionable);
test1.setProperty(test, 1);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 2);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 3);
session.save();
test1.checkin();

String baseVersion = test1.getBaseVersion().getName();
System.out.println(Base version name:  + baseVersion);

VersionHistory vh = test1.getVersionHistory();
for (VersionIterator vi = vh.getAllVersions(); vi.hasNext(); ) {
Version currenVersion = vi.nextVersion();
String versionName = currenVersion.getName();
if (!versionName.equals(jcr:rootVersion)  
!versionName.equals(baseVersion)) {
String propertyValue = 
currenVersion.getNode(jcr:frozenNode).getProperty(test).getString();


System.out.println(Removing version :  + versionName +  
with value:  + propertyValue);

vh.removeVersion(versionName);
}
}

Thanks,

Nicolas


Le 12:23 2005-11-18, vous avez écrit:

Hi Nicolas,

 I didn't try your code but I think it throws
ReferentialIntegrityException because you are trying to remove the
base version which is referenced by the versioned node.

see http://thread.gmane.org/gmane.comp.apache.jackrabbit.devel/3746

br,
edgar


On 11/18/05, Nicolas Belisle [EMAIL PROTECTED] wrote:
 Hi,

 I'm trying to remove a version of a Node, but the
 VersionHistory.removeVersion() method throws :
 javax.jcr.ReferentialIntegrityException: Unable to remove version. At
 least once referenced..

 Secton 8.2.2.10 (Removal of Versions) of the specification indicates that
 the version graph should be automatically repaired upon removal. Then,
 VersionHistory.removeVersion() should take care of references. In fact, a
 user cannot alter the references (jcr:predecessors and jcr:successors),
 since they are protected properties.

 Here's the example :

  Node root1 = session.getRootNode() ;
  Node test1 = root1.addNode(test) ;
  test1.addMixin(mix:versionable);
  test1.setProperty(test, 1);
  session.save();
  test1.checkin();

  test1.checkout();
  test1.setProperty(test, 2);
  session.save();
  test1.checkin();

  test1.checkout();
  test1.setProperty(test, 3);
  session.save();
  test1.checkin();

  VersionHistory vh = test1.getVersionHistory();
  for (VersionIterator vi = vh.getAllVersions(); vi.hasNext(); ) {
  Version currenVersion = vi.nextVersion();
  String versionName = currenVersion.getName();
  if (!versionName.equals(jcr:rootVersion)) {
  String propertyValue =
 currenVersion.getNode(jcr:frozenNode).getProperty(test).getString();
  System.out.println(Removing version :  + versionName + 
 with value:  + propertyValue);
  vh.removeVersion(versionName);
  }
  }

 Something I do wrong ?


 Many thanks,


 Nicolas






[jira] Created: (JCR-272) Removal of versions throws javax.jcr.ReferentialIntegrityException

2005-11-18 Thread Nicolas Belisle (JIRA)
Removal of versions throws javax.jcr.ReferentialIntegrityException
--

 Key: JCR-272
 URL: http://issues.apache.org/jira/browse/JCR-272
 Project: Jackrabbit
Type: Bug
  Components: versioning  
Versions: 1.0
 Environment: CVS build (2005-11-16) and DerbyPersistenceManager
Reporter: Nicolas Belisle


From the following thread : 
http://www.mail-archive.com/jackrabbit-dev%40incubator.apache.org/msg03483.html

When trying to remove a version of a Node  the VersionHistory.removeVersion() 
method throws : javax.jcr.ReferentialIntegrityException: Unable to remove 
version. At least once referenced..

Secton 8.2.2.10 (Removal of Versions) of the specification indicates that the 
version graph should be automatically repaired upon removal. Then, 
VersionHistory.removeVersion() should take care of references. (In fact, a user 
cannot alter the references (jcr:predecessors and jcr:successors), since they 
are protected properties.)

Here's the example (*updated) :

Node root1 = session.getRootNode() ;
Node test1 = root1.addNode(test) ;
test1.addMixin(mix:versionable);
test1.setProperty(test, 1);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 2);
session.save();
test1.checkin();

test1.checkout();
test1.setProperty(test, 3);
session.save();
test1.checkin();

String baseVersion = test1.getBaseVersion().getName();
System.out.println(Base version name:  + baseVersion);

VersionHistory vh = test1.getVersionHistory();
for (VersionIterator vi = vh.getAllVersions(); vi.hasNext(); ) {
Version currenVersion = vi.nextVersion();
String versionName = currenVersion.getName();
if (!versionName.equals(jcr:rootVersion)  
!versionName.equals(baseVersion)) { 
String propertyValue = 
currenVersion.getNode(jcr:frozenNode).getProperty(test).getString();
System.out.println(Removing version :  + versionName +  with value: 
 + propertyValue);
vh.removeVersion(versionName);
}
}

Regards, 

Nicolas

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira



XML schema to node types

2005-10-31 Thread Nicolas Belisle

Hi,

I'm currently investigating ways to convert XML schemas to Jackrabbit node 
types declaration. This way, most metadata formats (Dublin Core, MARC21, 
etc.) could be integrated easily in a Jackrabbit repository.


Anyone has done something in that direction and would like to its share 
ideas ? Any other comments on this ?


I would certainly contribute the result back to Jackrabbit.


Regards,

Nick



Re: XML schema to node types

2005-10-31 Thread Nicolas Belisle

Great news !

I'm looking forward to this.


Many thanks,

Nick


Hi Nicholas, Actually, I wrote something that does this. I haven't gotten 
around to completely finishing it yet, but I will take your mail as a 
motivator to do just that. Then I will commit to contribs. Cheers, Peeter 
On 10/31/05, Nicolas Belisle [EMAIL PROTECTED] wrote:  
Hi,   I'm currently investigating ways to convert XML schemas to 
Jackrabbit node  types declaration. This way, most metadata formats 
(Dublin Core, MARC21,  etc.) could be integrated easily in a Jackrabbit 
repository.   Anyone has done something in that direction and would like 
to its share  ideas ? Any other comments on this ?   I would certainly 
contribute the result back to Jackrabbit.Regards,   Nick  




Re: Problems with concurrent sessions

2005-07-21 Thread Nicolas Belisle

Hi Marcel,

If all three tryLock() fail, the event is certainly active. The event is 
then waiting for an ACTIVE lock to be released (the last tryLock() confirms 
that fact). The event is not cancelled/removed until the lock is obtained. 
Then doInTransaction() is called.


The only way I see to stop the transaction from executing is to stop the 
server...


Am I missing something ?

Regards,

Nicolas


Le 05:54 2005-07-19, vous avez écrit:

Hi Nicolas,

Looks better now, but there are still cases where the doTransaction() 
method will not be called, though very unlikely: when all three tryLock() 
attempts fail. not very likely but theoretically possible...


regards
 marcel

Nicolas Belisle wrote:

Hi,
Thanks again for your comments.
Here's the second version of my template class. It should resolves the 
concurrency issues you mentionned :

package app;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
public abstract class SerializableTemplate {
private Session session;
private Node scope;
private boolean done = false;
private EventListener el;
public SerializableTemplate(Repository repository, Credentials cr, 
String scopePath) throws LoginException, RepositoryException {

session = repository.login(cr);
scope = session.getRootNode().getNode(scopePath);
//scope = session.getNodeByUUID(scope.getUUID());
}
public abstract void doInTransaction(Session session) throws 
RepositoryException;

public void execute() throws RepositoryException {
if (tryLock()) {
return;
}
this.el = new EventListener() {
public void onEvent(EventIterator events) {
try {
tryLock();
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
}
};

session.getWorkspace().getObservationManager().addEventListener(el, 
Event.PROPERTY_REMOVED, scope.getPath(), true, null, null, false);
//Try again, in case the lock is removed before observer could 
be put in place

tryLock();
}
private synchronized boolean tryLock() throws RepositoryException {
try {
if (done) {
return false;
}
if (!scope.isLocked()) {
scope.lock(true, true);
try {
if (el != null) {

session.getWorkspace().getObservationManager().removeEventListener(el);
}
doInTransaction(session);
} finally {
done = true;
if (session.isLive()) {
session.logout();
}
}
return true;
}
} catch (LockException e) {
e.printStackTrace();
}
return false;
}
}
Here's how to use it :
SerializableTemplate sTemplate = new SerializableTemplate(repository, new 
SimpleCredentials(user, password.toCharArray()), node/path) {

//@Override
public void doInTransaction(Session session) throws 
RepositoryException {

//Do your favorite transaction...
};
sTemplate.execute();

For the constructor you suggested, I actually came up with a similiar 
design at first, but found a problem with it : since the template class 
might use an EventListener the class should be responsible for closing 
the session (the EventListener can wait a while...). Else, the event 
could be removed by the user before being invoked. That's the reason for 
my ugly constructor.

I welcome your comments again...
Regards,
Nicolas




Re: Giving a name to the workspace ?

2005-07-18 Thread Nicolas Belisle

Hi,

Please, read the following thread : 
http://thread.gmane.org/gmane.comp.apache.jackrabbit.devel/2660


= WorkspaceImpl.createWorkspace()

Regards,

Nicolas


Le 09:49 2005-07-18, vous avez écrit:

Hi,
I would like to create a workspace in my repository with a name (soacms 
in this case). I saw the getName() method for the workspace, but not the 
setName method...

So, I don't see how I have to set its name ?

Thank you for your help...
Jessica




Re: Problems with concurrent sessions

2005-07-15 Thread Nicolas Belisle

Hi,

Thanks again for your comments.

Here's the second version of my template class. It should resolves the 
concurrency issues you mentionned :


package app;

import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;

public abstract class SerializableTemplate {

private Session session;
private Node scope;
private boolean done = false;
private EventListener el;

public SerializableTemplate(Repository repository, Credentials cr, 
String scopePath) throws LoginException, RepositoryException {

session = repository.login(cr);
scope = session.getRootNode().getNode(scopePath);
//scope = session.getNodeByUUID(scope.getUUID());
}

public abstract void doInTransaction(Session session) throws 
RepositoryException;


public void execute() throws RepositoryException {
if (tryLock()) {
return;
}

this.el = new EventListener() {
public void onEvent(EventIterator events) {
try {
tryLock();
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
}
};
session.getWorkspace().getObservationManager().addEventListener(el, 
Event.PROPERTY_REMOVED, scope.getPath(), true, null, null, false);


//Try again, in case the lock is removed before observer could be 
put in place

tryLock();
}

private synchronized boolean tryLock() throws RepositoryException {
try {
if (done) {
return false;
}

if (!scope.isLocked()) {
scope.lock(true, true);
try {
if (el != null) {

session.getWorkspace().getObservationManager().removeEventListener(el);
}
doInTransaction(session);
} finally {
done = true;
if (session.isLive()) {
session.logout();
}
}
return true;
}
} catch (LockException e) {
e.printStackTrace();
}
return false;
}
}

Here's how to use it :

SerializableTemplate sTemplate = new SerializableTemplate(repository, new 
SimpleCredentials(user, password.toCharArray()), node/path) {

//@Override
public void doInTransaction(Session session) throws 
RepositoryException {

//Do your favorite transaction...
};
sTemplate.execute();


For the constructor you suggested, I actually came up with a similiar 
design at first, but found a problem with it : since the template class 
might use an EventListener the class should be responsible for closing the 
session (the EventListener can wait a while...). Else, the event could be 
removed by the user before being invoked. That's the reason for my ugly 
constructor.


I welcome your comments again...

Regards,

Nicolas


Le 05:07 2005-07-15, vous avez écrit:

Hi Nicolas,

I can see where you are heading for ;)

I think the constructor take the node that acts as the lock scope. It 
should provide all that is needed:


public SerializableTemplate(Node scope) {
session = scope.getSession();
this.scope = scope;
}

you may then also ommit the session parameter in doInTransaction. And just 
as a minor improvement the method should be allowed to throw a 
RepositoryException.


After checking whether a node is locked it is not guaranteed that you can 
then lock the node.
A similar concurrency problem can arise when isLocked() returns true, 
between that call and the listener registration the node might get 
unlocked. so, you don't get an event for that and keep waiting.


regards
 marcel

Nicolas Belisle wrote:
I just thought about something like this (Note that I've only done a few 
tests on that class.)  :

public abstract class SerializableTemplate {
private Session session;
private Node scope;
public SerializableTemplate(Repository repository, Credentials cr, 
String scopePath) throws LoginException, RepositoryException {

session = repository.login(cr);
scope = session.getRootNode().getNode(scopePath);
}
public abstract void doInTransaction(Session session);
public void execute() {
try {
if (!scope.isLocked()) {
scope.lock(true, true);
doInTransaction(session);
if (session.isLive()) {
session.logout();
}
} else {
EventListener el = new EventListener() {
public void onEvent

Re: Problems with concurrent sessions

2005-07-14 Thread Nicolas Belisle

Hi again,

 You probably want a lock call that is blocking and returns when the lock 
could be retrieved.
 Locks in jsr-170 were primarily designed to lock nodes for a longer time 
and not just while
 in a transaction. Maybe a blocking variant of the getLock() method is 
something we should

 consider for the next jcr version.

I just thought about something like this (Note that I've only done a few 
tests on that class.)  :


import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;

public abstract class SerializableTemplate {

private Session session;
private Node scope;

public SerializableTemplate(Repository repository, Credentials cr, 
String scopePath) throws LoginException, RepositoryException {

session = repository.login(cr);
scope = session.getRootNode().getNode(scopePath);
}

public abstract void doInTransaction(Session session);

public void execute() {
try {
if (!scope.isLocked()) {
scope.lock(true, true);
doInTransaction(session);
if (session.isLive()) {
session.logout();
}
} else {
EventListener el = new EventListener() {
public void onEvent(EventIterator events) {
try {
if (!scope.isLocked()) {
scope.lock(true, true);
doInTransaction(session);
if (session.isLive()) {
session.logout();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
session.getWorkspace().getObservationManager().addEventListener(el, 
Event.PROPERTY_REMOVED, scope.getPath(), true, null, null, false);

}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

I don't like a few things about that class, especially the constructor...

What do you think overall ?

 Again I think this always depends on the application on top of the 
repository.
 Setting an isolation level as a global property does not seems to be a 
good idea to me.


Well, if many applications need control of their isolation level, maybe 
that feature should be implemented in one place or documented in a worked 
example...


Regards,

Nicolas



Le 12:34 2005-07-08, vous avez écrit:

Hi Nicolas,

Nicolas Belisle wrote:

  no, but you may use locks to further control isolation level.
There seems to be at least two problems with that approach :
- You will get a (unpleasant) javax.jcr.lock.LockException if another 
transaction tries to lock the node (or a child).


You probably want a lock call that is blocking and returns when the lock 
could be retrieved. Locks in jsr-170 were primarily designed to lock nodes 
for a longer time and not just while in a transaction. Maybe a blocking 
variant of the getLock() method is something we should consider for the 
next jcr version.


- It is not enforced even though it should be used everywhere, even for 
only a read.


This depends on the application. I don't think you have to lock the 
workspace when your applicaton is fine with an read-committed isolation level.



Sorry there was an error in my example. I should make more sense this way :
Example v.2 :
A : open session
A : read nodes test  test2
B : open session
B : delete nodes test  test2
B : save session //WHAT SHOULD HAPPEN ??
B : logout
A : read nodes test  test2 //WHAT SHOULD HAPPEN ??
A : logout


yeah, that definitively makes more sense ;)

deleting the two nodes with Session B will be successful, unless session A 
has locked the two nodes.
regarding the second attempt to read the two nodes with session A, this 
depends whether A already obtained references to the nodes or not.


If A already has reference to those two nodes, calles that read the state 
of those nodes will throw an InvalidItemStateException. Indicating that 
the nodes do not exist anymore.


If A tries to retrieve the nodes again. E.g. by calling getNodes() on the 
parent of the just deleted nodes. The returned NodeIterator will simply 
not contain the nodes anymore.


It would be useful if the isolation level could configured at the 
repository level. So if your application needs better isolation or 
performance you would only need to change the configuration and not your code.


Again I think this always depends on the application on top of the 
repository. Setting an isolation level as a global property does not seems

Re: Problems with concurrent sessions

2005-07-08 Thread Nicolas Belisle

Hi,

Many thanks for your response.

 no, but you may use locks to further control isolation level.

There seems to be at least two problems with that approach :

- You will get a (unpleasant) javax.jcr.lock.LockException if another 
transaction tries to lock the node (or a child).
- It is not enforced even though it should be used everywhere, even for 
only a read.


 I cannot quite follow you here. thread B seems to save a session without 
having
 made  changes to it? that means 'B : save session' is basically no op. 
But I guess

 that's not  what you want to know...

Sorry there was an error in my example. I should make more sense this way :

Example v.2 :
A : open session
A : read nodes test  test2
B : open session
B : delete nodes test  test2
B : save session //WHAT SHOULD HAPPEN ??
B : logout
A : read nodes test  test2 //WHAT SHOULD HAPPEN ??
A : logout

It would be useful if the isolation level could configured at the 
repository level. So if your application needs better isolation or 
performance you would only need to change the configuration and not your code.
An implementation could (hypothetically) use locks in SessionImpl and use 
events (when a session saves/logout) to prevent throwing exceptions. A 
queue would hold pending operations. However, we would have to be careful 
about long lived sessions...


What do you think ?

Regards,

Nicolas


Le 04:06 2005-07-08, vous avez écrit:

Hi Nicolas,

Nicolas Belisle wrote:
What is the session isolation level [ref. 
http://www.unix.org.ua/orelly/java-ent/ebeans/ch08_03.htm] by default ?


the default is read commited.


Is it configurable ?


no, but you may use locks to further control isolation level.

a session in jackrabbit will see changes as soon as they are committed. 
you may however use locks to achieve a higher isolation level. 
successfully setting a lock on a node will give you repeatable read for 
that subtree. if you do that on the root node you get serializable 
isolation level.


At least, Jackrabbit seems to prevent dirty reads (determined from 
tests). Is there any documentation regarding isolation level ? I think it 
is a very important topic...


Unfortunately there is currently no documentation on isolation levels, but 
this thread may be a good starting point to collect all relevant 
information and then put it into a nice xdoc or wiki page.



Example :
A : open session
A : read nodes test  test2
B : open session
A : delete nodes test  test2
B : save session //WHAT SHOULD HAPPEN ??
B : logout
A : read nodes test  test2 //WHAT SHOULD HAPPEN ??
A : logout


I cannot quite follow you here. thread B seems to save a session without 
having made changes to it? that means 'B : save session' is basically no 
op. But I guess that's not what you want to know...


regards
 marcel




Problems with concurrent sessions

2005-07-06 Thread Nicolas Belisle

Hi,

I'm a Jackrabbit newbie. I'm doing some tests with the tool and I'm having 
problem with concurrent sessions.


I have joined my (simple) test class (JCRTest) and the exception I get from 
running it.


Anyone had similar problems ?

Regards,

Nicolas


--The exception report:
java.util.NoSuchElementException: cdeab285-fdbc-4af3-918a-bf4316a29276
at org.apache.jackrabbit.core.LazyItemIterator.next(LazyItemIterator.java:157)
at 
org.apache.jackrabbit.core.LazyItemIterator.nextNode(LazyItemIterator.java:98)

at app.JCRTest$ThreadDeleter.run(JCRTest.java:107)

--The class:
package app;

import java.util.Hashtable;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.jackrabbit.core.jndi.RegistryHelper;
import org.apache.jackrabbit.core.value.StringValue;

public class JCRTest {

private Repository repository;

public JCRTest(Repository repository) {
this.repository = repository;
}

public void execute() throws Exception {
Session session = this.repository.login(new 
SimpleCredentials(, .toCharArray()), null);


Node rn = session.getRootNode();
new ThreadObserver().start();
Node n = rn.addNode(node + System.currentTimeMillis(), 
nt:unstructured);

n.setProperty(testprop, new StringValue(Hello, World.));
new ThreadDeleter().start();

session.save();
session.logout();
}

public static void main(String[] args) {
try {
String configFile = repository/repository.xml;
String repHomeDir = repository;

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, 
org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory);

env.put(Context.PROVIDER_URL, localhost);
InitialContext ctx = new InitialContext(env);

RegistryHelper.registerRepository(ctx, repo, 
configFile, repHomeDir, true);

Repository r = (Repository) ctx.lookup(repo);

for (int i = 0; i  20; i++) {
JCRTest test = new JCRTest(r);
test.execute();
}

} catch (Exception e){
e.printStackTrace();
}
}

public  class ThreadObserver extends Thread {
public void run() {
System.out.println(Observing thread started);
try {
Session session = repository.login(new 
SimpleCredentials(, .toCharArray()));

EventListener el = new EventListener() {
public void onEvent(EventIterator 
events) {

while (events.hasNext()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}

Event e = events.nextEvent();
if (e.getType() == 
Event.NODE_ADDED) {

try {
System.out.println(Node 
added :  + e.getPath());
} catch 
(RepositoryException re) {


re.printStackTrace();
}
} 


}
}
};
session.getWorkspace().getObservationManager().addEventListener(el, 
Event.NODE_ADDED, /, true, null, null, false);

session.save();
//Some time to listen
Thread.sleep(500);
session.logout();
} catch (Exception e) {
e.printStackTrace();
}
}
}

public  class ThreadDeleter extends Thread {
public void run() {

Re: How do I create more workspaces

2005-07-06 Thread Nicolas Belisle

Hi Richard,

I would suggest WorkspaceImpl#createWorkspace(), since this method is 
public rather than protected (SessionImpl#createWorkspace()).


Hope it helps,

Nicolas


Le 13:53 2005-07-06, vous avez écrit:
Apologies if this is a really dumb question but how can I create multiple 
workspaces with jackrabbit? Passing a named workspace into the login 
returns a javax.jcr.NoSuchWorkspaceException, but will create a new 
default workspace if it dosnt already exist and trawling over the API 
hasn't helped. The repository.xml file seems to define a workspace 
template rather than a list of workspaces (at least that's how I read it).


Ah, as I'm typing I can see createWorkspace() on SessionImpl -- I guess 
I'm supposed to cast an active session object to the jackrabbit 
SessionImpl and call that?


- Richard




Re: Problems with concurrent sessions

2005-07-06 Thread Nicolas Belisle

Hi Oliver,

Thanks for your response.

Thereforeall your threads have to have their own session

My code doesn't share any session between threads. Only the repository is 
shared.


 [...] or you have to synchronize session access to avoid
the exception you get (which is similar to ConcurrentModificationException
 thrown by standard SDK collections/iterators).

Then a solution (as you suggest) would like something like this :

synchronized( repository ) {
Session session = this.repository.login(new SimpleCredentials(, 
.toCharArray()), null);

//Do something
session.save();
session.logout();
}

What is the preferred approach ?

Also, if I'm responsible for preventing concurrrent sessions, then why is 
there those multithreading issues in JIRA : 
http://issues.apache.org/jira/browse/JCR-18  
http://issues.apache.org/jira/browse/JCR-155 ?


Regards,

Nicolas


Le 18:37 2005-07-06, vous avez écrit:

Nicolas,

the JCR spec does not require a session to be thread-safe so you are on
your own to take care for problems like the one you describe. Therefore
all your threads have to have their own session or you have to
synchronize session access to avoid the exception you get (which is
similar to ConcurrentModificationException thrown by standard SDK
collections/iterators).

Oliver


Nicolas Belisle wrote:

 Hi,

 I'm a Jackrabbit newbie. I'm doing some tests with the tool and I'm
 having problem with concurrent sessions.

 I have joined my (simple) test class (JCRTest) and the exception I get
 from running it.

 Anyone had similar problems ?

 Regards,

 Nicolas


 --The exception report:
 java.util.NoSuchElementException: cdeab285-fdbc-4af3-918a-bf4316a29276
 at
 org.apache.jackrabbit.core.LazyItemIterator.next(LazyItemIterator.java:157)

 at
 
org.apache.jackrabbit.core.LazyItemIterator.nextNode(LazyItemIterator.java:98)


 at app.JCRTest$ThreadDeleter.run(JCRTest.java:107)

 --The class:
 package app;

 import java.util.Hashtable;

 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 import javax.naming.Context;
 import javax.naming.InitialContext;

 import org.apache.jackrabbit.core.jndi.RegistryHelper;
 import org.apache.jackrabbit.core.value.StringValue;

 public class JCRTest {

 private Repository repository;

 public JCRTest(Repository repository) {
 this.repository = repository;
 }

 public void execute() throws Exception {
 Session session = this.repository.login(new
 SimpleCredentials(, .toCharArray()), null);

 Node rn = session.getRootNode();
 new ThreadObserver().start();
 Node n = rn.addNode(node +
 System.currentTimeMillis(), nt:unstructured);
 n.setProperty(testprop, new StringValue(Hello,
 World.));
 new ThreadDeleter().start();

 session.save();
 session.logout();
 }

 public static void main(String[] args) {
 try {
 String configFile = repository/repository.xml;
 String repHomeDir = repository;

 Hashtable env = new Hashtable();
 env.put(Context.INITIAL_CONTEXT_FACTORY,
 org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory);
 env.put(Context.PROVIDER_URL, localhost);
 InitialContext ctx = new InitialContext(env);

 RegistryHelper.registerRepository(ctx, repo,
 configFile, repHomeDir, true);
 Repository r = (Repository) ctx.lookup(repo);

 for (int i = 0; i  20; i++) {
 JCRTest test = new JCRTest(r);
 test.execute();
 }

 } catch (Exception e){
 e.printStackTrace();
 }
 }

 public  class ThreadObserver extends Thread {
 public void run() {
 System.out.println(Observing thread started);
 try {
 Session session = repository.login(new
 SimpleCredentials(, .toCharArray()));
 EventListener el = new EventListener() {
 public void
 onEvent(EventIterator events) {
 while
 (events.hasNext()) {
 try {
 Thread.sleep(100);
 } catch (InterruptedException e