Dónal
Dónal

Reputation: 187399

binding request parameters to action arguments

In Grails you can declare a controller action like this:

def create(Integer foo, Integer bar) {
}

And if your HTTP request has parameters named foo and bar with values that can be converted to an Integer, the parameters will be assigned these values. I'm wondering how Grails can do this, because my understanding is that at the JVM bytecode level, a method's formal parameter names are not available. Is this witchcraft or am I misunderstanding something?

Upvotes: 1

Views: 558

Answers (2)

Burt Beckwith
Burt Beckwith

Reputation: 75681

Basically what happens is that there's an AST transform that adds a new method with no args and the same name. This new method has logic in it to do the data binding based on the declared types of your "real" method, and then call your method. That's why the types are required (otherwise there's no way to do a conversion) and why you cannot have method overloads.

The inability to have overloaded methods is easy to work around though. Say you wanted an action

def foo(String bar)

and another

def foo(String bar, Integer wahoo)

In this scenario just keep the 2nd method and check to see if wahoo is null.

It's also important to use object parameter types and not primitives. If you use int/long/boolean/etc. and there is no provided parameter, you would get a NPE (since zero is not an acceptable conversion from null for numbers, and either is false for booleans).

You can get a decent sense for what's going on if you decompile the class using JD-GUI or another decompiler.

Upvotes: 3

Joshua Moore
Joshua Moore

Reputation: 24776

The fact that Grails controllers are Groovy classes helps quite a lot. Looking through the source code for controllers you can see where it makes heavy use of AST transformations, in particular the MethodNode. So, before it becomes bytecode the "witchcraft" is done. :)

Upvotes: 1

Related Questions