Wednesday, October 27, 2010

GUG Poland emerged!

Hi folks!

I'd like to let you know that the grails community has one more place to find answers! This time it's a discussion group for polish speakers, GUG Poland.

Come join and let's bring the community the best help we can!

Grails - custom view engine

Hi there!

Following the last post I was wondering how hard it is to actually create your own artificial view engine for your custom file format. The reason for that might be for example that you want to create Excel files from data returned by an action (like a list of people for example).

I'll assume that the view engine will be completely artificial which means it will not use any resources other than the model being passed on from controller.

Here are the steps one needs to do to make it happen:

1. Register your format so that it is recognized by the system.
2. Implement the ViewResolver and register it as a bean in beans.groovy
3. Implement the actual View and it's "render" method.

Not going into the details here's an example that works. After you run it navigate to http://localhost:8080/example/home/index to see the HTML representation and then to http://localhost:8080/example/home/index.example to see the custom format being rendered instead of the GSP page.

Hope it helps someone :)

Grails and rendering different content types

Hi there Grails freaks!

I've discovered something ground breaking (well, at least for me) with the way Grails renders views so I thought I'll share it with the class :)

Imagine you have a controller, say a PersonController for example. And there you have the "get" action that returns just enough data to render the view. Well times are different than what they used to be 3-4 years before and HTML is not the one and only output format we expect these days. There's JSON, plain text, ATOM, RSS - you name it! Back to the original thought...

Knowing that the JSON format for example looks different than the HTML one (no surprise there) it's kind of obvious the way it's being rendered will need to be different. So for example an HTML view will have everything embedded into an <html> element, then there will be a <body> item containing whatever needs to be rendered whereas the JSON version will most probably contain only the key-value map in JavaScript format.

So what's so ground breaking here? We all know there's this "render person as JSON" thingy, right? Do we really need anything else?

As a matter of fact we do. There are lots of examples where JSON generated this way will not cut it. For example you need the actual data wrapped into some outer object, maybe some additional "count"-like field for list is something you need... You name it!

To get around this here's the revelation: you create not one but as many views as you need but add the extension to their names, for example for the "get" action of "person" controller you'd have get.gsp for the HTML view of the thing and a "get.js.gsp" view for the JSON representation!

Of course one always needs to remember to set the content type properly:

<%@ page contentType="text/javascript"%>

