0

We have a class like this in a Grails 2.4.3 application (migrated from 2.3.8):

@Validateable
class Foo {
    Integer noDefault;
    Integer withDefault = 1;

    static constraints = {
        noDefault(nullable:false)
        withDefault(nullable:false)
    }
}

This class is being instantiated in a complex configuration mechanism using a Map like this:

[
    noDefault: 0,
    withDefault: 2
]

(In fact the Map is part of a huge one, but the class constructor sees this small one.) Formerly the class worked if we omitted the withDefault entry from the config map, using the default value which is not null. In Grails 2.4.3, however, it tells me that this field cannot be null. I can fix it by letting it be null in the constraint, but it lets setting the explicite value null (and overwrite the default value), which causes problem during operation.

Do you know some workaround, which preserves the semantics and correct operation?

Thanx in advance, best regards: Balázs

Bámer Balázs
  • 169
  • 1
  • 9
  • Are you sure that the `Map` you are binding really doesn't contain a value for `withDefault`? If it contains a value that is null that would explain the behavior you are seeing. If the `Map` really doesn't contain a value for `withDefault` then the behavior your are describing doesn't make sense to me. There must be some other factor which isn't expressed in the description. See the code I posted below and if you can narrow in on the specifics of a problematic scenario I will be happy to look into it. Best of luck. – Jeff Scott Brown Sep 19 '14 at 17:04
  • Random shot in the dark, but could the property name (`withDefault`) somehow be colliding with Groovy's `Map.withDefault()` method? – Andrew Sep 19 '14 at 17:13
  • Andrew, that seems unlikely to me. The scenario as described is one where there isn't any entry in the map for withDefault. Even if there was that should still work, but since withDefault isn't even in the map I don't know how that could be relevant. – Jeff Scott Brown Sep 19 '14 at 17:23

1 Answers1

0

What you are describing is not consistent with what I would expect and not consistent with the behavior I am seeing. The project at https://github.com/jeffbrown/validatedefaults contains the following code.

At https://github.com/jeffbrown/validatedefaults/blob/master/src/groovy/demo/Foo.groovy

// src/groovy/demo/Foo.groovy
package demo

import grails.validation.Validateable

@Validateable
class Foo {
    Integer noDefault;
    Integer withDefault = 1;

    static constraints = {
        noDefault(nullable:false)
        withDefault(nullable:false)
    }
}

The test at https://github.com/jeffbrown/validatedefaults/blob/master/test/unit/demo/FooSpec.groovy passes:

// test/unit/demo/FooSpec.groovy
package demo

import spock.lang.Specification
import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin

@TestMixin(GrailsUnitTestMixin)
class FooSpec extends Specification {

    void 'test validating default values'() {
        given:
        def map = [noDefault: 0]
        def foo = new Foo(map)

        expect:
        foo.validate()
    }
}

When I run the app I get the same behavior.

// grails-app/conf/BootStrap.groovy
import demo.Foo

class BootStrap {

    def init = { servletContext ->
        def map = [noDefault: 0]
        def foo = new Foo(map)

        // this prints true...
        println "Foo is valid? : ${foo.validate()}"
    }
    def destroy = {
    }
}

I hope that helps.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • Your example works, and the test passes by me. I have tried the real application once more, and this time it worked. The reason is mystic - I often see unexplainable errors occuring on my JVM, and they keep repeat themselves even for a day. No matter how I do grailsw clean, delete the workdir or restart the system. The JVM is broken, reinstalling it or a different version does not help, either. Sorry for the false question. – Bámer Balázs Sep 19 '14 at 19:21