How to declare a method inside a closure.Or which is better to use method or closure.
I have a closure and in that closure i have a method to call and i defined method as
def getBindedGenes(Long colId) {
........
}
But when i used codenarc plugin for code review it is showing the rule as GrailsPublicControllerMethod and the message as The Grails controller has a public method getBindedGenes. This should be a closure property or moved
What is the cause and what is happening exactly.
Thanks in advance
I think CodeNarc is warning you that your controller actions must be public closures, not public methods. Given that you can't use a public controller method as an action, there's probably no good reason to have one.
Grails 2.0 Update
Since Grails 2.0, public methods of controllers can be used as actions, and if fact, it is now recommended to use methods instead of closures.
Related
In grails we can define an action using 2 ways:-
def actionname()
{
}
and
def actionname = {
}
What is the difference between the two styles? When I tried to insert a spring security annotation above the action (second style) it said "#Secured" not applicable to field.
What does this mean? Is it because of closure?
The Grails reference docs 7.The Web Layer mentions the use of closures for controller actions in earlier versions of Grails, the preference is now to use methods. However, both are supported. It goes on to list some benefits of using methods instead.
Personally, I use methods in all my controllers and have also come across the issue with annotations such as #Secured that only work on methods and not the closures.
In earlier versions of Grails option 2 (actions as closures) was the only supported style. Grails 2.x introduced the actions-as-methods style and this is now the recommended approach, but the closure style is still supported for backwards compatibility and you'll see it if you are working on an app (or plugin) that was originally written on Grails 1.x.
The first is normal method definition with undefined return type.
The second is an assigment of a closure to a property 'actionname'.
That is why you get "#Secured" not applicable to field message, because this annotation is for methods only.
Shuttsy is correct that that the first way is now a preffered way to define actions in Grails.
This is an agreeable way of defining methods in Groovy at minimal level having the structure above.
The second way of defining is not refering to a method definition rather it's somehow a rule like closure constraints that governs a given class or method. Like when it is used in domain class .
Example
class Person {
String name
Person parent
static belongsTo = [ supervisor: Person ]
static mappedBy = [ supervisor: "none", parent: "none" ]
static constraints = { supervisor nullable: true }
//this allowed for methods only and why you got an error in above cases
#override
def toString(){
return name.toString()
}
}
#Secured annotation accept list of roles (String[])
it is used only for a method definition based on
toString() method inside the class ...i just give u a scenario of the two ..
#Secured annotation since spring security 2.0 supports method only. As a result, you have to convert closures to real methods if you want to apply the security annotation for it. Read more #Secured Annotation.
I have a very simple function which I define as follows:
def mySimpleFunction(Map myMap) {
// Function logic here...
}
However, when I try to compile this, I get a warning message and build exception which says that: The [mySimpleFunction] action accepts a parameter of type [java.util.Map] which has not been marked with Validateable.
How can I mark this function as Validateable? I imported the org.codehaus.groovy.grails.validation.Validateable
and have marked my class as #Validateable .
What should I be doing differently in order to get my application to build?
Thank you in advance!
If it is a helper method, make it private. In Grails 2.0+ public controller methods are assumed to be actions, and arguments are assumed to be bindable. That means they need to be number types, boolean, String, etc., or a command object class.
Command object classes are automatically made validateable if they're defined in the controller class file, and if they're defined elsewhere they need to be annotated as #Validateable.
Since this is a helper method and not an action, just make it private (especially since it can't be called from another class anyway):
private mySimpleFunction(Map myMap) {
// Function logic here...
}
I'm trying to create a generic function in grails that will allow me to specify a class and function name, and intercept any function calls based on that criteria:
getSomeClass().metaClass.invokeMethod = { String methodName, args ->
MetaMethod someAction = getSomeClass().metaClass.getMetaMethod(methodName, args)
def result = someAction.invoke(delegate, args)
if (methodName==getSomeMethodName())
intercept(args, result)
return result
}
This works for POGO, and domain classes, but does not seem to work for controller classes. While I'm fully aware there are Controller interceptors and filters available in Grails, these don't really centralise what I'm trying to achieve, and was trying to create a simple generic function for some centralised behaviour
Any guidance on why this doesn't work on Controllers would be appreciated, thanks
Your approach will work for method calls that are made through the Groovy metaclass mechanism, but in Grails 2 this doesn't apply to controller actions - they're called using normal Java reflection (java.lang.reflect.Method.invoke), and therefore your custom invokeMethod is bypassed.
If you want an AOP mechanism that'll work for calls from Java as well as from Groovy you'll probably have to use something like AspectJ load-time weaving. Spring's proxy-based AOP may work but the Grails 2 controller system relies on the action methods having a particular #Action annotation (which is added at compile time by an AST transformation) and I don't know whether Spring AOP proxies preserve method annotations from the target class on the generated proxy methods.
Could it be that MyController.metaClass.invokeMethod is overwritten by the grails framework after your definition?
Have you tried to check the content of MyController.metaClass.invokeMethod through reflection?
How does inheritance work in groovy for closures? Is there anything special to be aware of? My application is to extend a plugin controller, that I need to leave alone should any updates come in for it.
Closure inheritance doesn't make much sense (in the way we tend to use them anyway). A closure in practice is an instance of the Closure class. If we created subclasses of Closure then we could subclass those, but we don't. For example in controllers, we define actions as inline instances, e.g.
def list = {
...
}
These are treated like methods in that we can call list(), but that's just syntactic sugar for list.call(), since call() is an instance method of the Closure class.
In Grails 2.0 the preferred approach to creating controller actions is to use methods, although closures are still supported for backwards compatibility. One of the primary reasons for this switch is to support overloading and overriding, which isn't possible (or at least practical) with inline closures. You can define a closure instance in a subclass with the same name as a base class instance, but you can't call super.list() since it will result in a StackOverflowError
My use case is to log every method call on an object.
After adding a method interceptor on the target object, I call the method Foo. This method Foo calls a method Bar. Only the method Foo will be logged.
class MyClass {
public void Foo() {Bar();}
public void Bar() {}
}
Reading the Spring documentation, I have found a sentence that explained why I cannot implement what I want. From Spring documentation (page 146):
Please note that in both cases a target method implementation that calls
other methods on the target object will not be advised.
Am I missing something here? Or is this really a Spring limitation?
A start of solution...
http://www.digizenstudio.com/blog/2007/05/29/the-self-calling-limitation-in-spring-aop-and-one-unintrusive-solution/
EDIT
Finally, I decided to switch to Castle AOP. They propose a class proxy that feets my needs.
You could use AspectJ weaving that will not have any such limitations.