I have no idea if this works with any other version of Grails other than 1.3.5 (this is what I've tested) but this feature is so nice it will allow for effortless rendering of different types of results with no pollution in controller code.

Here is an example project that does what I've described. Once you've got it up and running navigate to http://localhost:8080/example/home/index and http://localhost:8080/example/home/index.js to see the results.

Have fun!

Sunday, October 24, 2010

Git adventures

Hi there folks!

I've been trying really hard (with success!) to get Git (the revision control system from Linus) to work the way I like it.

So the first thing I tried was to clone a remote repository from git hub. That was pretty easy. git clone URL and the repo was cloned. Piece of cake.

Next thing (since I like to mess around) was to create a repo from scratch. No surprise here - git init folder_name and I was done. Working with the new repo did show some surprises... First, the git add required me to specify something to work with. With Mercurial or Bazaar this was not the case so I was surprised to see an error message but I figured out it pretty quickly.

Next thing - commit.
Well, if you worked with Subversion, Mercurial and Bazaar you'd be pretty used to the "ci" abbreviation. Unfortunately it's not working in Git and you have to specify the whole command name... Same thing goes for "status".

Using TortoiseGit under Windows didn't bring much surprise - it was as I'd be using Subversion which means plain and simple.

Last but not least came the problem of sharing my work and creating a "central" (the most important) repository. Had I known this would be so f..ing difficult I'd not start with it at all...

First, there's a "git-daemon" thingy that should take care of the "server" part. Well, it does and exporting (making publicly available) a repository was not a nightmare. One needs to remember that a repo is not automatically available via this daemon but first after creating a tag file in .git subdirectory called "git-daemon-export-ok". That was not intuitive but I can live with it. Google did help.
My anger started when I wanted to push something to the newly cloned and modified repo. It turns out it's not that simple because the "git-daemon" thingy is supposed to be read-only!
After hours of fighting with stupid error messages that the connection was suddenly dropped... Very counterintuitive! But I thought it's not the end of the world and looked further.
I've finally stumbled upon a post describing that git is actually allows interoperability using SSH protocol. So I've cloned the repo using different url (username@host:/path), done the same changes again, checked them in and tried to push. Well... It didn't work either. The repo had to be marked as "bare" - whatever that means. If you've come across this term anywhere else please drop me a note - I have no fricken idea what it means.
So I've "marked" the repo as "bare" in the config file. And again I was not able to push any changes because the repo was empty (surprise! an empty repo cannot be served!!!). After doing some foobar changes to it and committing them on the server I was finally able to push my local changes.

It all sounds like a piece of cake once you know what to do, but attacking the problem head on for the first time is simply a pain in the ass to figure it out.

To summarize:
- you cannot server r/w repo using git protocol. You need to use SSH or other protocol that supports authentication.
- you have to have at least one checkin in the server version of the repository before you're able to push chages from remote clients.
- you need to create "git-daemon-export-ok" for the repo to be picked up by "git-daemon" or else!
- you need to set the "bare" config option to "true" or else!

I hope this will help someone. Have fun!

Tuesday, October 12, 2010

Grails, GORM, Teradata and no primary key

Hi,

I've stumbled upon a problem which is most probably a very common one though I couldn't find any clear answer right away... Mapping to so called natural keys with GORM.

Imagine you have a badly designed table without surrogate key acting as unique primary key. To map such a table in GORM you need to compose the ID of a mapped class using a composed key, that's obvious:
static mapping = {
id composite: [ 'reportId', 'managerId' ]
}

Since there's no restriction telling the database that the fields have to have values then if at least one of the fields contains null what you'll get in return is a null in a list where you'd expect your domain objects!!!

I have no idea if this is a bug but I surely believe that this is a design error in the database.

The fix for that (an ugly like hell one) is to add as much fields that always have values and remove those columns that can have nulls in them.

But I strongly recommend that you do add the surrogate, required (or better yet auto-populated) primary index.


Have fun!

Friday, October 8, 2010

Grails controllers and command objects

Hi there folks!

This is one of the days that come from time to time when one feels as if a lightning struck went down in extreme proximity :)

Well, I've been asked to implement a functionality, a very simple one. Take 2 parameters from the URL, verify if all of them are given, check if one is a valid identifier of an existing entry in the database and if so set a given property of that domain object to the value of the other parameter. Let's see how this might be done:
class CarController {
def index = { ... }

def setCarAvailability = {
def car = Car.get(params.id)
if (car && params.available) {
car.avaiable = params.available
car.save(flush: true)
redirect action: 'index'
} else {
flash.message = "Error: either no valid car id, available not given or saving failed"
redirect action: 'index'
}
}
}

Pretty easy, right?

Now somebody please tell me what's wrong with this picture?

At first, if this is a simple application with one or two controllers having one or two actions this seems completely acceptable, right? But what if there are 5 or 10 actions in 20 different controllers? The answer is simple: UNMAINTAINABLE RAVIOLI CODE!!!

To counteract this I've came across an idea of making command objects not just dumb value placeholders with validation capabilities but to actually implement the command as it should be (given its proud name).

So at the end of the day this is how I'd really code this:
class CarController {
def index = { ... }

def setCarAvailability = {
SetCarAvailabilityCommand command ->

if (command.validate()) {
command.execute()
redirect action: 'index'
} else {
flash.message =
command.errors.allErrors.collect { error ->
error -> error.field
}.join(", ")
redirect action: 'index'
}
}
}

