Search code examples
javaoopgrailscommandextend

Grails command that extends another command bug


I'm having a problem with Commands in Grails when I extends one generic Command to reuse it's custom validator.

When I clean the grails project, it loses the reference to the extended custom validator. I need to cause a syntax error in CommandA with the project running and undo that error so it compiles back the command.

file: /src/groovy/app/commands/ImageCommand.groovy

class ImageCommand {
    static imageValidator = { value, command ->
        ... DO SOMETHING ...
    }
}

file: /src/groovy/app/commands/CommandA.groovy

class CommandA extends ImageCommand {
    def file
    static constraints = {
        file nullable: true, blank: true, validator: imageValidator
    }
}

To cause the error I just erase a part of the CommandA:

class CommandA extends ImageCommand {
    def file
    static constraints = {
        file nullable: true, blank: 
    }
}

And undo it to force recompile:

class CommandA extends ImageCommand {
    def file
    static constraints = {
        file nullable: true, blank: true, validator: imageValidator
    }
}

What should I do? I can't move my CommandA to the Controller file because I use it in many places.

*Using Grails 2.2.2


Solution

  • You can try to move your validator to separate class in src\groovy like this:

    class PhoneNumberConstraint extends AbstractConstraint {
        private static final String NAME = "phoneNumber";
        private static final String DEFAULT_MESSAGE_CODE = "default.phoneNumber.invalid.message";
    
        @Override
        protected void processValidate(Object target, Object propertyValue, Errors errors) {
            if (!isPhoneNumber(target, propertyValue)) {
                Object[] args = [constraintPropertyName, constraintOwningClass, propertyValue]
                rejectValue(target, errors, DEFAULT_MESSAGE_CODE, DEFAULT_MESSAGE_CODE, args);
            }
        }
    
        private boolean isPhoneNumber(Object target, Object propertyValue) {
            if(propertyValue instanceof String && ((String)propertyValue).isNumber() &&
                    (((String)propertyValue).length() == 13 || ((String)propertyValue).length() == 11)) {
                return true
            }
            return false
        }
    
    
        @Override
        boolean supports(Class type) {
            return type != null && String.class.isAssignableFrom(type)
        }
    
        @Override
        String getName() {
            return NAME
        }
    }
    

    Then register your validator in resources.groovy like this:

    beans = {
        ConstrainedProperty.registerNewConstraint(PhoneNumberConstraint.NAME, PhoneNumberConstraint.class);
    }
    

    It works for me flawlessly with commands.