Thursday, August 7, 2008

Getting Fully Qualified (attributes, that is)

There's a lot of good examples out there on using GPath to read XML, but I couldn't find anything on a specific use case I had. While it's simple to access namespace-qualified elements, I was bereft of an example showing how to access a namespace-qualified attribute. Is this a black art, or is my Google-Fu weak? Hopefully neither. In any case, I figured out a way to it, and it's dirt simple.

Just use the Node.attribute() method, and pass it the QName of the attribute. You'll just need to define a namespace, like:

def atom = new Namespace("http://www.w3.org/2005/Atom")
def rdf = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf")


And then you're ready to go. For example, you have a document with a title node with an RDF "about" attribute. title[@about] won't get it, because the attribute is behind the namespace. But this will:


def parser = new XmlParser(false, true) def feed = parser.parse(feedDoc)
def about = feed.title.attribute(rdf.about)


The nice thing about this is it works the same way everywhere, e.g.,
def ed = root[foaf.Person].find {
it.attribute(rdf.about) == "$edRef"
}[foaf.name].text()


And so on. Have fun!

Thursday, May 1, 2008

Password validation in Grails on user domain class

If using Grails to create a web site there are many tricks to be learned. This one concerns password validation. In any sane website you ask a user twice for their password. That way you can compare the two to make sure the user entered the password correctly. In Grails domain classes use a nice little DSL for validation. You will probably want to leverage this when validating a user's password. Here is an arbitrary user domain class:


class User {

String userId

String password

String password2

String email

static constraints = {
password(blank: false, nullable: false, size:5..20, validator: {password, obj ->
def password2 = obj.properties['password2']
if(password2 == null) return true // skip matching password validation (only important when setting/resetting pass)
password2 == password ? true : ['invalid.matchingpasswords']
})
}

static transients = ['password2']
}


Notice password2 property is a 'transient' property. This means it will not be included in the database model or object relational mapping of GORM. The other trick here is the custom validator closure in the constraints for the password field. The way this validator works is if password2 property is not null compare it with password, if they do not equal return the error code 'invalid.matchingpasswords'.

In this case you could add the error code user.password.invalid.matchingpasswords in the messages.properties file in 'grails-app/i18n' folder of your project. Do this like normal Java properties:

user.password.invalid.matchingpasswords=uh oh the passwords you entered do not match

Now in cases where password2 is not being used it will be null. This will prevent the validator from doing the test of password vs. password2. This is important if you have forms which update the other fields on your user class while not updating the password field. With out this check for null you would have many troubles saving user instances due to this validation. Note this trick it could be useful to you many times over!

To finish this little exercise off check out this little bit of controller code:


class UsersController {

def create = {
// maybe pass some models into template?
}

def save = {
def user = new User(params) // password, password2 set from form?
if(user.save())
{
flash.message = "user '${user.userId}' added"
redirect(action:create)
}
else
{
flash.message = "error(s) creating user"
render(view:"create",model:[user:user])
}
}
}


When creating the new User object we pass params to the constructor. This will cause the form parameters to bind to the User object's properties. See the data binding section of the Grails reference documentation. If password2 was a form field then it is auto magically set on the new User object. When we call save a few lines later this value will be compared with the 'password' property, voila!

Wednesday, October 31, 2007

DOMCatagory

If you do any XML processing then I suggest you try DOMCategory in Groovy. A 'category' itself is feature of the Groovy language, borrowed from the objective C language. The short of it is you can use 'category' classes to wrap a given piece of your code. The objects in the wrapped code then gain new abilities! So what about DOMCatetgory (DOMcat)? This category allows you to work with DOM objects using a simple syntax. So an example would help. Let me first show a simple XML document then I will give a short script that can parse some values from the document.

Here is a real piece of XML I have dealt with. You can see its complexity is more than basic. It contains the namespace 'soap' which maps to http://www.w3.org/2003/05/soap-envelope, and also there are namespaces with values of urn:zimbraAdmin and urn:zimbra. For sake of ease lets say this file is named "zimbra.xml" and is found at the root ('/') of the file system.


