I was migrating a grails2 plugin to the grails3, There is a class
org.codehaus.groovy.grails.web.servlet.GrailsControllerHandlerMapping
in grails2.x version, I did not find this class in grails3.
Has this class has been replaced with any other class, or it just has been removed?
There are 2 more classes which I did not find in grails3, these are
org.codehaus.groovy.grails.commons.metaclass.BeanBinding
org.codehaus.groovy.grails.commons.metaclass.PropertyExpression
There is no direct equivalent of GrailsControllerHandlerMapping this area has been refactored and is now implemented as UrlMappingsHandlerMapping
https://github.com/grails/grails-core/blob/master/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/UrlMappingsHandlerMapping.groovy
The metaclass package has also been removed as all metaprogramming has been replaced by the use of Traits.
Related
Upgrading a legacy system of grails. One of the controllers implements Serializable. This is throwing the following error in newer versions of grails:
Invalid duplicate class definition of class com.regional.ScheduleController :
The source contains at least two definitions of the class.
One of the classes is an explicit generated class using the class statement,
the other is a class generated from the script body based on the file name.
Solutions are to change the file name or to change the class name.
The solution mentioned would break (previous) grails convention. Anyone know how to handle this in grails 2.5+?
EDIT
Serializable is not the issue. I tried removing it and got the same error.
I found this explanation from another question:
IN groovy.. class B{} is a class structure and defines a class B.
Scripts are classes too.
Now you may create a B.groovy, with the content "class B{}; def b = new B()".
There would be one class named B, and a script with the very same name.
This is a conflict.
However this does not explain why it runs fine below grails 2.5 and not above it. And I can't find a def conflict like the one mentioned above in that controller.
ANSWER:
One of the imports was what was actually failing- in a way that caused groovy to generate a class definition based on the current file name. When it hit the class definition, there was already an auto generated class name to collide with.
I have a generic method for doing a common operation on many domain class
static Map getNumberOfPropertyByTopicIds(def criteriaClass, List ids) {
criteriaClass.createCriteria(). //Some GORM methods used
}
I wanted autocomplete on various things applied on criteriaClass. But for doing that I need to replace def criteriaClass to InterfaceForDomainClassBehaviour criteriaClass.
But I don't know InterfaceForDomainClassBehaviour is what. Which interface/abstract class implements Domain class behaviour?
There isn't one.
Grails uses "convention over configuration", so unlike other frameworks where you extend a base class, implement one or more interfaces, use annotations, etc., you simply put your artifact classes (domain classes, services, etc.) in the correct directory under grails-app, use the appropriate class naming convention (except for domain classes), and Grails mixes in behavior for you. You can configure things of course, e.g. with the mapping block, etc.
Before Grails 2 adding methods was mostly done using Groovy runtime metaprogramming, and in Grails 2 most of the behavior is added at compile time using ASTs, and runtime metaprogramming is used mostly for dynamic code like findAllByHeightAndWeightAndHairColorAndShoeSize where it would be impractical and/or impossible to compile in every combination.
Over 100 methods are added to domain classes (decompile some - it's pretty amazing to see how much ends up in your classes considering how small the Groovy source is) and dozens are added to controllers. But this is all mixed in, so although there is significant overlap between your domain classes, there's no common base class or interface unless you add them yourself.
I am trying to use Spring in my rails project but I have my own class called Spring that inherits from another class of mine called Feature.
In my code I call .superclass on a variable that is set to Spring sometimes. It fails because the variable is set to the other Spring class. How can I set it to class I defined?
i would suggest use modules.
create your class inside a module and call it MyModule::Spring to avoid conflicts
According to the documentation, a Grails controller is simply a class with "Controller" appended to the name and saved in grails-app/controllers/. The simplest of such a class being:
package some.package
class FooController {
def index = {}
}
When the Grails application is run, this controller will inherit some standard methods like getParams and getSession. From the attached screenshot I can see that these are added via groovy.lang.ExpandoMetaClass. What I don't see is how this happens. The controller doesn't implement any interfaces or extend any abstractions. Where do these methods come from?
From Grails 2.0 a new methodology was adapted to add the dynamic methods to the controller artefacts. You can visit them step wise to see how those properties are added to Controllers:-
Controller in grails is not part of grails-core but a plugin by itself to grails named grails-plugin-controllers.
Being a plugin, the corresponding *GrailsPlugin Class would define the behavior of the plugin.
ControllersApi (extending CommonWebApi) bears all those properties which are to added to controller artefact. (Introduced from Grails 2.0)
ControllerGrailsPlugin registers ControllersApi as a spring bean.
There is more to just adding ControllerApi as a bean.
There is a concept of MetaClassEnhancer which would take/consider an API (in this case ControllerApi) and enhance/reconcile the artefact (controller) with the corresponding API by adding CachedMethods to the artefact using reflection, which is the role of a BaseApiProvider present in grails-core.
This magic happens in the Controller plugin class as well.
Now, prior to Grails 2.0 a different method was adapted to add the dynamic properties to controller. That way metaClass properties were added to controllers at runtime which was found to be less efficient. Each of the dynamic property was represented by its own class (viz: GetParamsDynamicProperty, GetSessionDynamicProperty) which is not in use right now.
So what you need to look now in the object tree for those dynamic methods is this where the CachedMethods are available in the controller. Hope that helps. I would be glad to add more if you seek more. :-)
You are right, Grails 'Controllers' are not really Controllers in the sense they inherit from a base class, but rather they are just simple POGOs that follow the convention of being placed in the grails-app/controllers directory. When your application is compiled, 30+ methods are mixed in through AST transformations, the majority of them coming from
org.codehaus.groovy.grails.plugins.web.api.ControllersApi, but also from
org.codehaus.groovy.grails.plugins.converters.api.ConvertersControllersApi,
org.codehaus.groovy.grails.plugins.web.api.ControllersMimeTypesApi.
The preceding was paraphrased from Programming Grails by Burt Beckwith, and I would recommend it if you are interested in the finer details of Grails.
Quoting from Burt Beckwith's excellent book, Programming Grails:
Over 30 methods are mixed into controller classes with AST
transformations. The majority are added from the
org.codehaus.groovy.grails.plugins.web.api.ControllersApi class
ControllersApi source
before Grails 2.x we used an abstract class to model shared domain properties. This worked perfect but now when using Grails 2.x is see no way of creating shared domain properties and methods. When i use an abstract class and let my domain classes extend that abstract class i get one big database table.
Is there a alternative way of creating shared domain properties / methods?
Docs says that you need to move your base class into the /src/groovy at this case