With the imminent release of Terracotta 3.1 and it’s suite of integration modules, I thought it would be good to do a quick blog on a feature I put together during our last dev week: automatic module version selection in tc-configs.
Over the last couple years, we have been steadily moving more and more of the “product integration” code out of the Terracotta core and onto our forge. This is good for a bunch of reasons but perhaps the most important reason is that it lets those modules evolve and release independently and on a faster cycle. As of Terracotta 3.1, we’ve nearly completed that process.
One downside of the module setup is that we currently use pretty tight versioning between Terracotta Integration Modules (TIMs) and from TIMs on the core product. [That is itself another topic and something we’re continuing to work on but not the point of this post.] Module versions have historically showed up in the Terracotta configuration file with something like this (taken from the Examinator):
... <modules> <module name="tim-jetty-6.1" version="2.0.1-SNAPSHOT"/> <module name="tim-hibernate-entity-3.3" version="1.4.1-SNAPSHOT"/> <module name="tim-hibernate-cache-3.3" version="1.0.1-SNAPSHOT"/> <module name="tim-annotations" version="1.4.1-SNAPSHOT"/> <module name="tim-spring-security-2.0" version="1.2.1-SNAPSHOT"/> <module name="tim-async-processing" version="1.2.1-SNAPSHOT"/> <module name="tim-concurrent-collections" version="1.2.1-SNAPSHOT"/> <module name="tim-distributed-cache" version="1.2.1-SNAPSHOT"/> <module name="tim-spring-webflow-2.0" version="1.2.1-SNAPSHOT"/> </modules> ...
The name and version here are basically showing two of the three parts of a full module coordinate (basically the same as Maven coordinates). Here “name” acts like artifactId in Maven. The missing coordinate is the groupId (actually “group-id” attribute here in our schema) which defaults to “org.terracotta.modules”, which is correct for all of these modules.
The problem here is all those version numbers. When you first include one of these modules, you will typically get it by downloading it with the tim-get tool included in the Terracotta kit. The command will be something like:
[~/terracotta-3.1.0]$ tim-get.sh install tim-hibernate-cache-3.3 Terracotta 3.1.0, as of 20090816-190843 (Revision 13427 by cruise@su10mo5 from 3.1) Installing tim-hibernate-cache-3.3 1.0.0 and dependencies... INSTALLED: tim-hibernate-cache-3.3 1.0.0 - Ok INSTALLED: tim-hibernate-cache-provider-3.2 1.0.0 - Ok INSTALLED: tim-concurrent-collections 1.2.0 - Ok INSTALLED: tim-distributed-cache 1.2.0 - Ok INSTALLED: tim-hibernate-concurrency-3.3 1.0.0 - Ok INSTALLED: tim-hibernate-concurrency-common 1.0.0 - Ok
tim-get is a really nice tool for working with Terracotta modules. It resolves dependencies, knows where to install them in the kit, can tell you whether the modules you have are the latest version, search by keyword (find modules with “cache” in the name), install all modules mentioned in a tc-config file, etc etc.
When you do this initial module download (or a subsequent update), you’ll see the module version at the end of the line there and that’s the version that needs to go into tc-config.xml. That’s not too bad, but it’s one more thing to worry about. Perhaps the more striking problem is when you update from Terracotta X to Terracotta Y, there are typically new versions of all the TIMs and you must then go into the tc-config and modify all the module versions based on the current Terracotta version compatible modules. [Fixing the “all new versions” issue is the other side of this coin.]
This is the primary reason tc-config files are not automatically portable between Terracotta releases and is definitely a stumbling block for anyone maintaining or upgrading Terracotta. We see a significant amount of traffic on the Terracotta forums just dealing with these kinds of versioning problems. It’s a huge pain for us as well – our Maven deployment process has to update these if they are embedded in tests or between TIMs. Our docs have these versions sprinkled all over and they are constantly out of date. Etc etc.
After all that build-up, the new feature is kind of small. If you examine the actual available modules, you find that tim-get is already filtering the modules you see down to the ones appropriate to your Terracotta version. You typically then only have one or maybe a couple versions in your local module repository. It’s a simple thing to simply find the newest version from that set.
As of Terracotta 3.1, specifying module versions in your tc-config is now optional. All the other parts of your process remain the same – you still want to use tim-get to install and update your local set of modules and specify those modules in your tc-config. You just can skip worrying about the exact version number. When you update a module, you’ll automatically find the new version. The support for versioning is all still there of course, so existing tc-config files still work and if you need greater control over the version, that all works just the way it always has.
The example above becomes just:
... <modules> <module name="tim-jetty-6.1""/> <module name="tim-hibernate-entity-3.3"/> <module name="tim-hibernate-cache-3.3"/> <module name="tim-annotations"/> <module name="tim-spring-security-2.0"/> <module name="tim-async-processing"/> <module name="tim-concurrent-collections"/> <module name="tim-distributed-cache"/> <module name="tim-spring-webflow-2.0"/> </modules> ...
One place where this version issue still shows up is with Maven. If you are building and executing your project with Maven, those module versions also show up in your pom.xml file. You specify them there either because the TIM also has a compile-time API (like tim-distributed-cache, tim-concurrent-collections, tim-async, etc) OR because you just want Maven to ensure you have the right lib downloaded so it can be loaded as a TIM by Terracotta. In either case, you’ll still probably need to specify a specific version. It’s harder to get around this constraint. As we look more at loosening our versioning, you might be able to specify less of the version and let Maven find the newest instance through similar logic but we’re still experimenting with some of those things.