<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<sessionId id="467" type="admin">467</sessionId>
<change token="8"/>
</context>
</soap:Header>
<soap:Body>
<GetAllDistributionListsResponse xmlns="urn:zimbraAdmin">
<dl id="b5d362c5-ef95-4fce-a5bc-1f7b06ece7f6" name="testing2@west.ora.com">
<a n="uid">testing2</a>
<a n="mail">testing2@west.ora.com</a>
<a n="zimbraMailStatus">enabled</a>
<a n="cn">testing2</a>
<a n="description">Testing DL for SOAP</a>
<a n="zimbraId">b5d362c5-ef95-4fce-a5bc-1f7b06ece7f6</a>
<a n="objectClass">zimbraDistributionList</a>
<a n="objectClass">zimbraMailRecipient</a>
<a n="displayName">testing2</a>
<a n="zimbraMailAlias">testing2@west.ora.com</a>
</dl>
<dl id="45c9cd14-811f-426b-888f-42ec05f3d7cc" name="testing3@west.ora.com">
<a n="uid">testing3</a>
<a n="mail">testing3@west.ora.com</a>
<a n="zimbraMailStatus">enabled</a>
<a n="cn">testing3</a>
<a n="description">for testing Zimbra SOAP services</a>
<a n="zimbraId">45c9cd14-811f-426b-888f-42ec05f3d7cc</a>
<a n="objectClass">zimbraDistributionList</a>
<a n="objectClass">zimbraMailRecipient</a>
<a n="displayName">testing3</a>
<a n="zimbraMailAlias">testing3@west.ora.com</a>
</dl>
<dl id="ddcec243-29fd-4aea-b443-912c69b30544" name="testing@west.ora.com">
<a n="uid">testing</a>
<a n="mail">testing@west.ora.com</a>
<a n="zimbraMailStatus">enabled</a>
<a n="cn">Testing</a>
<a n="description">Testing DL via SOAP</a>
<a n="zimbraId">ddcec243-29fd-4aea-b443-912c69b30544</a>
<a n="objectClass">zimbraDistributionList</a>
<a n="objectClass">zimbraMailRecipient</a>
<a n="displayName">Testing</a>
<a n="zimbraMailAlias">testing@west.ora.com</a>
</dl>
</GetAllDistributionListsResponse>
</soap:Body>
</soap:Envelope>

Now lets examine parsing this document from disk and examining some of its data. Here is a code snippit to create a DOM object, which we will use later with a DOMCategory.


def reader = new FileReader(new File("/zimbra.xml"))
def doc = DOMBuilder.parse(reader)
def zimbradom = doc.documentElement

Now that we have a dom we can bust out the DOMCategory so that parsing is a snap!


use(groovy.xml.dom.DOMCategory)
{
soapdom.'soap:Body'[0].'GetAllDistributionListsResponse'[0].'dl'.each { node ->
println "I am ${node.'@name'}"
}
}

A simple example but there is a lot to explain here. First you can see that you use indexes to select a given node. In this case our XML document has only one 'soap:Body' node, and only one 'GetAllDistributionListsResponse' node. So we could acutally omit the [0] indexes:


use(groovy.xml.dom.DOMCategory)
{
soapdom.'soap:Body'.'GetAllDistributionListsResponse'.'dl'.each { node ->
println "I am ${node.'@name'}"
}
}

Notice how we select an attribute value on a given element. Simply prefix a '@' symbol before the name of the attribute. See also that the full qualified names are being used to select some elements. Since the document names the element 'soap:Body' it can be selected with that exact name. While the elements that fall in the 'urn:zimbra' and 'urn:zimbraAdmin' namespaces are not prefixed and therefore we do not use a prefix to select said elements (as seen in selecting 'GetAllDistributionListsResponse' and 'dl'). Keep this idea in mind when selecting qualified attributes too!

Tuesday, July 24, 2007

Samba + Groovy

If you have an application where you need to connect with a Samba server I suggest you use JCIFS. This is a nice library for Java that allows file interaction on a remote machine via Samba. The nice thing about this library is that it uses classes that function just like the file classes you normally use in Java. Here is a nice little groovy script JCIFS:


smbAuth = new NtlmPasswordAuthentication("bob.com", "joe", "smoe")

fullPath = "smb://bob.com/media$/blah.txt"

smbFile = new SmbFile(fullPath, smbAuth)

if(smbFile.exists()) {
    smbDate = new Date(smbFile.getLastModified())
    println "Date on SMB file: ${smbDate}"
}

The above example connects to the samba machine, gets the file we want, and then gets and prints the modified date on that file. You can use this library to write quick scripts to sync files from a non samba machine to another machine (Windows?).

Wednesday, June 27, 2007

Go Check Out this Loop Tutorial

In combing aboutGroovy I found this nice loop tutorial. I recommend you take a look.

I'm gonna write about Groovy!

Groovy is my choice for hacking something together quick. It has a nice little syntax that help you succinctly express what you want. No semi-colons and type definitions, no problem! Being able to leverage the Java APIs (the best around) with no hassle what-so-ever, pricless! I am writing articles here in hopes that others will pick up and use this fun little language. If nothing else it is a great tool to add to your arsenal.

I'll make sure that I add new things here often. I encourage readers to ask questions, hoping that I can answer them. This could lead me to understand better how groovy could fit into others personal worlds.