Hi Kim,
you wrote that the session is shared among several listeners. while
it may be ok in some cases to use multiple threads that read from a
single session (this is not 100% supported), you have to make sure
that only one thread *writes* to a session instance and no other
thread reads from that session instance. Just to make sure you are
not doing work with multiple threads on the same session instance...
I used the following jsp as a test case and the listener works
fine. The jsp registers a listener for 60 seconds and prints out
the first 32 characters of any file that is created within that time:
<%@ page import="org.apache.jackrabbit.j2ee.RepositoryAccessServlet,
javax.jcr.Repository,
javax.jcr.Session,
javax.jcr.SimpleCredentials,
javax.jcr.observation.EventListener,
javax.jcr.observation.EventIterator,
javax.jcr.observation.Event,
javax.jcr.Node,
java.io.InputStream,
javax.jcr.RepositoryException,
java.io.IOException,
java.io.PrintWriter"%><html>
<head>
<title>Jackrabbit JCR-Server</title>
</head>
<body>
Listening for nt:file events:
<%
Repository rep = RepositoryAccessServlet.getRepository
(pageContext.getServletContext());
final Session s = rep.login(new SimpleCredentials("jack",
"rabbit".toCharArray()), null);
final JspWriter finalOut = out;
try {
s.getWorkspace().getObservationManager().addEventListener(
new EventListener() {
public void onEvent(EventIterator events) {
while (events.hasNext()) {
Event e = events.nextEvent();
try {
Node n = (Node) s.getItem(e.getPath
());
if (n.hasProperty("jcr:data")) {
finalOut.println("<br/>Event
occurred. Path=" + e.getPath());
InputStream in = n.getProperty
("jcr:data").getStream();
byte[] data = new byte[32];
int r = in.read(data, 0, 32);
finalOut.println("<br/>" + new
String(data, 0, r) + "<br/>");
finalOut.flush();
}
} catch (Exception ex) {
ex.printStackTrace(new PrintWriter
(finalOut));
}
}
}
}, Event.NODE_ADDED, "/", true, null, null, true);
for (int i = 0; i < 60; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ignore
}
out.println(".");
out.flush();
}
} finally {
s.logout();
}
%>
</body>
</html>
regards
marcel
Kim Altintop wrote:
Hi Marcel,
thanks for answering so quickly.
I've put together a simple class that illustrates the issue. The
whole point of
accessing the jcr:data property directly (instead of using e.g.
Workspace.copy)
it that the file is not reflected as nt:file in the target
workspace, but
rather as a binary property of a domain-specific node type.
Thanks for looking into this,
Kim
// I'm using this as a singleton Bean instantiated by Spring
(which also
// injects the session which is shared among all my listeners) with
// jackrabbit 1.2.1 under Tomcat 5.5.20 deployed in 'model 1'.
public class SimpleWebdavDropFileListener implements EventListener {
private final static Logger log = LoggerFactory.getLogger
(MyListener.class);
private Session systemSession;
public SimpleWebdavDropFileListener(Session session) {
this.systemSession = session;
ObservationManager omgr = systemSession.getWorkspace
().getObservationManager();
omgr.addEventListener(
this, // register myself
Event.NODE_ADDED, // on node added events
session.getRootNode().getPath(), // at root node
true, // and descendants
null, // not using uuid constraints
new String[] { "nt:file" }, // receiving events only
for files
false // ignoring local events
);
}
public void onEvent(EventIterator events) {
while (events.hasNext()) {
Event event = events.nextEvent();
// strip leading '/'
String path = event.getPath().substring(1);
try {
Node theFile = systemSession.getRootNode().getNode(path);
Node contentNode = theFile.getNode("jcr:content");
// this will be zero unless we're implementing
SynchronousEventListener
long dataLength = contentNode.getProperty
("jcr:data").getLength();
log.info("Just received a file and the size of it's
jcr:content/jcr:data property is: " + dataLength);
// walk through all properties and output their name and
value (as string)
// -> every property except jcr:data will have a value
printed
PropertyIterator props = contentNode.getProperties();
while (props.hasNext()) {
Property prop = props.nextProperty();
log.info(prop.getName() + " has value: " + prop.getString
());
}
} catch (Exception e) {
e.printStackTrace(); // whatever
}
}
}
}
Marcel Reutegger <marcel.reutegger <at> gmx.net> writes:
>
> Hi Kim,
>
> I'm not able to reproduce the behaviour you described. Though I
didn't use
> WebDAV to import files, but just imported them using a JCR
session.
>
> Can you please provide a code fragment that shows how you
access the content
> from within the event listener?
>
> regards
> marcel
>
> Kim Altintop wrote:
> > Hi,
> >
> > I'm trying to implement a simple "Drop Folder" setup where
users would
> > connect to one Jackrabbit workspace using (simple) WebDAV,
drop files in
> > there, and an EventListener listening for NODE_ADDED events
(restricted
> > to "nt:file") would then copy the file(s) to another
workspace. As it
> > turned out, the EventListener is able to locate the just-
dropped file
> > and read its properties but the jcr:data property is always
empty (i.e.
> > contains no data). If I change my listener to implement
> > SynchronousEventListener it works fine. However, from the
spec I would
> > expect it to work just the other way round...
> >
> > Am I getting something wrong here?
> >
> > Regards,
> > Kim
> >
> >
>
>