While working on the content repository, we felt it was easy to store data, but sometimes awkward to organize it in a way that was easy and friendly to work with java objects.
So we've developed something called a bean coder for our application. We've made it open source in case other people would want to use it. With it, you can easily persist some java beans to the repository, and retrieve them at any time.
The cool thing is that it plays nicely with the available repository search facility so that you can quickly and easily retrieve any of the persisted objects, list or maps of beans.
There's a short how-to
online, but here's a quick example showing storage of a JavaBean under the root node of a given session:Node rootNode=Session.getRootNode();
// note that storing data under the root node is probably
// a bad idea in the real world
// adding mix:referenceable makes the node's UUID available
session.save();Decoding it is just as simple:// assume findNode returns a single node
// and key matches an existing key
MyObject obj=(MyObject)JcrBeanCoder.decode(myNode);Not sure this is suitable for everyone, especially people concerned with more complete solutions, but this has been in production and working very well so far in our environment (50 servers), so just felt like we should contribute back something to the java community.
It's already integrated and used in different strategic places in the Magnolia CMS
for persisting/loading configuration of the server and also for building inbox from active workflow items. It can of course be used with any compatible JCR repository such as JackRabbit
As said above, it just works, and has already been in production for some time. What would be nice now is to get scenario such as:
- how to extend the library
- how would other use it
- if this is actually used, would it make sense to spawn a completely separate projects for it?
Message was edited by: firstname.lastname@example.org
I have been playing with the same ideas for implementing a persitent storage system for content repositories. I think JSR-170 implementations are potentially much better at storing objects than any database could ever offer. For me it seems almost the obvious step. If it does become a separate project, I might participate.
I think JSR-170 implementations are potentially much better at storing objects than any database could ever offer.
About making it a separate project : for the moment it's a "Maven2 module" of OpenWFE (openwfe-jcr), you can load it as a dependency without 'loading' the rest of OpenWFE. We're in the process of making further dependencies a bit lighter. So for the moment, in our opinion, it's separate enough.
I think this is a great idea. For the future direction, I think it should provide the following features:
1. Object reference resolution. Java serialization lump entire object graph into one chunk of binary. Each object should be stored independently to be useful.
2. Object query support, especially matching the JCR's query language. There are several XPath to Java object query tool such as Jxpath
. It would be nice to be able to query stored Java objects the same way as access the JCR content.
3. Option to store Java object in XML format instead of binary format.
The big question is - what direction you are going.
Either you take your existing beans (POJO model) and generate JCR repository metadata from it, along with binding code.
Or you take existing JCR metadata and generate POJOs to access it, along with binding code.
In the end everyone likes to work with POJOs, and leave all uninteresting work to automatically generated code.
So both scenarios look plausible, and we end up with a sort Hibernate-for-JCR solution. Good idea, but when you look at all that stuff in between, like lazy loading, versioning on updates... well, it's a huge undertaking.
* * *
A while ago I've made a somewhat alike thing for JCR. It was a sort of helper class that constructs POJO beans dynamically, based on given JCR Node object and populates it with property values from the Node. This way new properties could be added to JCR metadata and be used from the page template, without changing single line of Java code in between.
all your points look really interesting.
We've been focusing so far on the first solution, as in we knew the shape of the beans we wanted to store in the JCR.
It looks possible to start working along the same lines as what you did. I am not sure how far we can go in this direction though. I feel like it would be possible and easy for simple java beans, but I am not sure about more complete and complex ones. What was the idea behind the helper class you wrote ? What kind of beans could you encode ?
Lazy loading was discussed about while writing the code, and I'd be interested in knowing if some people have some input, implementation solution for this. Do you ?
Versioning on updates can also be seen in two different ways:
- the beans version has changed
- the coder version has changed
which one were you thinking about ?
Would a simple filter on load work for the first case ?
Thank you for your feedback !
OK let's concentrate on POJO->JCR metadata scenario, I think most people go this way anyway.
(My helper class was doing quite opposite - say you have an Article JCR type with a few fields like 'author', 'dateOfCreation', 'dateOfPublication' and so on. Normally you need have to have a value object to have getters and setters for these properties. But I've got a few types of articles and new fields were added just to be shown at the web page separately. What I've done is a class that takes a Node instance, retrieves its properties and using CGLIB dynamically constructs a Class for just these properties appearing in the Node. This way, adding another property to JCR and using it from page template would not require updating code with another getter/setter pair. Thus in fact, I've built a transparent brigde from JCR to page templates.)
I've just took a brief look at graffito and, hmm, it looks like Hibernate before 1.5 annotations and XDoclet, a little bit ugly to my taste. I would definitely prefer something along the latest trends, targeted to really lazy guys like me - something that uses reflection and annotations where appropriate (e.g. ignore field or override name) and does everything in transparent and inobtrusive way.
Ideally, it should allow you to take my POJO model and use some ANT task to generate "JCR bindings" and JCR repository metadata.
I would also prefer persistence layer to take care of eventual updates and persist my changes without making explicit update() calls (unless overridden by me).
To implement lazy loading you need to construct proxy objects dynamically, a proxy that still maintains a connection with original JCR Node object and will retrieve data from this Node on demand.
Under 'versioning on update' I meant probably something different, namely that if you retrieve an object and then the same object once again, and then you save first one, and then you try to save second one - and then your persistence layer says something - "no way, you trying to update an object that is already updated" or "you're trying to update object state that doesn't exist anymore".
Class inheritance and interface inheritance look rather straightforward to map into JCR metadata.
So, Nicolas, if you are going to start implementing generic object persistence for JCR, let me know. Being a greatest fan of JCR, I can probably contribute something.
I pretty much thing, we could/should provide without too much work a similar helper class. The value I am seeing is actually in handling different versions of the bean itself: it would be nice and easy to create the new beans with the content from the JCR.
We tried to avoid any of Graffito/Hibernate, because of the same reasons you are citing: make it easy, transparent, inobtrusive to the code. Keep it simple and easily integrated was the main goal.
generic object persistence sounds awesome. Problem being for us, to actually identify the steps so that it is possible work on it gradually and modularly.
- We could then add more "persistence" like functionalities thus avoiding the all-or-nothing.
- This would also make external contribution possible and easy to integrate, with a focus on different part of the persistency work.
I obviously cannot say: "I am going to get a generic object persistence layer for JCR in a month", but I would like to make the library open for such eventualities.
So I call you when I start working on it right ?
You might contact me at "timur at jacum dot com" address, so we can discuss these matters without polluting this thread with technical details.
I'm very happy to see that more and more people are interesting to persist java beans into a JCR repository. We are calling this concept "OCM" (object content mapping). This can offer complete abstraction on the JCR technology without loosing its flexibility.
Concerning Graffito : of course, some features are missing like annotations, object cache, ... but we plan to do so.
Please wait! The communities for this kind of tools are generally small. You will not found a JCR persistence framework with all features you are dreaming on. The most important is to exchange ideas and build communities. That's why there are some discussions to move the Graffito OCM tools inside Jackrabbit.
you forgot to add a link to your project :
(well, rather a link to one of the topic addressed by your project).
Hi there, the library looks great i will try it with my application for sure. I made a post about the JCR 170 in the discussion area, but no one answered me and i think you guys could...check out my post at http://www.theserverside.com/discussions/thread.tss?thread_id=42522
Thank you and continue your good work.
Why not use http://carbonado.sourceforge.net
/? Amazon.com opensource!
tried to have a look, but the site said it was still in planning phase, and I could not access the svn repository...
we're just focussing on storing simple Java beans into JCR repositories.
You seem to want to drive the way your fields are mapped to the JCR; in our solution, you leave that to the JcrBeanCoder (that takes advantage of the hierarchical nature of the JCR specification).
I too have been playing with this idea for some time, and am thankful that someone with more time and resources has worked to a more complete solution than what I currently have... Good work.
There is some similar code in the graffito (in incubation) subproject at apache (http://incubator.apache.org/graffito/jcr-mapping/index.html
) for a general Object-JCR mapping tool. Having looked at their code and concepts I'm excited to look at this project too.
In terms of generating the content model or the object model, I'm thinking that with a bit of thought/work the same tooling concepts that Hibernate uses should be possible, allowing you to design either side of the model and generate the other...
Thanks again for the great work.
hibernate can map to xml data so why not just adding functionality so hibernate can map to jcr data? ...instead of yet another objectdata mapping tool?
This is great news
I was thinking about implementing same thing, now I see that not some one else has implemented it earlier but also several implementations are available (according to other posts).
One week ago and idiot told me JCR is a specification no one is using and no body is working on it and it is totally useless!
I hope this project and other Object JCR mapping tools become as mature as Object Relational mapping tools are today.
May be some one can take EJB 3.0 persistence API and implement it over JCR?
i agree. a JPA connector to the JCR, even a partial implementation, would be ideal.
Nobody? We have been developing Magnolia - Simple Enterprise Content Management - on top of it for more than three years, and is used around the world in 15 languages by thousands of companies.
(and I am glad that John & Nico make their work no this available on a broader scope)
do you have any information about performance and scalibity of magnolia?