Posts tagged with “groovy”
Gldapo Validation
I am about to commit the new GORM inspired validation mechanism to Gldapo. Here is what it is going to look like…
Declaring your constraints
Instead of a DSL like GORM, we are using annotations…
import gldapo.schema.annotations. class Person { @GldapoNamingAttribute String uid @Required String sn @Required @Matches(/[A-Z]./) String givenName }
Plugging in your own constraints
You can register your own constraints quite easily. There are two parts, the constraint annotation and the validator.
The constraint annotation (has to be in Java since you can't define annotations in Groovy 1.5.x)…
import java.lang.annotation.*; import gldapo.schema.annotation.Validator; import gldapo.schema.attribute.validator.EqualsValidator; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Validator(EqualsValidator) // <-- define what can validate this type of constraint public @interface Equals { Object value(); }
As you can see it's a stock standard annotation, that is itself annotated with @Validator to tell Gldapo how to validate this type of constraint.
The validator looks like this…
package gldapo.schema.attribute.validator class EqualsValidator extends AbstractFieldValidator { def validate(obj) { if (obj != this.constraint.value()) { return ['notequals', "notequals.${this.constraint.value()}"] } } }
Validators have to extend gldapo.schema.attribute.validator.AbstractFieldValidator and implement validate(obj). This method takes the value to validate and returns either a single error code, or a list of error codes. If the value is valid it should return null.
Gldapo will register several error codes if validation fails. If a class called Person has it's name field annotated with @Equals('Luke') and it fails validation, the following error codes will be registered…
notequals
notequals.Luke
person.notequals
person.notequals.Luke
person.name.notequals
person.name.notequals.Luke
If the usage of error codes seem a bit weird here, then you should check out 7.4 Validation and Internationalization in the Grails user guide as the concept is exactly the same.
Finally, you need to register your constraint with Gldapo. You do this by listing your custom constraint types as a list under the contraintTypes key in the config…
Gldapo.initialize( contraintTypes: [Equals] )
Performing validation
This side of things works exactly like GORM…
def p = new Person(uid: "ld", givenName: "Luke" sn: "Daley") if (!p.save()) { p.errors.allErrors.each { println it } }
There is also the validate() method if you just want to perform validation without trying to write the object back.
If you haven't used validation in GORM, check out this chapter in the user guide, because it will all hold true (except how constraints are defined) with Gldapo.
11:52 AM | 0 Comments | Tags: gldapo, groovy, grailsGldapo 0.7.1 Released
This release has only one change which fixes an issue with password attributes.
11:52 AM | 0 Comments | Tags: gldapo, groovyGldapo 0.7 Released
Gldapo 0.7 (and a corresponding grails plugin) is now available.
This release primarily fixes some bugs with password attributes and brings the following major features/improvements:
- The addition of an LDAP filter DSL (thanks to Siegfried Puchbauer)
- Drastic improvement to the API for creating and moving objects.
- JavaDoc for commonly used classes (thanks to new GMaven features)
Release Notes
Sub-task
- [GLDP-66] - Base the location of entries in the directory on a ‘parent’ directiory rather than the ‘rdn’ attribute
- [GLDP-69] - Make defining a naming attribute mandatory (i.e. throw exception if none defined)
- [GLDP-70] - Add documentation for @GldapoNamingAttribute
- [GLDP-79] - Raise exception if rdn is set with a different naming attribute
- [GLDP-82] - Raise exception if naming attribute is changed directly (i.e. not via move() or replace())
- [GLDP-86] - Create ‘GldapoEntry’ abstract base class and document
Bug
- [GLDP-76] - Converting raw array values to native (groovy) values with schema-custom mapper raises GldapoTypeMappingException
- [GLDP-77] - Reading an entry with a password attribute raises exceptions
- [GLDP-81] - Static properties on schemas are not ignored
- [GLDP-91] - GldapoSynonymFor breaks GldapoNamingAttribute
Improvement
- [GLDP-47] - When moving/replacing an object, the in memory value of the naming attribute should be updated to reflect the change
- [GLDP-58] - Fix JavaDoc generation and use that as the definitive documentation source
- [GLDP-60] - Sanitise API for replacing/moving objects
- [GLDP-72] - Consolidate overloaded rdn setter on schema objects
- [GLDP-73] - Fetch raw values from contexts as objects, not strings
- [GLDP-74] - Implement tests for schema-custom TO FIELD type mappers
- [GLDP-75] - Implement tests for schema-custom TO TYPE type mappers
- [GLDP-87] - Rename ‘rdn’ property to ‘brdn’
New Feature
- [GLDP-41] - Provide way to name object based on particular attribute
- [GLDP-68] - Add a Filter DSL to ease LDAP querying
- [GLDP-71] - Support password type attributes
- [GLDP-78] - Add ‘namingValue’ property to entries
- [GLDP-83] - Add move(String,Object) method to move an object by naming value and parent
- [GLDP-84] - Add replace(String,Object) method to replace an object by naming value and parent
- [GLDP-85] - Add replace() method
- [GLDP-89] - Provide find() and findAll() variants that take a filter builder closure
- [GLDP-90] - Typemapping for Boolean type
Enjoy.
03:29 PM | 0 Comments | Tags: gldapo, groovyThe warm blanket of test coverage
A recent email identified that Gldapo struggles to work with password type attributes. I suspected this was going to be the case, but had pushed it aside in the hope that no one would hit the problem until I had time to look at it. Passwords are a bit of a funny case as they aren't really read/write, but there are cases when you do want to read the encrypted password hash.
It turns out that the problem was that I was reading raw context attributes as strings, when I should have been reading them as objects. Passwords seem to be stored as an array of bytes which can't be cast to a string. The fix was not that difficult, but it's fairly low down the stack. Any change that far down could easily have unexpected repercussions.
It pays to have tests
This isn't a new idea by any stretch. But a couple of times I have wondered if I am going a little overboard with the tests for Gldapo. I don't know what my actual coverage percentage is (there is no real solution for Groovy projects built by Maven for coverage at this time) but I suspect/hope that its > 85%. I try to be vigilant about tests for any new feature or change. As an aside, Gldapo development has been a great tool for learning how to test (and coincidentally how much easier testing is with dynamic languages).
The end result
Because of the good test coverage, I was able to make this change and verify that it did not break the public API. I did have to rejig some tests that tested internal API though. This is good news! I know at least this bug fix won't break any Gldapo 0.6 applications when they upgrade to 0.7.
08:06 AM | 0 Comments | Tags: gldapo, groovy, mavenGldapo (0.6) now hosted @ Codehaus
Codehaus were kind enough to approve my request to have Gldapo hosted there. I have now released 0.6 which lives at new home of http://gldapo.codehaus.org.
This gives me some great stuff I sorely needed. Like an issue tracker and a CI and distribution in the central maven repo.
Now it feels like a real project.
03:39 AM | 0 Comments | Tags: gldapo, groovy