How do I determine if a class is a Grails domain object? - grails

For an arbitrary object what is the easiest way to determine if the type of the object is a Grails domain class?

You can use the GrailsApplication for that. Add a dependency injection to your controller or service:
def grailsApplication
and then you can use it like this:
def foo = ...
if (grailsApplication.isDomainClass(foo.getClass()) {
...
}

Found the following snippet at https://svn.intuitive-collaboration.com/RiskAnalytics/trunk/riskanalytics-grails/src/java/org/codehaus/groovy/grails/web/binding/GrailsDataBinder.java
DomainClassArtefactHandler.isDomainClass(clazz)
The javadoc is here: http://grails.org/doc/latest/api/org/codehaus/groovy/grails/commons/DomainClassArtefactHandler.html#isDomainClass(java.lang.Class)

Related

Grails and Groovy metaclass package name convention

I would like to be able to place my metaclasses in the package groovy.runtime.metaclass according to the convention defined here using the delegating meta class. I have placed MyClassMetaClass in groovy.runtime.metaclass.mypackage. for the concrete class mypackage.MyClass{}. Unfortunately calls to MyClass{} are not intercepted by MyClassMetaClass{}. Perhaps this is related to how grails initializes..?
It is possible to use a delegating meta class in a grails project by changing BootStrap.groovy.
import org.codehaus.groovy.runtime.InvokerHelper
class BootStrap {
def init = { servletContext ->
def myMetaClass = new MyClassMetaClass(MyClass.class)
InvokerHelper.metaRegistry.setMetaClass(MyClass.class, myMetaClass)
}
def destroy = {
}
}
Ofcourse this is not the same as implementing delegating meta classes as mentioned in the question.

issue with injecting grails service in domain class

I am trying to inject 'GraauditService' into grails 'User' domain class.
I am using grails 1.3.7
I have tried direct injection method as I do in controllers
import com.gra.audit.GraauditService
class User {
def graauditService // or even GraauditService graauditService with graauditService as transient
.......
the above does not work. graauditService is always coming up as null
I also tried to inject through ApplicationHolder as shown here
But looks like ApplicationHolder is deprecated now
How can I use the service in the domain class?
The following works for me
class User {
def springSecurityService
static transients = ['springSecurityService']
}
Try injecting it using the transient keyword:
class User {
transient graauditService
}
For Grails 1.3.7, the solution is to inject it through the ApplicationHolder, as shown here by Burt Beckwith.
The above solutions may work for Grails 2.0, but not for 1.3.7 or earlier.

creating a grails domain class from its class name

I am trying to use the Class.forName('com.mypack.MyDomain').newInstance()
to create an instance of the grails domain from its qualified name.
But Its throwing a ClassNotFoundException.
I assume this is because the .forName('') expects the class to be a java class instead of a groovy class?
How to make this work in grails, or is there another method to create the domain object from the class name in String format.
Thanks
Priyank
Another route to try would be to do:
GrailsDomainClass dc = grailsApplication.getDomainClass( 'com.mypack.MyDomain' )
def newDomainObject = dc.clazz.newInstance()
Try
GrailsClass clazz = grailsApplication.getArtefactByLogicalPropertyName(DomainClassArtefactHandler.TYPE, className)
clazz.clazz.newInstance()

Change the name of an injected service in grails

Can't seem to find info on this, if you have some, please point me to the right thread/post/link!
I have a service, lets say it's called 'SomeServiceWithAReallyLongNameICannotChange'. Of course the normal way to use services is to allow grails to inject them using either typless or typed notation:
class SomeClass{
//...
def someServiceWithAReallyLongNameICannotChange
//...
}
-- or --
class SomeClass{
//...
SomeServiceWithAReallyLongNameICannotChange someServiceWithAReallyLongNameICannotChange
//...
}
What I would like to do is rename the service to something shorter, but only where I'm using it, as I cannot change the name of the actual service. I tried using 'as' notation like you do with imports, and I tried changing the name in the typed declaration, but none of these things seem to work. Is this possible?
I tried something like this:
class SomeClass{
//...
def someServiceWithAReallyLongNameICannotChange as SS
//and I tried
def SomeServiceWithAReallyLongNameICannotChange SS
//no joy
//...
}
Thanks for your help!
The solution is to use autowire by type. By default grails uses autowire by name and hence you have to declare the service with the same name as the bean.
Here's example
class FooController {
boolean byName = false //set autowire by type
SomeReallyLongService service
}
You have to define a boolean variable byName and set it to false
You can not use def but must use the actual type of the service when declaring the service
It will enable autowire by type for whole controller, so all other dependencies will also be autowired by type
It is explained here
Update:
It is even possible to use Autowired annotation along with Qualifier.
Example:
class MyController {
#Autowired
#Qualifier("myServiceWithDifferntName")
def someService
}
You should be able to create a new bean via resources.groovy
beans = {
ss(SomeServiceWithAReallyLongNameICannotChange)
}
You can then inject it normally:
class SomeClass {
//...
def ss
//...
}
Another option, if you don't want to use autowire by type through the whole controller, nor do you want to add a custom bean for some reason, is to add a simple method to your controllers where you need the service, like so:
def someServiceWithAReallyLongNameICannotChange
def getSS() { someServiceWithAReallyLongNameICannotChange }
Then you could reference the service using ss.someMethod() anywhere within that controller.
However, this still requires you to add a chunk of code for every controller you use this service, or you will have inconsistent naming of the service.
(Personally, I think that doelleri's method is the best, since it allows you to be consistent in naming without modifying individual classes.)
I tried it and it's not working for me on Grails 3, did this by doing
import org.springframework.beans.factory.annotation.Autowired
...
#Autowired
PaymentStrategyService paymentStrategySvc

How to access the g.-namespace in a Domain Class

I would like to make use of the g.message() functionality in the toString method of my domain class, but the g.-namespace is not accessible by default.
I doubt that a import g.* will do the trick.
I already know that I can use the messageSource functionality, but it would be nicer to use the same syntax as in the views.
You can use:
class MyDomain {
def someMethod() {
def g = ApplicationHolder.application.mainContext.getBean( 'org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib' )
return g.message(....)
}
}
or else you can get messageSource directly: ApplicationHolder.application.mainContext.getBean('messageSource')
Using g.render in a grails service has some hints how to use "g:" in a service. I have not tested this, but it should work mostly the same in domain classes, with one important exception: a domain class cannot use InitializingBean since it's not a bean residing in the application context.

Resources