tags:

views:

68

answers:

2

I am trying to dynamically populate the static constraint ={} at run time. Is there a way to do this. Example code:

Normal statement:

static constraint = { lastName(blank:false, maxSize: 100) }

What I am trying to do:

static constraint = {

call to an XMLSlurper that returns a HashMap of lastName as a key and (blank: false, maxSize: 100) as a value. // This part works.

have the HashMap executed as if it where hard coded information to validate the fields. //This part does not work.

} I hope this explains my problem well enough.

A: 

This is possible, but not the way you are trying to do it. The constraints for a GORM class are loaded using GrailsHibernateDomainClass. When the class is loaded, the evaluateConstraints method and the static property constraints is evaluated. You can look at the evaluateConstraints method in GrailsDomainConfigurationUtil to see how they are evaluated.

If you want to add your own constraints from an alternative source, you will need to modify the domain class yourself. The best way to do it is in a plugin. Read up on the plugin documentation first, and your entry point is the doWithSpring method:

def doWithSpring { -> 
  application.getArtefacts(DomainClassArtefactHandler.TYPE).each { domainClass ->
    def myConstraints = getConstraintsFromXml() /* Create a Map<ConstrainedProperty> from your XML */
    domainClass.constrainedProperties.putAll myConstraints
  }
}
Eric Hauser
Eric, Thanks for the direction, I am working through this now. I have made a getConstraint() to extracts the XML file and puts it into a hashmap, but I still get errors:org.springframework.beans.factory.access.BootstrapException: Error executing bootstraps; nested exception is org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.UnsupportedOperationExceptionCan you provide any help. Thanks
Mark
A: 

Looking into the GrailsDomainConfigurationUtil, you can see that the constraints map is built from the domain class's static constraints property using the ConstrainedPropertyBuilder. You can of course populate the constraints map by calling the builder methods dynamically using the map slurped from the XML.

static constraints = {
  def fromXml = [lastName: [blank:false, maxSize: 100]]
  fromXml.each { property, constraints ->
    invokeMethod (property, constraints)
  }
}

This might be suitable if you only need the XML based constraints in a single domain class, otherwise a more general approach as suggested by Eric is probably better, allowing e.g. a naming scheme for the XML files and thus extrapolating the idea of convention over configuration.

hlg
HLG, Your version works if I only invokeMethod(property), however if I do invokeMetthod(property, constraints) i throws an error:Caused by: groovy.lang.MissingMethodException: No signature of method: com.retirement.Dependant.dateOfBirth() is applicable for argument types: (java.util.Collections$EmptyMap, java.lang.String) values: [[:], blank: false, maxSize: 10]Any idea how to drop the leading [:] Thanks, Mark
Mark
Try to build the constraints one by one: invokeMethod('dateOfBirth', [blank:false, maxSize: 10]) - should be the same as dateOfBirth(blank: false, maxSize: 10). If that works, try iteration. Make sure you really have a map of property names as keys and maps of constraints as values to iterate over. Doublecheck your XmlSlurper result, it looks as if that gives you [[:], "blank: false, maxSize: 10"] instead of [blank: false, maxSize: 10]
hlg