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