I cant get Domain.count() static method to work - grails

The Grails documentation defines a "count" static method, defined in the documentation like this:
Description
Counts the number of instances in the database and returns the result
Parameters
None
Example
def noOfBooks = Book.count()
However, whenever I call it, I get this error! I simple added a call to the name of my Domain Class (Company) like this to a working Controller
def companies = Company.count()
and when it exectutes that line, it blows up with the following error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass
Other, working, code in the controller (pre-generated with the static scaffolding commands) access Company.get(...) etc, with no error
What am I doing wrong?

This
class HomeController {
def companies = Company.count()
def index = {
render(view:"index")
}
}
Fails because as lael pointed out the count() method is not available when the application is started. The count() method is a Dynamic method which GORM addeds to the domain classes. Spring (the underlying framework) creates an object for every artifact (Controller/Service/Domain Class etc) at start up. GORM would be after this.
Spring is trying to create a HomeController class, the construction of Home Controller will assign the value of company.count to Companies at startup, However GORM has not started yet so the dynamic methods have not been added.
This code is incorrect anyway, if it did work then the companies variable would only have the value of the number of companies at start up of the application. Once you get "used" to groovy and grails I think you will appreciate the speed of development.
Hope this helps.

The short answer is that the count() method and many others are added to the metaClass at runtime after the Hibernate Plugin is loaded. count() isn't a static method that is available at compile time as Java does it, but rather a static method that is added to the Domain's metaClass at runtime (apparently after parsing the controllers).
Why? Because it doesn't make sense to have count(), get() or read(), etc. methods until after Hibernate/GORM is initialized. It would not be hooked up to the datasource and the methods would be invalid.
I can't help but wonder why you would need to put a property like that on a controller. As soon as you save a new Company or delete one - your companies count would be off.
The long answer would be diving into Grails' source, From the GORMNamespaceHandler -> GORMSessionFactoryDefinitionParser -> GORMEnhancingBeanPostProcessor -> HibernatePluginSupport -> HibernatePluginSupport.addBasicPersistenceMethods()

Related

Get a service bean from Grails Holders class

I'm trying to update a plugin to Grails 2.4. Thus I have to replace the deprecated ApplicationContext class by the newer Holders class.
But I'm having some problems getting a service bean from the Holders class.
Running the code below:
import grails.util.Holders;
def myService = Holders.grailsApplication.mainContext.myService
println myService
println myService.getClass()
println myService.serviceMethod()
It prints something like:
grails.plugin.my.MyService#1e5cd54d
Exception thrown
java.lang.NullPointerException
at ConsoleScript2.run(ConsoleScript2:6)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
It throws a NullPointerException when I call both: the "getClass" method and the "serviceMethod" method.
I tryed to see what's happening by debugging from eclipse too and I can observe "myService" variable being set to an object. When I click on it I can see it's String representation just like printed above. But I can't see anything inside the object. This service' class has member variables, but I can't see them on debug. It's like uf they were'nt there.
Can someone explain me what is going wrong?
Thanks
Don't use Holders, and avoid pulling in dependencies. Use dependency injection, it's a Good Thing.
Your src/groovy class is probably called from a controller, service, Quartz job, or some other Grails artifact that supports DI, right? If so, inject this service there, and when you call your src/groovy class, pass it as a method argument, or inject it once in a constructor or a setter.
Even if it's not called from a Grails artifact it's likely easy to get access to the service. E.g. a servlet can access the ServletContext and it's simple to access the ApplicationContext from there.

Grails warning at compile of controllers

I am currently getting the warning in Grails of
'The [update] action accepts a parameter of type [edu.acu.teachereval.SubjectCode] which has not been marked with #Validateable. Data binding will still be applied to this command object but the instance will not be validateable.
#Transactional'
along with the same errors for show, save, edit, and delete for the controller mentioned in the error and other controllers that I have created. I have seen this issue for user created functions, but I have not seen this error for functions that are built in to grails. Any assistance would be appreciated.
I think you need to add a #Validateable annotation to your SubjectCode class.
Reference
This may be coming late, But this error is likely to occur when you use models not created in the domain conventional folder.
It seems grails automatically injects the #Validateable annotation to domain classes/models in the domain Folder,
If you therefore create your models in the src/grails or src/java folder, You are likely to get this error when the model object is passed/posted/submited via a View to a controller function.
Try adding the #Validateable annotation to the domain object
Move the domain model to the domain grails convention folder
or maybe Grails is overreaching while simultaneously giving misleading error messages... nah, that never happens. For a more relevant answer, see:
Groovy / Grails using a map as a parameter of a function

