Apache Cayenne 4.1: Java 8, no Dependencies, Smaller Memory Footprint

Andrus Adamchik
4 min readOct 14, 2017

--

Apache Cayenne project just published the first milestone release of Cayenne 4.1. Before that the community had worked for many months on stabilizing the previous version 4.0, which is now in beta. So this release was exciting for everybody involved in that we could run free again with experimentation and new features. And that’s what we did.

Below are release highlights…

4.1 Requires Java 8

Nuff said.

Cayenne Core is Dependency-Free

Ok, except for slf4j-api. To be a good Java citizen we still need the logging bridge, but none of the other dependencies. From what I know “dependency-free” is kinda unique in the Java ORM world. In case of Cayenne this means velocity, commons-langand commons-collections will no longer pollute your classpath and increase the size of your app. Wasn’t too hard to get rid of commons, but Velocity was used for template parsing, that is at the heart of Cayenne SQLTemplate functionality (for those who don’t know what this is, SQLTemplate allows to run manually created scriptable SQL within the ORM). To make it work we had to write a simplified (and also much faster) parser for the parts of the Velocity syntax essential for Cayenne. So most SQLTemplate queries in your code will keep working unchanged. If something does not (such as #chain / #chunk Cayenne directive), you have a backwards compatibility option (just addcayenne-velocity module to the app), or you can think of rewriting and simplifying your raw SQL queries. More details are available here.

Field-Based Data Objects

This has to be everyone’s favorite. But let me explain the background a bit first. If you are an existing Cayenne user, you may or may not realize that each persistent object stores its values in a map. This makes the object fully dynamic, which is good. But also requires more memory and is harder to debug. So 4.1 switching to field-based DataObjects is HUGE for the app performance. The new objects are much faster to read and write and significantly reduce the overall app memory footprint and the corresponding GC pauses. And talking of debugging, there’s no class-enhancement or bytecode manipulation tricks involved. Just pure code generation.

Some performance numbers from a very active cache-heavy app:

  • Memory use: 49% improvement.
  • Time spent in GC (per jstat tool): 43% improvement.
  • Throughput: 27% improvement (and climbing as the load rises).

The new objects are mostly backwards-compatible with our “classic” map-based objects from the application standpoint. The main source of incompatibility is support for “dynamic” properties (i.e. persistent properties not known at compile time). Such properties are a signature feature of Cayenne. Some common use cases are relationships to entities in other Cayenne models, fully “generic” objects, etc. So let’s compare the “flavors” of 4.1 DataObjects in respect to performance and dynamic properties support:

  • Field-based DataObjects that are subclasses of BaseDataObjectand are generated via new class templates. This is the default in 4.1 that provides all the non-trivial performance benefits above, but does not allow dynamic properties.
  • “Classic” map-based DataObjects that inherit from CayenneDataObject. This keeps things at the 4.0 performance level, but is fully backwards-compatible. To use this flavor you will need to explicitly use the old cgen templates and set org.apache.cayenne.CayenneDataObjectas a superclass for all entities. Though in fact you would rarely do this, because we support a hybrid approach that we’ll talk about next.
  • So what if you want both dynamic properties and and the 4.1 performance boost. For such cases there is a HybridDataObject superclass used with the new field-based template. As the name implies, HybridDataObject uses fields for the properties known upfront, and would lazily create a map for “dynamic” properties.

Extensible Project XML Structure

Last but not least, Cayenne mapping project structure was modularized, allowing embedding of extensions with their own XML schemas. While this doesn’t sound very exciting by itself, this will open the door to integrate various things in the base project. E.g. M1 already supports comments for entities, attributes and relationships:

This is a feature that our users have been asking for during the last 10 years. And we couldn’t do it properly until now. So you know, one small step for man … :) Future milestones will have extensions for cdbimport and cgen, making OR modeling workflow experience so much smoother (we already have GUI prototypes for some of this, so I am speaking with confidence here).

That’s all for the 4.1 overview. Don’t forget to check the upgrade notes if you are switching from 4.0, and of course the download link is here.

Follow me on Twitter.

--

--

Andrus Adamchik

ObjectStyle ; Open Source: ApacheCayenne, Agrest, Bootique, and more…