Skip to content
Print

ActiveObjects 0.8 Released

22
Mar
2008

Happy Easter everyone, we’ve got a new release!  ActiveObjects 0.8 is simmering at low heat (and footprint) on the servers even as I type.  This is probably the most significant milestone we’ve released thus far in that the 1.0 stream is now basically feature-complete.  I won’t be adding any new features to this release, just polishing and testing the heck out of the old ones.  We’ve already got a suite of 91 tests and I’ve got lots of ideas for more.  Expect this framework to get very, very stable in the next few months.

Features

Despite an annoyingly cramped schedule in the last couple months, I have managed to implement a few long-requested features.  The big ticket item for this release is pluggable cache implementations.  For those of you not “in the know”, ActiveObjects has a multi-tiered cache system composed of several layers and delegates.  This isn’t entirely unusual for an ORM, which is why I hadn’t mentioned it before.  The three basic layers:

  • Entity Cache – A SoftReference map from id/type pairs to actual entity values.  This means that if you run a query which returns an entity for people {id=1} and then run a second query which returns an entity for the same row, the two instances will be identical.  This is what enables the additional cache layers to function properly (and it saves on memory).
  • Value Cache – This is where all the field values for a given row are stored.  This will store both field values from the database as well as entity values (corresponding to foreign key fields).  Each entity has a separate instance of this cache.  Most of the memory required by ActiveObjects is taken up here.  With a long-running application, quite a bit of the database can actually get paged into memory.  This is a really good thing, since it drastically reduces round-trips to the database.  Thanks to the SoftReference(s) in the entity cache, running out of memory due to stale cache entries isn’t a problem.
  • Relations Cache – This is probably the most complex of all of the cache layers.  This cache literally caches any one-to-one, one-to-many or many-to-many result sets and spits them out on demand.  This reduces round-trips still more to the point where certain applications can be running completely from memory, even querying on complex relations.  This in and of itself isn’t that complex; the hard part is knowing when to expire specific cache entries.  This cache layer is essentially three different indexes to the same data, allowing cache expiry for a number of different circumstances.  Naturally, these structures don’t represent well as a single map of key / value pairs.  (more on this in a bit)

As of the 0.8 release, the value cache and relations cache layers have been unified under a single controller.  They’re still separate caches, but this unification allows for something I’ve been wanting to implement since 0.2: Memcached support.

High-volume applications often run into the problem of limited memory across the various server nodes.  Solutions like Terracotta can help tremendously, but unfortunately this doesn’t solve everything.  One answer is to provide every node in the cluster with a shared, distributed, in-memory map of key / value pairs.  This allows the application to page data into cluster memory and retrieve it extremely quickly.  Memcached is effectively this.  Naturally, it would be very useful if an ORM could automatically make use of just such a distributed memory cache and thus share cached rows between nodes.  Hibernate has had this for a long time, and now ActiveObjects does as well.

By making use of the MemcachedCache class in the activeobjects-memcached module (separate from the main distribution), it is possible to point ActiveObjects at an existing Memcached cluster and cause it to store the value cache there, rather than in local memory.  Once the relevant call has been made to EntityManager (setting up the cache), all cached rows will be stored in Memcached and shared between every instance of ActiveObjects running in your cluster.

Caveats

Of course, nothing is perfect.  For the moment, the major issues is that the relations cache doesn’t work properly against Memcached.  I had originally planned to just release it running against the local RAM, but this causes issue with proper cache expiry.  As such, the relations cache is disabled when running ActiveObjects against Memcached.  This doesn’t really impair functionality other than forcing ActiveObjects to hit the database every time a relationship is queried.  Since this is what most ORMs do anyway, it’s not too horrible.

I plan to have this issue resolved in time for the 0.9 release.  The biggest problem is figuring out how to flatten the multi-index structure into a single map.  Once I can do that, rewriting things for Memcached should be a snap.  (btw, if anyone wants to help out with patches in this area, you’re more than welcome!)

Databases Galore

One of the major focuses of this release was testing on different platforms.  This process uncovered an embarrassing number of bugs and glitches in some of the supposedly “supported” databases.  With the exception of Oracle, every bug I’ve been able to identify has been fixed.  So if you’ve tried ActiveObjects in the past and run into problems on non-MySQL platforms, now would be the time to give it another shot!

Speaking of Oracle, we’ve made some tremendous progress toward full support of this ornery database.  To be fair, I’m not the one responsible.  One of our community members has been tirelessly submitting patches and running tests.  We didn’t have time to get things fully sorted for this release (so don’t try AO 0.8 with Oracle unless you’re willing to risk server meltdown), but you can expect dramatic improvements in 0.9.  Once these fixes are in place, we should be able to safely claim that we support most of the database market (in terms of product adoption).

Final Thoughts

This really is an amazing release, well worth the download.  Most of the core API has remained the same, so things should be basically plug-n-play for existing applications.  The user-facing API is now in freeze and (unless some serious bug arises) will experience no changes between now and 1.0.  If you’ve been considering trying ActiveObjects for your project, now would be an excellent time.  I can’t promise no bugs, but if you point out my idiocy, I’ll certainly work to fix it!

Oh, as an aside, ActiveObjects is now in a Maven2 repository.  (thanks to some POM reworking by Nathan Hamblen)  To make use of this somewhat dubious feature, add the java.net Maven2 repository to your POM and then insert the following dependency:

<dependency>
    <groupId>net.java.dev.activeobjects</groupId>
    <artifactId>activeobjects</artifactId>
    <version>0.8</version>
</dependency>

After that, the magic of Maven will take over.  Of course, you’ll need to add the dependency for the appropriate database driver and (optionally) connection pool.  Those dependencies are left as an exercise to the reader.  Note, activeobjects-memcached isn’t in Maven yet, but it will be for the 0.9 release (either that or integrated into the core, I haven’t decided yet).