Grails Domain Class Abstract/Non-Abstract Dynamic Check

I have a loop in my controller that does something like this:
for(d in grailsApplication.domainClasses) {
def c = d.getClazz().count()
// construct table containing object instance counts
}
My intent is to use this loop to count the instances of non-leaf domain classes in my database. Is there a way to query the domain class itself to find out if it is abstract or not? I wasn't sure if there were some member functions automatically added by the framework since I am still new to Groovy/Grails. I couldn't find anything that addressed it in the Grails documentation.
Figured it out after a few minutes of poking around the Groovy documentation. The function isAbstract() can be invoked on the domain class to determine whether or not the domain class is a leaf node in the class hierarchy

Adding parameter to AuthorizeAttribute constructor causes failure in MvcSiteMapProvider?

I've been using MvcSiteMapProvider based on authorize attributes and it was all right until we introduced a new class derived from AuthorizeAttribute. Main difference is in its constructor signature:
public MyAuthorizeAttribute(param RoleCode[] roles) {
Roles = string.join(",", roles.Select(r => r.ToString());
}
And... MvcSiteMapProvider shown unexpected result: only actions marked by MyAuthorizeAttribute became invisible. I've checked that by disabling this constructor - everything went as it had been before adding a parameter to the constructor. Also - it's not params specific - any parameter (event int) leads to such behaviour.
AS I understood from MvcSiteMapProvider sources, it emits some code to emulate authorize attributes - but looks like it's impossible to save assembly generated by external code. I know that there is a workaround - use some kind of enumerable property, but have you got any suggestions how to make it work with constructor parameters? Do you know why MvcSiteMapProvider behaves like that?
So, after spending some time in debugging, I realized the answer: dynamic proxies.
The problem is that during request execution inside MVC framework there is no easy way to find out how a class derived from AuthorizeAttribute performs its work. In case of access check failure some could throw exception, some - return 401 status code, some redirect to login page at once, and so on.
But MvcSiteMapProvides does that! It uses the following workaround:
if class is AuthorizeAttribute:
create an instance of InternalAuthorize class which is fairly simple.
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
else
generate a proxy class derived from a type of attribute,
create instance, /// << here we get an exception
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
As it is clear, that's not an easy task to make a proxy, which is aware of your constructor parameters. Exception about default constructor absence is thrown, of course, but it is then consumed by empty catch clause. That is really sad - at least a single debug trace would have saved me a couple of hours.
So the answer at last:
Obviously you should use parameterless attribute constructor (why oh why that's not mentioned anywhere?)
Make custom acl provider: implement IAclModule interface and unleash your knowledge about your own authorize attributes within it.

Groovy Mixins?

I'm trying to mix-in a class in my Groovy/Grails app, and I'm using the syntax defined in the docs, but I keep getting an error.
I have a domain class that looks like this:
class Person {
mixin(ImagesMixin)
// ...
}
It compiles fine, but for some reason it won't work. The file containing ImagesMixin is located in my /src/groovy/ directory.
I've tried it using Groovy versions 1.5.7 and 1.6-RC1 without any luck. Does anyone know what I'm doing wrong?
stacktrace:
2008-12-30 17:58:25.258::WARN: Failed startup of context org.mortbay.jetty.webapp.WebAppContext#562791{/FinalTransmission,/home/kuccello/Development/workspaces/lifeforce/FinalTransmission/web-app}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError
at java.security.AccessController.doPrivileged(Native Method)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
at Init_groovy$_run_closure6.doCall(Init_groovy:131)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
at gant.Gant.dispatch(Gant.groovy:271)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:436)
at gant.Gant.processArgs(Gant.groovy:372)
Caused by: java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at Episode.class$(Episode.groovy)
at Episode.<clinit>(Episode.groovy)
... 13 more
Caused by: groovy.lang.MissingMethodException: No signature of method: static Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
at Broadcast.<clinit>(MyClass.groovy:17)
... 17 more
2008-12-30 17:58:25.259::WARN: Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError:
groovy.lang.MissingMethodException: No signature of method: Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
at Broadcast.<clinit>(Person.groovy:17)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at Episode.class$(BelongsToMyClass.groovy)
at Episode.<clinit>(BelongsToMyClass.groovy)
at java.security.AccessController.doPrivileged(Native Method)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
at Init_groovy$_run_closure6.doCall(Init_groovy:131)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
at gant.Gant.dispatch(Gant.groovy:271)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:436)
at gant.Gant.processArgs(Gant.groovy:372)
2008-12-30 17:58:25.271::INFO: Started SelectChannelConnector#0.0.0.0:8080
Since Groovy 1.6 you can either apply a mixin at compile-time to a class using an annotation
#Mixin(ImagesMixin)
class Person {
}
Or you can apply the mixin at runtime like this:
def myMixin = ImagesMixin
Person.mixin myMixin
The latter approach is more dynamic as the class to mixin can be determined at runtime. Further information about Groovy mixins is available here.
In my experience, a lot of meta-programming of domain classes simply doesn't work. I don't exactly know why, but suspect it's due to the fact these classes are already very heavily meta-programmed by the Grails runtime. In general my approach is
Try the meta-programming on a POGO in the Groovy console
If that works, try it on a non-domain class in the Grails console
If that works, try it on a domain class in the Grails console. If it doesn't work, then it must be because it's a domain class (rather than a problem with the syntax). At this point it's advisable to try and find another way of accomplishing your goal. If that's not possible, then use a combination of the Grails mailing list and/or Stackoverflow and/or the Grails source code to try and get the meta-programming working.
I don't think you are using the proper mixin syntax. Try this:
class MyMixin {
static doStuff(Person) {
'stuff was done'
}
}
class Person {}
Person.mixin MyMixin
new Person().doStuff()
I guess what you've seen there is rather a proposal than a feature ;) Groovy does not support mixins out of the box in this way yet (if ever). But there is a 3rd party lib that can be used to emulate such a behavour: Injecto. And mixins can be defined using AST-Macros in the 1.6 version of Groovy (which is not final yet).
You should always check if your're reading the docs from the real groovy project or from the GroovyJSR project (which is rather a place where proposals are collected).
Another way is to use plain-old MOP to inject behaviour into groovy classes by modifying metaClasses.
Cheers
In case this helps anyone, Following on from #virtualeyes comment above, I've found that
Person.doStuff()
fails unless you call the following first:
new Person().doStuff()
Person.doStuff()
after which, the static method on the class does seem to work (for me, using Grails 2.2.4) I guess it's to do with initialising the class, or something, but I tried:
Person.metaClass.initialize()
Person.doStuff()
and that didn't work!
FYI: There is such a thing as "embedded" domains in Grails now, but it has problems. This is where you can logically include one domain as part of another and have its fields all occur physically in the one DB table. For example, if you find that you have the same subset of fields appearing in multiple tables, like street address/city/state/zip, you could define a StreetAddress domain and embed it. One of the current problems is that Grails will still create a street_address table in addition to embedding its fields in the other tables (unless you play tricks). There are submitted patches pending for this, it seems.
Grails domain objects are already heavily meta-programmed.
Instead of the groovy mixin try:
#grails.util.Mixin(ImagesMixin)
class Person {
}
Use Traits!
Traits are the reason they removed support for mixins, because that are just better. They're basically abstract classes that are implemented. Allowing you to use multiple and operate them as partial classes.
trait A {
void printSomething() {
println "foobar"
}
}
class B implements A {
void printAnything() {
printSomething()
}
}
new B().printAnything()
Try it out!

Resources