How do we retrieve the list of parameters of a closure/method in groovy dynamically, javascript style through the arguments array
say for example that i want to log a message this way
def closure = {name,id ->
log.debug "Executing method with params name:${} id:${id}"
}
OR
void method (String name,String id) {
log.debug "Executing method with params name:${} id:${id}"
}
I read once about a way to reference the list of parameters of a closure, but i have no recollection of that and looking at the groovy API for Closure reveals only getParametersType() method. As for the method, there is a way to call a method as a closure and then i can retrieve the method parameters
ken
You won't like it (and I hope it's not my bad to do research and to answer), however:
There is no API to access the list of parameters declared in a Groovy Closure or in a Java Method.
I've also looked at related types, including (for Groovy) MetaClass, and sub-types, and types in the org.codehaus.groovy.reflection package, and (for Java) types in the java.lang.reflect package.
Furthermore, I did an extensive Google search to trace extraterrestrials. ;-)
If we need a variable-length list of closure or method arguments, we can use an Object[] array, a List, or varargs as parameters:
def closure = { id, Object... args ->
println id
args.each { println it }
}
closure.call(1, "foo", "bar")
Well, that's the limitations and options!
The parameter names can be retrieved if the compiler included debugging symbols, though not through the standard Java Reflection API.
See this post for an example https://stackoverflow.com/a/2729907/395921
I think you may want to take a look at varargs http://www.javalobby.org/articles/groovy-intro3/
Related
Suppose we have the following method:
def myMethodWithParameters(param1, def param2, Object param3) {
...
}
What are the differences between using the def keyword and using Object as type for an argument?
What are the differences between using the def keyword and not using any type/keyword for an argument?
What I know so far and does not completely answer the question:
def keyword is used to allow dynamic types.
So you can even put an Object[] in it.
def keyword can be used to make variables available only in current scope instead of globally
Quick link to the docs which do a good job of explaining this:
When defining a method with untyped parameters, you can use def but
it’s not needed, so we tend to omit them. So instead of:
void doSomething(def param1, def param2) { }
Prefer:
void doSomething(param1, param2) { }
But as we mention in the last
section of the document, it’s usually better to type your method
parameters, so as to help with documenting your code, and also help
IDEs for code-completion, or for leveraging the static type checking
or static compilation capabilities of Groovy.
The general rule I follow with Groovy, is:
If you know what type you expect, or return, then put that type in the definition. If you only accept String, add the type to the parameter (the same with returning a value). This goes doubly for methods which form part of your "public" API (ie: if other classes or people are going to be making use of the method).
If it's just internal, or accepts a range of value types, then leave the argument untyped, and let Groovy sort it out...
Why do some core taglibs in Grails return a closure? For example createLink (see source)? What are the benefits or use cases?
So, what you are actually seeing is that createLink is defined as a Closure, not that it's returning a Closure when it's executed. The closure itself is executed and delegates the implementation which is responsible for the actual work of creating the StreamCharBuffer.
Let's look at the source and see what's really going on:
Closure createLink = { attrs ->
return doCreateLink(attrs instanceof Map ? (Map) attrs : Collections.emptyMap())
}
As you can see above we have a variable called createLink of type Closure which delegates it's work to doCreateLink. Which happens to be a protected method within the containing class.
protected String doCreateLink(Map attrs) {
... // actual implementation cut out of this example
return useJsessionId ? res.encodeURL(generatedLink) : generatedLink
}
As you can see this is where the actual work is done to generate the StreamCharBuffer (Well, String, which casts nicely).
Now, why would you do this? One possible use case is, the method doCreateLink is much more strict than the closure createLink in the formal definition. By using a Closure instead of the method, the call to createLink can change slightly over time as enhancements or additions are made to it with (hopefully) little or no impact to previous uses of it.
Hopefully that helps explain a bit about what you are seeing and possibly why.
I have a method like this.
def process(file){
if(file != null && !file.empty){
anotherMethod(file.inputStream);
}
}
If I call this method from Java, what type of object do I need to pass into this method? I tried File,ZipFile but they don't have empty method.
It's impossible to say for definite without seeing more context (where is this method usually called from the Grails application, for example), but a possible candidate would be MultipartFile, or rather one of its concrete implementations such as MockMultipartFile. The empty and inputStream properties that the groovy code is accessing correspond to the isEmpty() and getInputStream() bean-style accessor methods of this interface.
The normal purpose of this type is to handle multipart/form-data file uploads - it's what you get when you call request.getFile('fieldName') in a controller.
I'm starting to learn grails and there is some groovy syntax that I don't get at all, and is undocumented as far as I can tell because I don't know what it's called.
What are 'grails', 'views', and 'gsp' in the code below?
grails {
views {
gsp {
encoding = 'UTF-8'
// ...
}
}
}
Thanks!
p.s. I feel like an idiot for not being able to figure this out...
This is an example of DSL (domain specific language) code. In Groovy, many DSLs are implemented as Groovy code, although sometimes it can look pretty funky. This code block is run as Groovy code, and it's more clear that it's code if you add in the omitted optional parentheses:
grails({
views({
gsp({
encoding = 'UTF-8'
// ...
})
})
})
and more so if we replace the property set call to the equivalent method call
grails({
views({
gsp({
setEncoding('UTF-8')
// ...
})
})
})
If you ran this in a console or as part of other Groovy code or in a Grails app it would fail, because there's no 'grails' method taking a closure as an argument, or a similar 'views' or 'gsp' method, and there's no setEncoding(String) method either. But when run as DSL code, often the code is run inside a closure whose delegate is set to a DSL helper class that handles the resulting methodMissing and propertyMissing calls.
This helper looks at the method name and the number and/or types of the method arguments (or property name and value type) and if they are valid for the DSL, it does the corresponding work, otherwise it throws a MissingMethodException/MissingPropertyException, or a DSL-specific exception, or handles the problem some other way.
In this case, there's a configuration DSL handler that translates these method calls into config property calls.
There are several other DSLs in use in a Grails app that work the same way. The mapping and constraints blocks in domain classes, the grails.project.dependency.resolution block in BuildConfig.groovy, etc. All are evaluated as Groovy code, and the missing method/property calls configure GORM mappings, constraint definitions, plugin dependencies, etc.
Programming Groovy 2 is a particularly good Groovy book for learning DSLs.
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?
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.
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. :)