class SetCarAvailabilityCommand {
Car car
Boolean available

static constraints = {
car nullable: false, validator: { it?.attached }
available blank: false, required: false
}

def execute() {
car.available = available
car.save(flush: true)
}
}
How about that, ha? Nice separation of concerns (actual entity that does the job separated from controller that should only care about controlling what should go next), automatic parameter validation, clean naming and if you put those two into the same file then even automatic reloading works!

The key here is that the parameter must be named "car.id" for this to work. This way the automatic binding will find the actual Car instance and put it into our command object automagically.
  <g:form action="setCarAvailability">
<g:textField name="car.id"/>
<g:checkBox name="available"/>
<br/><br/>
<g:submitButton name="action" />
</g:form>

You might have noticed the funny-looking validator for car field. This just checks that the Car instance came from the database. If one would be to specify an id that does not exists it'll fail.

Another neat thing is that all of the commands have similar interface so generally you can create a helper method that will get some parameters (where to redirect after failure for example) and have every single action be actually a one-liner! And remember: since this is a dynamic language with duck typing it does not have to be a java interface strictly speaking! Commands just have to talk and walk like commands :)

Oh, and if you'd like to delegate some code to service I rush to say that dependency injection works as expected with command objects so no worries :)

I would not be myself if a ready-to-use example would not be here :)

I wish you all some nice and well separated code!

Wednesday, October 6, 2010

Grails EasyB and Selenium

Hi there,

having EasyB in your grails project is handy. There's no question about it. However combining it with Selenium RC adds a whole new flavor to the mixture!

Let's examine a step-by-step scenario on how to include both grails-easyb and selenium-rc in a brand new application, then let's create a simple home controller with one action and let's test it using the potent mix of behaviors and remote test execution :)

Step 1: Create a new application

This one is extremely easy:
grails create-app example
Step 2: Install the grails-easyb plugin.

This one is extremely easy to:
grails install-plugin easyb
Step 3: Install selenium rc.

Well, there's 4 things to it.
a) download the Selenium RC package
b) extract the driver (selenium-java-client-driver.jar) into the lib folder of our example application
c) extract the Selenium RC server (the whole folder selenium-server-1.0.3)
d) run Selenium RC server
java -jar selenium-server.jar
Step 4: Create the home controller.

As you might have already guessed:
grails create-controller home
Step 5: Add some meat to the index action.

Let's change the default empty implementation of our index action into
[ message: "Hello, world!" ]
Step 6: Create a functional (yes! functional test at last!) in test/functional (this folder does not exist at first so you have to create it yourself). I'll call it MyFirstFunctional.story
import com.thoughtworks.selenium.*

before "start selenium", {
given "selenium is up and running", {
selenium = new DefaultSelenium(
"localhost", 4444, "*iexplore",
"http://localhost:8080/example/"
)
selenium.start()
}
}

scenario "Will show 'hello, world!' message", {
when "home/index opens", {
selenium.open("home/index")
}

then "the text 'Hello, world! appears on the page", {
selenium.isTextPresent("Hello, world!")
}
}

after "stop selenium", {
then "selenium should be shutdown", {
selenium.stop()
}
}
WARNING: you might naturally want to move the "after" section right below the "before" section. DON'T EVER DO THAT! EasyB test segments are executed in the order they have been declared so if you do that selenium will get stopped before any scenario can be executed!

Step 7: Run the test and see it fail (we have no view just yet)
grails test-app functional:easyb
Step 8: Create the view (/views/home/index.gsp).
Message: ${message}
Step 9: Execute the test and see it pass:
grails test-app functional:easyb

I hope this will cut down the time you spent implementing easyb- and selenium-enabled functional tests clearing any misunderstandings you might have after reading online docs (they suck big time!).

Do I hear "That's a lot of work, man!"??? Well if you're really that lazy grab the ready-to-run package here and enjoy the rest of the evening :)

Have fun!

Tuesday, October 5, 2010

Grails 1.3.5 Released!