I certainly hope you enjoy this latest release.  As always, feel free to drop by the users list if you have any questions or (more likely) uncover any problems.

Comments

  1. Very cool, nice work.

    Can I make one comment about naming, though? You should consider not calling your “Relations cache” that, but instead “Relationships cache.” The reason is that in the context of database theory “Relation” means something else than the way you are using it. It would be more like “Entity” cache. In the relational algebraic theory, a “relation” is roughly equivalent to what SQL databases call a “table.”

    Ryan Sunday, March 23, 2008 at 6:29 am
  2. Yeah, I’m aware of the algebraic meaning. To be honest, the reasoning behind the incorrect name is more laziness in typing than anything else. :-) “RelationsCache” has been a class internal to AO for a while now, I’m just now exposing some of the API. If a lot of people find the name confusing, I might be willing to change it for 0.9.

    Daniel Spiewak Sunday, March 23, 2008 at 10:57 am
  3. Looks really good.

    Any plans to support Sybase?

    David Lang Thursday, March 27, 2008 at 4:38 am
  4. Not for 1.0, but that may be something that goes into the 2.0 stream. I definitely want to add support for a few more databases.

    If Sybase support is something you need, it’s actually not that hard to write a custom DatabaseProvider for it. If you know you aren’t going to use migrations, you can actually omit like 95% of the provider implementation and strip it down to just a few lines. There’s no documentation on how exactly to go about this yet, but it is forthcoming. :-)

    Daniel Spiewak Thursday, March 27, 2008 at 7:33 am
  5. any discussion forums for activeobject? i dunno if i’m seeing a bug in this app or i’m just misusing it. i setup two entity classes, like the example, Person and Company. if i call the EntityManager migrate it deletes a table and replaces it with the other one. if in my implementation class i call manager.migrate(Person.class) it will delete the company table. if i call manager.migrate(Company.class) (from my other implementation class) it deletes the person table. running this against mysql. any thoughts?
    i specifically didn’t want to create the tables first in SQL to test this capability of ao.

    realgt Monday, April 7, 2008 at 4:48 pm
  6. You’re always welcome to send me an email directly, or (even better) email the users list (users@activeobjects.dev.java.net).

    To answer your question, ActiveObjects migrations literally sync the database schema with your entity structure. The *entire* database is made to sync, which means that if any tables are there which shouldn’t be, they are removed. It’s like making a commit into an SCM. The remote state is made to match your local state, including any files you may have deleted.

    There’s a feature scheduled for 2.0 which will allow configurability in this area, but for right now migrations are a true sync, regardless of what data may be lost.

    Daniel Spiewak Monday, April 7, 2008 at 6:24 pm
  7. hey thanks for the reply – that makes sense i guess, although it’d be easier to call EntityManager#migrate without a long list of classes and have it automatically migrate all classes which extend Entity. i guess i can’t see a use case where you don’t pass it a list of all your classes (which could get rather troublesome) …especially since it drops all unlisted class tables.

    in any case, i looked around and found AO to be the most developed ActiveRecords port to java, great job. looking forward to future releases.

    realgt Tuesday, April 8, 2008 at 6:15 pm
  8. :-) Glad you like it! If you have any suggestions, please don’t hesitate to send them my way.

    With regards to migrate, I wanted to do it so that it just migrated all of the entities in scope, but unfortunately Java doesn’t provide a way to do this reflectively. What I *can* do is migrate all dependent entities. So if you consider your schema as a directed graph, with paths defined by foreign key relationships, it is only necessary to add the unconnected “roots” of the graph and the rest will follow. So if Person has a getter which returns a Company, you can migrate Person and ActiveObjects will automatically traverse the dependencies and migrate Company as well. It’s not a perfect solution, but it does save listing *all* of the entities in the migration.

    Daniel Spiewak Tuesday, April 8, 2008 at 8:39 pm
  9. Is @Preload({“emitter”, “avg(processingTime) as processingTime” }) together with entityManager.find(AverageProcessingTimesByEmitter.class, Query.select().group(“emitter”)) the right way to do aggregations with AO? It works but I’m a bit unsure whether it’s supposed to work that way. Any thoughts, suggestions?

    Stephan Schwab Monday, July 7, 2008 at 6:05 pm
  10. I’m not sure what you mean by “aggregations”. Can you send me (or even better, the ActiveObjects users’s list) an email directly and explain in more detail?

    Daniel Spiewak Monday, July 14, 2008 at 10:43 am
  11. Is there somewhere a discussion-forum concerning activeobjects?

    Thomas Trocha Wednesday, July 16, 2008 at 6:58 am
  12. Technically, there is a forum on the java.net project page, but nobody really uses it. :-) I monitor it and certainly would not mind if it were used more, but currently the best place to discuss AO is on the users list (users [at] activeobjects.dev.java.net)

    Daniel Spiewak Wednesday, July 16, 2008 at 9:03 am
  13. Any update on the 0.9 or 1.0 release? And is Oracle “done” too? This looks very promising and appreciate all the hard work.

    Mark Wilhelm Tuesday, May 26, 2009 at 4:06 pm
  14. Awesome stuff, after years of Hibernate/EJB3 torture. :)
    Any chance the distribution can move off the infinitely godawfuly unreliable dev.java.net?
    Right now I can’t even download the release.
    Google Code, perhaps?

    Alex Zuzin Friday, October 9, 2009 at 4:53 pm
  15. Is there any way to auto-generate classes from a .SQL file? I have a big system, and I have all my DB generated and working. If I want to migrate to ActiveObjects, I will need something that generates the classes from a .SQL file, so I don’t have to write all manually.

    Francisco Valdez Monday, April 19, 2010 at 9:28 am

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*