JSR-170 is a Java Specification Request, that is, a standardized Java API for managing content in an abstract way. Every item in the repository has a path, and optionally an unique ID. It is developed under the Java Community Process, also known as JCP.
Why use JCR? Well, JCR gives you a very powerful metaphor for managing your content. Everything, including the content and any associated metadata, is treated similarly. All items in the repository are just Properties under an abstract location called a Node. For example, you could have a Node to hold your blog entries, located at a Node "/blog/entries/2008/10/24", and then have content for it, which would be located in "/blog/entries/2008/10/24/picture.jpg", and "/blog/entries/2008/10/24/blogentry.txt". These two properties would then be the children of the previous node, and you could easily access and list them. It's kinda like having your own, typed file system with workspaces, searching, observation and locking.
JCR repositories will also give optional goodies, like locking of content, or versioning it. The bigger ones will also give you clustering and scalability. Priha does not, but then again, that's not the aim.
The most famous implementation is probably the open source Apache Jackrabbit, which also serves as the Reference Implementation of the specification. In addition, at least Day CRX (commercial), Alfresco (open source) and eXo (commercial) also implement JSR-170.
JSR-170 is a fairly new specification, and there aren't that many implementations available yet. It is good for the marketplace if there is competition - and also, so far all of the JCR implementations are designed for large deployments.
Priha targets people who want to have a simple implementation to get the advantage of the JCR API, but don't want the complexity of using a library with many dependencies. It's the same reason why you would use e.g. HSQLDB instead of MySQL - simple is beautiful, and often enough.
And, because JCR is modular, you can always use whichever implementation you want, depending on your requirements for a particular application.
Priha is freely available under the Apache Public License, an open source license.
As mentioned, Priha does not yet completely support the full JSR-170 (though it does support all the mandatory parts). Priha supports:
The support for the following is partial, to the extent which is needed to fill the JSR-170 requirements:
The following are not supported at all at the moment:
Some of this stuff will certainly get into Priha, depending on the interests of the developers. If you want to contribute, head out to the priha-dev mailing list and help us out!
To minimize dependencies, Priha uses the JDK built-in logging library (java.util.logging). All logging is done in the "org.priha" -namespace.
Priha performance depends quite a lot on the underlying provider implementation. The built-in FileProvider is slow on writes, but can handle large files with ease. In general, Priha is quite fast doing random reads and large files; not so good when doing queries. You can do a rough benchmark by getting the source and saying "ant perftests". If you have Jackrabbit libraries in your classpath, also Jackrabbit numbers are included for reference.
Description of the tests:
Test | Description |
---|---|
FirstSess | Creation of a Session object from scratch, when the repository is not yet initialized. |
NewSession | Tests how quickly new Sessions can be created and discarded AFTER the initial session has been created. |
LargeSave | Stores a large number of large binary blobs into the repository in a two-level tree hierarchy. |
LargeRead | Reads the blobs stored in LargeSave in a random fashion and measures throughput. |
LargeRemove | Removes all the Nodes created in LargeSave. |
Save | Stores a large number of mix:referenceable Nodes into a two-level hierarchy, with Properties. |
RandRead | Reads a random property from the Nodes saved in the Save test. |
SeqRead | Reads through all of the properties of the Nodes saved in the Save test using getNodes(). This tests the sequential access speed. |
getProperty | Reads the same Property (using Node.getProperty()) all over again to see the raw overhead. |
getItem | Reads the same Property (using Session.getItem()) all over again to see the raw overhead. |
propUUID | Reads the same property (using Session.getNodeByUUID().getProperty()) all over again to see the raw overhead. |
Update | Fetches a Property from a random Node, updates it, and writes it back to the repository. |
exists | Performs Session.itemExists(), 50% of time fetches a random existing node, and 50% of time a non-existing node. |
UUID | Fetches a large number of random Nodes using Session.getNodeByUUID(). |
Remove | Removes all the Nodes created in Save. |
As a sample, here are the results for Priha (and Jackrabbit). Newer versions are probably faster, and the methodology used probably does not stand against any real scientific scrutiny, so please don't use this for any actual reference. Hardware used is a Dell server with 2 x Intel E5310 quadcore Xeons at 1.6 GHz running Ubuntu Linux and latest JDK 1.6.0.
Test results. The number is operations/seconds - larger means faster. Blob size 10 kB Repository size 1000 nodes Priha version 0.7.0-svn Jackrabbit version 1.6.0 FirstSess LargeRead LargeRemove LargeSave NewSession RandRead Remove Save MemoryProvider, no cache 2 169850 3467442 1180 19393 93403 2247833 614 FileProvider, no cache 96 25883 452 362 5892 31198 272 254 FileProvider, with Ehcache 14 30809 537 386 2935 35736 439 324 JdbcProvider, no cache 0.05 36381 288 281 8153 49126 285 201 JdbcProvider, with Ehcache 454 34604 379 290 3345 47363 373 260 Jackrabbit 0.26 11636 439 236 2177 15122 526 243 SeqRead UUID Update exists getItem getProperty propUUID MemoryProvider, no cache 19599004 56721 6364 643217 493640 186773 126756 FileProvider, no cache 2163 14839 1185 34142 1849271 628239 587961 FileProvider, with Ehcache 2973 23777 1633 34199 2874278 748280 705840 JdbcProvider, no cache 2775 15994 1406 18314 2684978 737968 695660 JdbcProvider, with Ehcache 4181 24879 1765 16629 2838486 744843 702273 Jackrabbit 2569 27752 310 21650 462022 1885147 771737
As you can see, Priha is in general on par or slightly faster than Jackrabbit. With smaller repositories, Priha is faster than Jackrabbit; whereas when the repository size grows, Jackrabbit tends to perform better.
Please see doc/Configuring.txt in the source repository.
Unfortunately, JSR-170 does not define a standard way to get to a Repository object. However, Priha does support a couple of ways to do it. First, you can use the included JNDI servlet by installing it via your web.xml:
TBD, not yet completed, please someone make org.priha.test.JNDIRegistrationServlet work...
Another way is to use the RepositoryManager interface, which just simply searches for a configuration file called priha.properties from your classpath.
... Repository prihaRepository = org.priha.RepositoryManager.getRepository(); ...
Yes. Please see bugs.priha.org
"Priha" is an old Finnish word and it translates roughly as a "young man".
I am Janne Jalkanen, who wrote most of JSPWiki. At the moment I am working on Priha alone, but I hope to get more contributors.
Absolutely. If you're interested in contributing, please join the priha-dev mailing list.