Hi there all you Grails geeks!

Yesterday Grails 1.3.5 was released :) With one small addition from me:

class HomeController {

def index = { }

def save = { LoginCommand login ->
println "login.username: ${login.username}"
println "login.password: ${login.password}"
println "comment.text: ${comment.text}"

redirect action: "index"
}
}

class LoginCommand {
String username
String password
}

This is pretty basic stuff, right? We're creating a command object, giving it as the closure parameter and values from the form (named "username" and "password" get deserialized into this object.
What was missing though is the fact that not all of the form parameters need to be bound to the same command object. In fact there are times when more than one object allows for better re-use and/or separation of concerns.
The elements that need to be deserialized into multiple command objects should be prefixed with command type (by convention).

So "LoginCommand" becomes "login.", "CommentCommand" becomes "comment." and for example "VeryLongAndComplexCommand" becomes "very-long-and-complex.".
  <g:form action="save">
<label for="login.username">Username: <g:textField name="login.username"/><br/>
<label for="login.password">Password: </label>
<g:textField name="login.password"/><br/>
<label for="comment.text">Comment</label>
<g:textField name="comment.text"/><br/>
<br/>
<input type="submit"/>
</g:form>
class HomeController {

def index = { }

def save = { LoginCommand login, CommentCommand comment ->
println "login.username: ${login.username}"
println "login.password: ${login.password}"
println "comment.text: ${comment.text}"

redirect action: "index"
}
}

class LoginCommand {
String username
String password
}

class CommentCommand {
String text
}

I know this example is lame, useless and all that but hey - it's just an example :D

The actual prefix for commands is taken from the class name - not the parameter name! Bear that in mind!

I hope you'll like it!

Monday, October 4, 2010

Grails console and LDAP via JNDI

Hi folks!

I've spent over 6 hours today fiddling with LDAP from Grails console and let me tell you it's been a huuuuge disappointment! Let me explain...

I'm using LDAP (it's Active Directory but this is not really relevant) to store users with their attributes. To perform authentication other than usually (having a user that has right to read the password attribute and then query LDAP once a user logs in, verify the password, etc.) I need to login in using credentials provided by user on login page.

With that the use of grails-springsecurity-ldap is pretty much toasted and a new implementation is needed. I don't want to get into any details of spring security plugin, because it makes no sense in this context. What makes a huge difference is the way we interact with LDAP in Java.


import javax.naming.*
import javax.naming.ldap.*

try {
LdapContext context = new InitialLdapContext((Hashtable) [
(Context.INITIAL_CONTEXT_FACTORY): "com.sun.jndi.ldap.LdapCtxFactory",
(Context.PROVIDER_URL) : "ldap://ldap.localdomain.com",
(Context.SECURITY_AUTHENTICATION): "simple",
(Context.SECURITY_PRINCIPAL) : "DOMAIN\\invalid",
(Context.SECURITY_CREDENTIALS) : "invalid",
(Context.REFERRAL) : "follow",
(Context.BATCHSIZE) : "30"
], (Control[]) []);
println "Logged in!"
} catch (AuthenticationException e) {
println "NOT lOGGED IN"
}


The assumption here is of course that "DOMAIN\invalid" either does not exist or has a password other than "invalid" :)

What one would expect from this piece of code is that it tries to create the initial context and since the credentials are wrong an AuthenticationException is being thrown thus the message "NOT LOGGED IN" should appear.

Well, in Groovy console (you know, the one that you get when you install Groovy on your PC) works exactly this way but Grails console works differently. It creates the initial context without problems and presents one with "Logged in!" message.

Why is this happening? Well the CLI support stuff overrides all protocol handlers (and I mean EVERY SINGLE ONE) with Spring's org.springframework.mock.jndi.SimpleNamingContext! Grouse!

What I ended up doing was to use the LdapClient directly (even though it's an implementation detail it gave me all the methods I needed) and life is (sort of) good again...

Check the bug report here.