Archive

Archive for the ‘Testing’ Category

Validation differences between Grails 1.1 and 1.2

June 9th, 2010

…or My Penance For Ignoring Validation Errors…

We recently updated our app from Grails 1.1.1 to 1.2.2. (We wanted to move all the way to 1.3.1 but since we build with maven, we finally decided to wait until a new grails-maven plugin is released. See GRAILS-6327.) During the upgrade, we hit two particularly annoying issues related to persistence and setting up associations.

The first involved a belongsTo relation like this:

class AppUser {
    UserPrefs prefs = new UserPrefs()
}

class UserPrefs {
    static belongsTo = [user: AppUser]
}

This worked under Grails 1.1, but under Grails 1.2 the prefs object was not getting persisted when the user was saved. Other belongsTo relations, both one-to-many and one-to-one worked as expected. We finally discovered that using the short form of the relation notation did work:

static belongsTo = AppUser

This post provided a clue as to where the problem may be. The user property of the Prefs object is not automatically set because the relationship is one-to-one. (At least, it is not automatically set all the time. If we load an AppUser object with Hibernate, it appears that the user property is set in the UserPrefs object. Go figure.) Under Grails 1.1, having a null user was apparently fine. My guess (based on the second error we hit, below) is that any validation errors caused by the child object were not stopping the save of the parent object. Grails 1.2, on the other hand, does care about the child object validation, though I could never get it to report anything in the errors property of either the parent or child object.

In order to work around the issue, I loosened the constraints on UserPrefs a little:

class UserPrefs {
    static constraints = {
        user(nullable: true)
    }
    static belongsTo = [user: AppUser]
}

With this change, cascading persistence works. Given, it’s not an ideal solution, but it does let us have access to the user property if needed.

What made this extra confusing is that we have a similar relationship in another set of classes that worked without a problem. The only difference there is that the child class is not automatically created with a static initializer as is done in for the prefs property in AppUser. It is always explicitly set into the owning object. I’ve run out of time to pursue this one further, so I don’t have a final answer. Anyone else out there have more insight into this?

The second persistence issue related to this section of code in the update method of one of our controllers:

def update = {
    def hubMap = HubMap.get(params.id);
    hubMap.properties = params;
    if (hubMap.save()) {
        ...add success message to response...
    } else {
        ...add failure message to response...
    }
    ...
}

Again, the code worked fine under Grails 1.1.1, but the save call failed under 1.2.2. Unfortunately, there was a hole in both our unit and integration tests for this method, so we didn’t catch it until much later in the release cycle.

Was the JSON conversion in the controller’s get method that generated the original data for the browser different? Nope.
Had the behaviour of the properties meta-method changed? Nope.

The difference is in how Grails handles any existing validation errors on a domain object when you call save(). In our case, the JSON that was being sent to the controller (via a Prototype AJAX call) contained two properties that were references to other objects. The javascript object conversion in the browser was not setting these properties in a meaningful way for the AJAX call; they were both coming across with the string value [object Object]. Since these fields are never updated in this particular workflow, we had never checked what was happening to them. Grails obviously could not convert from the string values to the proper objects, it ignored the values and set two errors on the domain object to record them. However, we didn’t check for errors after the properties call. We went straight to the save call. Under Grails 1.1, deep within the saving sequence in a random class called AbstractDynamicPersistentMethod, you come across this bit of code:

doInvokeInternal(...) {
    ...
    Errors errors = new BeanPropertyBindingResult(target, target.getClass().getName());
    mc.setProperty(target, ERRORS_PROPERTY, errors);
    ...
}

Any existing errors are replaced with a fresh, clean BeanPropertyBindingResult object, wiping out the error information. We never spotted it because we never expected the properties with errors to change anyway. That hole has been closed in Grails 1.2:

doInvokeInternal(...) {
    ...
    Errors errors = setupErrorsProperty(target);
    ...
}

The new setupErrorsProperty call will copy out existing errors. We put in a few adjustments to not attempt to update those properties and all is well.

So there you have it. A couple of gotchas in the upgrade path for grails. Hope this saves some folks from banging their head against the wall.

Testing, frustration, grails , ,

Grails, Maven, packaging, and skipTests fun

April 22nd, 2010

The grails maven plugin honors the maven.test.skip option (which turns off compiling and executing tests), but not the skipTests option (which only turns off executing tests). This means that you cannot easily create a package with test classes in it without running all of the tests. I finally come up with a close work around:

mvn clean grails:exec install -Dcommand=test-app -Dargs="-unit DoesNotExist" -Dmaven.test.skip=true

By explicitly listing the test-app command but specifying a test that does not exist, I was able to get the unit tests to be compiled. Since I only needed some common testing files in my package, this works for me. If someone wanted to package both the unit and integration tests, I don’t think this would work. I filed a new issue in the Grails Jira to try to get a real resolution.

Testing, Uncategorized, frustration, grails, maven, unit test , , ,

Corrections to Grails Documentation

September 5th, 2009

Here are two quick tips for anyone working with Grails 1.1.1:

1) The User Guide has conflicting info about cascading persistence.   Section 5.2.1.2 says “The default cascading behaviour is to cascade saves and updates, but not deletes unless a belongsTo is also specified.” Section 5.3.3 says, “If you do not define belongsTo then no cascades will happen and you will have to manually save each object.”

The former, 5.2.1.2, is correct. Create and Update actions are cascaded for one-to-many relations. However, hey are not cascaded for one-to-one relations.

2) Section 9.1 (Unit Testing) demonstrates how to pass in a list to the mockDomain(clazz, instanceList) call.  It then says that you can check that list to verify that persistence actions behaved as expected.  This is no longer correct.  The list is copied inside the mockDomain call.  To get access to the list of persisted objects for a class, use the MockUtils.TEST_INSTANCES map with the class name as the key.  For example:

def testInstances = []
mockDomain(Item, testInstances)
def i = new Item(name:"foo").save()
assertEquals 0, testInstances.size()
testInstances = MockUtils.TEST_INSTANCES[Item]
assertEquals 1, testInstances.size()

And in case you try the same thing as me, the mocking behavior does not support cascades.

Testing, frustration, grails , , ,