November 28, 2005, 3:56:40 am
OmniBase is an Object Oriented Database. It's great. It does almost everything I wanted to do with Elephant. What's more, it's already ported to VW, Dolphin, VA, Squeak, ST/X (and possibly more).
So, instead of reinventing the wheel with Prevayler and Elephant, I've decided to drop those projects. So since i'm dropping them I should put in the final word on them.
Prevayler works well for what it does. I built it for a friends MUSH game and I used it in the 2005 Smalltalk Solutions competition. But alas it had a few drawbacks. It used BOSS and it overrode the Immutability methods in VW.
Elephant was meant to break those problems. It used the Modtracking framework by Gemstone's Martin. This immediately means it has more life than Prevayler ever did. I also tried to make it not use BOSS so that it could be ported easily. I had a nice text format going and Blaine Buxton even had a crack at porting it. Elephant was also going to include transactions and ACID. But in the end this proved to be too much effort. Elephant works and passes its tests - but it uses BOSS still and has no transactions.
WebCanvas at Wizard Information Services is probably the true achievement of this line of thinking. It's completely in-memory, as in, it doesn't dictate any kind of persistence mechanism. You can use it with an OODB or a RDBMS. As it happens, at Wizard, we use Toplink with it to store to a DB when we're happy to commit our transaction. This framework is called Shadow Transactions. I won't explain how it works here but it's a transparent transaction mechanism. You simply modify your objects inside a transaction and you get full isolation from other Smalltalk objects reading or writing to the same objects. It works, it works really well. We write the Shadow's to a DB so that we can suspend/resume transactions as well. It's great fun.
Since Shadow Transactions is really Wizard's baby and it /isn't/ a persistent mechanism (only a transaction one), I thought I'd see what else was out there to satisfy my apetite. I'd heard Mark Roberts talk about Omnibase before and Sean Malloy also pointed me to it when we were discussing SimpleWeb.
So OmniBase suddenly was on the radar in a big way. I read the doco and FAQ on it and thought "Hey, this sounds great." I've since tried it out and played with a bit more and decided that I like it a lot. It takes away all the effort and doesn't require a full OODB solution like Gemstone. Great!
So I'm hereby dropping Prevalyer and Elephant in place of OmniBase. But not before I've hacked at it a bit :)
I've just published OmniBaseTracker to public store. Basically, it draws on some of my Elephant experience and Shadow Transactions experience to make OmniBase more transparent. The thing that disturbed me with OmniBase was this constant #markDirty send I had to put every where. Any time I changed an OrderedCollection or BusinessObject I would have to mark it as dirty.
This is a well known limitation with OmniBase, as described in the presentation given at Bled by OmniBase's author. He actually gave the answer in his presentation on how to fix this... so I've done it.
I've used ModTracking to manage the persisted objects of OmniBase. Each object becomes "immutable" and managed by the OmniBaseModificationPolicy. So, whenever you try to change an object stored in the database, the new value you're setting will become auto-managed and the object you're setting it on will be marked dirty.
On top of that, any object you make persistent and any object you read back will automatically become managed with the OmniBaseModificationPolicy too.
The only trick left is "how much do I auto-manage" (the age old question with Object traversal!). I've left that up to you. I've made a method called #odbIsPersistent which when ^true will become its own entity in the OmniBase database. String/Number/Date/Time are currently set to ^false and Object is set to ^true. That should cover most cases.
So if you're using VisualWorks and OmniBase and you're sick of #markDirty then load up OmniBaseTracker.
| omni txn | omni := OmniBase openOn: 'foo'. txn := omni newTransaction. OmniBase getCurrentAndSet: txn on: Processor activeProcess. (txn root at: 'users') first securityRoles add: SecurityRole new. txn commit
Notice the lack of #markDirty calls in there. Without OmniBaseTracker you'd have to make that #securityRoles dirty.
By Mark Roberts on December 2, 2005, 9:12:44 pm