Grails override a plugin service static method - grails

I'm using a plugin which has this Service:
package grails.plugins.imports
class ImportsService {
static rabbitQueue = "${grails.util.Holders.grailsApplication.metadata['app.name']}ImportRows"
....
}
While this works fine when using run-app; i.e grails run-app, this is wreaking havoc when attempting to run as a war; grails run-war.
2014-09-09 15:54:25,069 [localhost-startStop-1] ERROR StackTrace - Full Stack Trace:
java.lang.NullPointerException: Cannot get property 'metadata' on null object
at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56)
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:169)
at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at grails.plugins.imports.ImportsService.<clinit>(ImportsService.groovy:9)
Short of forking the plugin, any suggestions here?
Grails 2.3.10
Thanks in advance,
Todd

So, I know your goal was to avoid forking the plugin, but I think the issue is that the plugin was written in earlier days when you would get the grailsApplication object through a holder class. That's not really recommended these days (see Burt Beckwith's post on the subject), but there are options.
The easiest way for your plugin to get the grailsApplication object would be through dependency injection:
class ImportsService {
def grailsApplication
static rabbitQueue = "${grailsApplication.metadata['app.name']}ImportRows"
//....
}
Though in this case, since all you need is the app.name, it might be better to:
class ImportsService {
static rabbitQueue = "${grails.util.Metadata.current.'app.name'}ImportRows"
//....
}
You might try manipulating the plugin code in a local copy to see if that fixes the issue. GGTS makes that fairly easy by providing the plugins in the project explorer view. If that change works, and you can submit a patch to the plugin developer, you might be able to have the fix become part of the official release.

Related

Java EE injection not working on Glassfish

(Please be kind, these are my first steps in Java EE).
I'm working with Netbeans 8.1, deploying an EJB module on a local Glassfish Server.
I have a glassfish-resource.xml with the following resource defined:
<jdbc-resource enabled="true" jndi-name="java:app/jdbc/myDataSource"
And I have a DAO class where I'm trying to inject that resource
#Named
public class SimpleDal {
#Resource(name = "jdbc/myDataSource", lookup = "java:app/jdbc/myDataSource")
private static DataSource ds ;
I have tried several ways to make this work but I always end up with NULL in the variable ds. I've been debugging and querying the Context, and I always end up with the name java:app/jdbc/myDataSource not found.
Maybe I'm not doing something right, this is my first steps on Java EE (I've always developed for PHP). Can somebody please direct me in order to avoid losing more time? Thanks
Note: I've add the #Named annotation to the SimpleDal class because I've read somewhere that in order to Injection to work, I have to be on a Bean.
So, after some time I finally found out that injection doesn't work reliably on static fields (at least on my setup). Changed the field to an instance field and It worked . Posting this answer for anyone who is facing the same situation

How do I detect a Composite Primary Key in Grails 3.0?

