The Groovy programming language is a JVM based scripting language. It is used by the Grails web framework and the Gradle build automation system.
Groovy has a language feature called Named argument constructors. This means that given a class with properties, for example
class Example { String text }
you can initialize the properties directly when calling the constructor:
def example = new Example(text: ' This is an example. ') assert example.text == ' This is an example. '
This is basically a shortcut for initializing the properties via explicit assignment:
def example = new Example() example.text = ' This is an example. ' assert example.text == ' This is an example. '
So far so good.
Enter Grails
We use the aforementioned Grails framework for some of our web application projects. It is advertised on its website as featuring “convention-over-configuration” and “sensible defaults”. Grails uses the Groovy programming language, and a simple domain class looks just like a plain old Groovy class, except that it lives under the grails-app/domain
directory (this is one of the convention-over-configuration aspects):
class Example { String text }
As expected, you can initialize the property via regular assignment:
def example = new Example() example.text = ' This is an example. ' assert example.text == ' This is an example. '
So one might expect that you can initialize it via a named argument constructor call as well:
def example = new Example(text: ' This is an example. ') assert example.text == ' This is an example. '
And indeed, you can. But what’s this? Our assertion fails:
assert example.text == ' This is an example. ' | | | false This is an example.
It is not directly obvious from the assertion failure output, but the property value is indeed no longer equal to the expected text: the leading and trailing spaces got trimmed!
I was surprised, but after some research in Grails documentation it turned out that it’s not a bug, but a feature. In the section on Data Binding, you can find the following sentence:
The mass property binding mechanism will by default automatically trim all Strings at binding time. To disable this behavior set the
grails.databinding.trimStrings
property to false ingrails-app/conf/application.groovy
.
Groovy’s named argument constructor feature is used as a data binding mechanism by Grails to bind web request parameters to a domain object. For this the default behavior was modified, so that strings are automatically trimmed. I can only guess that this is considered to be an instance of the “sensible defaults” mentioned on the Grails homepage.
To me personally this kind of surprising behavior is not a sensible default, and I think it goes against the Principle of least astonishement. I prefer consistency over “magic”.