Skip to content
geoffreywiseman edited this page Dec 10, 2014 · 24 revisions

Moo v2.0 started from a few external user requests and snowballed into a major release with multiple modules and significant internal refactorings.

Although the issue list for the release contains more information, the features of v2.0 are summarized below.

Features

Multiple Modules

Moo v1.0 used an expression library, MVEL, to enable translation expressions that could reach within nested objects or call out to static classes. While MVEL is a solid choice for an expression language, coupling Moo so directly to it had some problems.

For instance, Moo used MVEL for all source property retrieval, which meant that source properties could not be retrieved from private fields, which resulted in a feature request.

I also encountered a few frustrations with MVEL that made me wish the relationship to MVEL were a bit more arm's length. I wrote up some of my concerns in a blog post, if you want to read more about it.

Ultimately, I decided that I did want to continue to use Moo, but that I wanted flexibility for myself and for other people who were using Moo who didn't need MVEL or who wanted the option of using when it added value and not using it when it wasn't needed.

In order to do this, I had to convert Moo to a multi-module project with two modules, moo-core and moo-mvel. If you're upgrading from a previous version of Moo, you'll probably want to look at the Upgrading notes below to see how to make the transition as smoothly as possible.

While extracting Moo from the core module, I took the opportunity to upgrade the version to MVEL 2.0.19 and to do some work around precompiling and retaining the MVEL expressions.

(see #14, #83, #9, Extensions)

Source Properties

Source property values are now retrieved using explicit SourceProperty classes, which are created by SourcePropertyFactory classes. This is more explicit and helped enable the MVEL refactoring. There may be other SourcePropertyFactory instances in the future, but for now most of you probably won't need to interact directly with these.

Item Source Expressions

It is now possible to translate a collection by extracting part of each item. For instance, you might collapse a more complicated object to its name during translation:

@CollectionProperty(itemSource="name")
Set<String> roles;

(see #82)

Map Translation

When I built Moo v1.0, I didn't have any instances of needing to translate a Map, and it required more work, so I deferred it. With Moo v2.x, I still didn't have a strong need for Map translation, but it was starting to feel like more of a glaring omission, and I decided to add it to the feature set anyhow.

Map translation requires the new @MapProperty annotation, and can be configured to translate the key or value to a specified type or use a specified source expression.

(see Translating Map Properties, #37)

Translating Objects to Strings

You can now translate objects to instances of String using the built-in toString() implementation. This is perhaps the first value type translation.

(see Translating to Value Types, #90).

Translation Target Factories

When Moo translates an object, collection or map property, it constructs an instance of the target type, target collection type or target map type, then populates the object's properties, collection's items, or map's keys and values.

This works well for the common case, but if the target type is an interface, or the root of a class hierarchy where the desired target type might be one of the subclasses in the hierarchy, Moo might not be doing what you want it to. With Moo v2.0, you can customize this behaviour by replacing the default TranslationTargetFactory used to construct the object, collection or map.

(see Translation Target Factories, #75)

Cross-Collection Translation

Prior to Moo v2.0, when translating a collection, if the destination collection wasn't the same type as the source, Moo wouldn't know what to do. In v2, Moo can translate from a source Set to a destination List or vice versa. There's no additional configuration for this but it can make some simple cases easier and addresses a specific concern raised by a friend who tried to employ Moo on a project.

(see #33)

Translator and Annotation Caching

Moo now caches instances of Translator for the target class and annotations within properties to streamline performance and memory usage on large translation graphs.

(see #7, #10)

toString() for Debugging

Whenever I needed to debug Moo, having no real toString() implementation for FieldProperty and MethodProperty was mildly annoying, so I fixed that. That might come in handy for some of you as well.

(see #79)

Extracted TranslatorFactory from Configuration

In Moo v1.x, the Configuration class was responsible for creating translators. It wasn't so much that this was the right place for this functionality, it was just where it started and as it took shape, I didn't extract it to something more purpose-built.

As I wrote in my notes to document this for the release, "They didn't belong there, the just grew up there, and needed to move out on their own."

Unless you're customizing Moo, this isn't likely to affect you.

(see 7d2d52...)

Upgrading

Upgrading from one version of Moo to another is usually not a great deal of work, but there are, at times, changes that you should be aware of or even backwardly-incompatible changes that could pose problems.

MVEL Properties

Prior to Moo v2, if you were using Moo, you were using MVEL implicitly. In Moo v2, that becomes a more explicit choice, which is mostly a good thing, but it does mean that when you're upgrading, you'll need to decide if MVEL is important to you.

If you're not sure, I'd suggest starting with Moo Core, and only upgrading to MVEL if you're sure that you need it. If you know that you want to use the MVEL extension to Moo, or you'd like to give it a try, then use the moo-mvel artifact instead.

You can read more about moo-mvel on the Extensions page, and more about Getting Moo.

itemTranslation to itemClass

Prior to Moo v2, itemTranslation was used as the @Translation attribute used to refer to the class that should be used for the item.

During the Moo v2 development process, this was changed to itemClass, which is perhaps slightly more clear, and itemTranslation was repurposed for the translation expression. However, the translation expression was later changed to itemSource to be consistent with other uses of source expressions.

Having said that, I still prefer the new itemClass name for the attribute, so I’m sticking with it, taking the v2.0 line as an opportunity to introduce some backwardly-incompatible changes, which I hope won’t cause too much pain for those of you already using Moo.

Of course, this means that if you were using the itemTranslation attribute, you need to change that to itemClass when you upgrade to Moo v2.0.

(see #82)

Translation to Source

During the extensive changes for Moo v2.0, I took the time to make handling of sources more explicit and complete. In the process, I changed several ‘translation’ expressions to ‘source’ expressions, which match the ‘source properties’ that underly them.

This has resulted in some change to annotations as well as error messages and internals, such as:

  • translation attribute on @Property changed to source.
  • translation attribute on @CollectionProperty changed to source.

This is consistent with new annotations and classes as well:

  • @MapProperty has source, keySource, valueSource
  • the new SourcePropertyFactory interface

Property Translation Order

Most of you have probably not needed to care what the ordering of property translation is in Moo. Prior to v2.0, this order was undefined. In Moo v2.0, the order cannot be controlled, but it is partially defined, which should solve a class of potential and subtle problems.

(see Order of Property Translation)

Clone this wiki locally