I am currently migrating a Grails 2.4 project to Grails 3.0.10 or 3.1.0.M3.
In Grails 2.4, the following method is a workaround that allows me to detect whether a Domain Class features a composite primary key:
void isCompositePrimaryKey(GrailsDomainClass targetClass) {
def binder = new GrailsDomainBinder()
def idMapping = binder.getMapping(targetClass).identity
return idMapping instanceof org.codehaus.groovy.grails.orm.hibernate.cfg.CompositeIdentity
}
I cannot find a way to detect this in the Public API.
Though GrailsDomainClass still exists in the implementation source code, I cannot seem to access it from my project nor can I find the old CompositeIdentity.
An alternative strategy could be via targetClass.getIdentifier().getType()
but I cannot find any documentation on how to detect a composite key using the identity type.
Solved this simply by adding an additional explicit (non-transitive) dependency to build.gradle for the Hibernate 4 GORM implementation package.
(I determined the package and version by looking in the local gradle files cache but gradle dependencies would also have worked.)
Added to build.gradle:
compile 'org.grails:grails-datastore-gorm-hibernate4:5.0.0.RC2'`
This allows access to the internal API, then the above method still works.
NB. The GORM developers also advise that there is existing GORM API for this, via the PersistentEntity and MappingContext classes without using GrailsDomainClass.

Intellij IDEA + Groovy + better static validation?

I have a method in a Grails service:
void methodA(Car car) { }
and a second method in the same class calling this method:
void methodB() {
methodA("A string")
}
But intellij doesnt even warn for this clearly incorrect usage.
I understand that a methodA can be injected with a String signature, but is there a way to make Intellij act or expect less dynamic behavior?
It would be nice to code statically with Groovy yet continue to have some kind of flag.
It would be a real downer if one has to choose so drastically between Java and Groovy.
I am using Grails 2.3.7, and I believe it is using Groovy 2.x.y
I am using IntelliJ IDEAD 12.1.6 and it does provide a warning for your example:
On the Idea Groovy Plugin page it states the following:
Inapplicable method calls marked as warnings
Do you have that plugin installed/enabled? (check under file->settings->plugins)

Grails URLMappings

I have a plugin that relies on a custom url mapping. When i install the plugin i need to copy the content of the UrlMappings.groovy of the plugin and merge it with the one in the application where the plugin is installed
I would like however to register these url mappings directly into the grails framework without copying the content into the application itself. I don't want the user to change these mappings as they are core to how the plugins works.
Anyone can give me hints where to venture to achieve that.
Thank you
-ken
Create another file in grails-app/config/ with a name ending in UrlMappings.groovy and put the customized mappings in there, for example myUrlMappings.groovy
Seems like i need to interface with UrlMappingsHolderFactoryBean directly to be able to do that. I was hoping that there might be an easier way to do that. The code below is taken from the UrlMappingPlugin itself, the only source that i found to help me solve my problem.
if (application.isUrlMappingsClass(event.source)) {
application.addArtefact(UrlMappingsArtefactHandler.TYPE, event.source)
BeanBuilder beans = beans {
grailsUrlMappingsHolderBean(UrlMappingsHolderFactoryBean) {
grailsApplication = application
}
}
ApplicationContext appCtx = event.ctx
beans.registerBeans(appCtx)
HotSwappableTargetSource ts = appCtx.getBean("urlMappingsTargetSource")
ts.swap appCtx.getBean("grailsUrlMappingsHolderBean")
}
Personally I use Java approach and inject mappings form plugin (I have only one plugin for that).
But generally my approach is following:
1.App
class UrlMappings {
static mappings = DimaURLMappings.getMappings()
}
2.Plugin (called "Dima")
class DimaURLMappings {
static def getMappings(){
return {
//Mappings here
}
}
}
Yes I need to add it manually, but on the other hand it's quite obvious where application gets that mappings, and there are no magic.
I use it in such way because I have few applications that use my plugin. If you have few plugins with mappings you will just need to merge them I think it is not hard. you could also return closure from plugin. But don't forget to change "delegate" in application.

Load application class from plugin

In a Grails 1.1 plugin, I'm trying to load a class from the main application using the following code:
class MyClass {
static Map getCustomConfig(String configName){
return new ConfigSlurper().
parse(ApplicationHolder.application.classLoader.loadClass(configName))
}
}
Where configName is the name of the class in $MAIN_APP/grails-app/conf containing the configuration info. However, when the code above runs within a unit test applicationHolder.application returns null, causing the method above to throw a NullPointerException. A Grails JIRA issue was created for this problem, but it has been marked as fixed despite the fact that problem appears to still exist.
I know that within the plugin descriptor class I can access the main application (an instance of GrailsApplication) via the implicit application variable. But the code shown above is in not in the plugin descriptor.
Is there a way that I can load a class from the main application within a plugin (but outside the plugin descriptor)?
Thanks,
Don
It turns out there are 2 possible answers.
The Right Answer
GrailsApplication is not available in unit tests, so for the code above to work it should be an integration test
The Hack that Works
Change
parse(ApplicationHolder.application.classLoader.loadClass(configName))
to
parse(MyClass.classLoader.loadClass(configName))

Resources