Hi,

I was following the Jackrabbit project for some time now and what I was
missing so far is a good log / trace mechanism for the JCR API. So I started
to write one. If you are interested I can contribute this wrapper to
Jackrabbit 'contrib' and I can add the missing functionality and maintain
it. Here is what I have so far:

- A wrapper for a Repository. All other objects that where created directly
or indirectly (Session, Node and so on) are wrapped as well. The
java.lang.reflect.proxy mechanism is used to wrap the objects.

- The log writer. I didn't use log4j or some other external library so far,
but of course this could be done. Currently logging to a file and / or to
System.out is supported.

- A 'generic' mechanism to create Repository objects: RepositoryFactory.
Reason: I don't like calling the constructor 'new TransientRepository()'
directly in the application as you have to change the application (and
recompile) if you want to use the log wrapper (or another layer, or another
implementation). RepositoryFactory.open works like
DriverManager.getConnection in the JDBC API. So you only have to change the
'url' (a String). This url should normally not be hard coded in the
application itself but kept in a properties file or xml config file or
somewhere else. I know there is JNDI, but probably not all applications use
JNDI (I didn't use it so far).

- The log file itself can be compiled to a Java class with javac. You just
need to add the header and footer of a Java class. This doesn't work if the
log file is too big (there is a 64 KB bytecode limit for a Java method).

- A player to re-play log files. That means the relevant lines in the log
file are parsed and the statements are executed (using reflection). A very
limited subset of the Java language is supported (just enough to replay the
log file).

- Also logged is from where the JCR API was called (what line in the
application). This is done using stack trace processing. It is optional
(because it is slow). With Eclipse, you can directly jump to the calling
line (if you have the application).

Here is a sample log file:

//09-08 15:04:45
//>FirstHop.main(FirstHop.java:18)
/**/Repository rep0 = org.apache.jcrlog.RepositoryFactory.open
("apache/jackrabbit/transient");
//>FirstHop.main(FirstHop.java:19)
/**/Session s0 = rep0.login();
//09-08 15:04:48
//time: 3250
//>FirstHop.main(FirstHop.java:21)
/**/s0.getUserID();
//>FirstHop.main(FirstHop.java:22)
/**/rep0.getDescriptor("jcr.repository.name");
//>FirstHop.main(FirstHop.java:26)
/**/s0.logout();
//time: 203

- The starting time of a function is logged as well, and the time spent in
the function (if it took more than some threshold).

- So far, this wrapper works for the FirstHop, SecondHop and ThirdHop
examples. Don't expect it to work for other applications currently! But you
can try, tell me what doesn't work.

I have posted the files here (28 KB):
http://www.day.com/o.file/jcrlog.zip?get=8954e4b08c9f7b706e6c672a8cba1245

Build instructions:
- Unzip the file
- Add the relevant libraries to jcrlog/jcrlog/src/lib (jackrabbit-core,
derby, concurrent, commons-collections, and so on; whatever is required for
jackrabbit-core).
- Compile the application (I used Eclipse, but there is an ant build script
as well).
- Run FirstHop, SecondHop, ThirdHop, Player or Test

So, what do you think about it?

Thanks,
Thomas

Reply via email to