Hi all,
I have the following problem: in a web application that gets some of
it's content from jackrabbit, I have to implement a monitor process that
periodically checks whether the JCR is still alive and usable by the
application.
I'm testing locally on tomcat 5.0 that hosts my web application which
uses a remote Oracle database for a part of its data and a JCR which is
configured to also use a remote Oracle database for a different part of
its data. My use case is to unplug my network cable to simulate losing a
connection.
I thought that if I tried to retrieve some content that is also used by
the application I would get an indication whether the JCR is able to
retrieve it or not, but it turns out not to be a good choice. The JCR
caches the information that is retrieved, so if my network cable is in
place and I access the JCR for some node path containing some content
and it is retrieved successfully, unplugging the network cable and
trying to retrieve the same content again will also succeed.
I than had the idea to create a dummy node if it was not already present
in the JCR or delete it if it wasn't. Similar to the previous attempt, I
use the Spring JcrTemplate in which I use the JcrCallback interface to
execute these actions. When the network cable is in place, everything
works ok (of course). When I unplug, I get the desired behavior that
calling save() on the session fails after creating a dummy node
underneath the root. But, when I reconnect my network cable, the JCR
does not seem to recover from the previous error and throws a
javax.jcr.ItemNotFoundException for UUID of the dummy node that was
created in a previous run (see stacktrace). The JCR seems to keep state
somewhere, which is logical since I get the Session from the same
sessionfactory in Spring eveytime...
Caused by: javax.jcr.ItemNotFoundException:
33d0f734-2ad7-4097-a3b2-fd349d0b0ba2
at
org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.ja
va:467)
at
org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:323)
at
org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:7
96)
at
org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:740)
at
org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:687)
at
org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1912)
....
....
I'm using JCR version 1.2.1, java 1.4.2, Oracle 9.2.1
Does anybody have an idea on how to tackle this properly?
Raymond
The code:
result = (Boolean) template.execute(new JcrCallback() {
public Object doInJcr(final Session session) throws
RepositoryException {
Boolean success = Boolean.FALSE;
Node rootNode = session.getRootNode();
try {
createDummyNode(rootNode);
session.save();
success = Boolean.TRUE;
} catch (RepositoryException e) {
// Rollback any changes
session.refresh(false);
throw e;
} finally {
session.logout();
}
return result;
}
});
private void createDummyNode(Node rootNode) throws RepositoryException {
boolean hasNode = false;
try {
hasNode = rootNode.hasNode("dummy");
} catch (RepositoryException e) {}
if (hasNode) {
Node dummyNode = rootNode.getNode("dummy");
dummyNode.remove();
} else {
rootNode.addNode(("dummy");
}
}
Spring config:
<bean id="jcrTemplate" class="org.springmodules.jcr.JcrTemplate">
<property name="sessionFactory" ref="jcrSessionFactory" />
<property name="allowCreate" value="true" />
</bean>
<bean id="jcrRepository"
class="nl.anwb.autoportaal.dao.jackrabbit.RepositoryFactoryBean">
<property name="configuration"
value="classpath:jcr-repo-jndi.xml"/>
<property name="repositoryHome"
value="data/jackrabbit-repository"/>
</bean>
<bean id="jcrSessionFactory"
class="org.springmodules.jcr.JcrSessionFactory">
<property name="repository" ref="jcrRepository" />
<property name="credentials" ref="credentials"/>
</bean>
<bean id="credentials" class="javax.jcr.SimpleCredentials">
<constructor-arg index="0" value="bogus"/>
<constructor-arg index="1">
<bean factory-bean="password" factory-method="toCharArray"/>
</constructor-arg>
</bean>
<bean id="password" class="java.lang.String">
<constructor-arg index="0" value="somepassword"/>
</bean>