Possible to pre-configure Grails plugins from (chained) downstream plugins? - grails

Say I have a grails-master plugin that itself contains a (chained) "sub-plugin" called grails-widget. The master plugin pulls in the chained plugin like so:
// grails-master's BuildConfig.groovy:
plugins {
compile ':widget:1.0.5' // or whatever
}
This way, anytime a Grails app includes grails-master as a dependency, both master and chained plugins get pulled in.
Now let's say that the chained grails-widget plugin requires configuration. Let's say that if an app requires grails-widget directly (sans the master), then one must configure the plugin from inside the Grails app's Config.groovy like so:
grails.plugin.widget.fizz=1
grails.plugin.widget.buzz='YES'
... etc.
Here's what I'd like to accomplish, if at all possible:
If a Grails app just lists grails-master as a dependency, then the master pulls in grails-widget but provides default values for its fizz and buzz properties. This way, when the app declares grails-master, they do not need to define the above properties in its Config.groovy.
Again, if a Grails app just lists grails-master as a dependency, then although grails-master will (somehow, automagically) provide defaults for fizz and buzz, the app developer can still choose to define them in their app's Config.groovy. In this case, the app-defined values for fizz and buzz will override the defaults set back in grails-master.
Finally if the developer only lists grails-master as a dep, it would be nice to allow the app developer to disable the use of the (chained) grails-widget plugin altogether. Hence, anything the plugin does at app startup would not occur.
Are these items possible? If so, how could I accomplish them? If not, why?

Yes you can accomplish that. Default configs can be added when the master plugin is installed. Manually you can do as a post initialization configuration in doWithApplicationContext. But there is a convenient plugin-config plugin which can do that for you. Add this plugin to master plugin and set up default values for the widget plugin. The doc for plugin is self-explanatory. If not, I can add an example.
Any config provided by the plugin can be overridden in application's Config.groovy. Application's config is initialized in the end (after all plugins are initialized). So you can definitely override the default config which you would have setup from step 1 above.
You can exclude widget plugin from the master plugin when required, in application's BuildConfig.
Example:
//BuildConfig in application
plugins {
compile(':master:0.1') {
//exclusion based on some logic at build/compile time
if(some logic satisfied) {
excludes 'widget'
}
}
}

Related

Execute plugin functionality after application config/startup

I'm developing a grails plugin, which I would like to send an email after the application's Config.groovy has been processed. (For one reason, that the Config.groovy - or other external configuration file - will have all the config I need for emails.)
I attempted a MyPluginBootStrap.groovy, however this got executed before the applications configuration (and indeed, its BootStrap.groovy). And it seems all the normal plugin onXXX() hooks are executed before the application startup.
My next thought is simply to tell people that they need to manually call a method in the plugin to trigger the functionality. So, they'd potentially add a call to their BootStrap.groovy. But I want it more automatic.
Ideally I'd like things to work as follows:
A developer adds the plugin to their BuildConfig.groovy;
A developer specifies some configuration in their Config.groovy - or external config; and then
When you app starts, the email gets sent - without them having to do anything more than item 1 and 2 above.
Is this possible?

How to run GrailsPlugin.groovy during 'war'

Grails Version: 2.3.11
Dear all,
I have a plugin where in the doWithSpring Closure I use some central resources to build up a properties file in the war that is then used during runtime. The central resources will only be available when building the war in a production environment so putting the files into the /src (for example) of the plugin is out of the question.
Currently my plugin will work in a run-app and testing environment, but the file is never created when 'war' is run.
I have tried setting the scopes variable to include war but this doesn't appear to be doing much (or at least, is not invoking the doWithSpring closure). Does anyone know how to do this or if it is possible?
All of the logic is within doWithSpring (which delegates to a class) but that is only using the classLoader and grailsApplication so if there is anywhere else I can do this that will also be great.
Thanks
Adam
Okay, the best approach is to hook into the events with your plugin. I highly recommend you read the documentation on events. It's as simple as creating the correct file within your plugin and placing your code within the associated closure.
For example:
scripts/_Events.groovy
eventCreateWarStart = { warName, stagingDir ->
// place your code here.
}

How can a Grails plugin modify the app's default mappings/constraints config?

I'm creating a Grails plugin which will modify the value of the following config property:
grails.gorm.default.constraints
The problem is that by the time my plugin descriptor starts running (doWithSpring) if the Grails application that uses the plugin had an existing value for the default constraints property, it would have been already executed.
I'd like my plugin to modify the value of the default constraints before Grails begins executing it so that the constraints I'm adding will also be included. The default constraints closure seems to get executed multiple times during Grails app startup.
I've tried a few approaches:
Use the platform-core plugin which this post talks about: How to configure a grails plugin from another grails plugin.
Problem there is similar: the Grails app's default constraints block is executed at least once before the plugin's doWithConfig begins to run.
(Hackish) Modify Grails app to include a FooConfig.groovy in its "locations", a file which exists in the plugin's grails-app/conf/ dir and thus accessible on the classpath (see below).
Problem: Hackish, still working through it but might be my only option.
grails.config.locations = ["classpath:FooConfig.class"] // Yes, *.class

Encapsulating services in a plugin

I get the idea in Grails Services from a plugin can be injected into applications that use that plugin. But, what if don't want some services to be injectable, you only want the plugin to know about them.
Is there anyway to achieve this?
You can achieve it using pluginExcludes property in *GrailsPlugin.groovy script:
def pluginExcludes = [
"grails-app/services/com/my/package/MyService.groovy",
]
This way the service won't be included into packed plugin *.zip file.
One drawback is that this approach does not work for in-place plugins - see http://jira.grails.org/browse/GRAILS-5404
In-place plugins are the ones that are loaded from file system using the path specified:
grails.plugin.location.shiro = "/home/dilbert/dev/plugins/grails-shiro"
All Grails services are exposed as Spring beans. These beans are available through the application context, and thus the containing application that uses the plugin. There really isn't a way to 'protect' these services from being used.

Specifying order of plugins in Grails

My grails application depends on several grails plugins that append and entries to web.xml
The problem is I need to control the order the plugins are executed. There is a particular plugin which is used for some security purposes which adds a filter in web.xml. This filter needs to be the first executed filter in web.xml Thus I would like this filter to be executed last so that I can ensure that this plugin will be appending the configurations in the first position.
I know there is a dependsOn property on the plugin class to ensure it gets executed last, but that only works if I know which plugins are going to be used in combination with this plugin. I would like this plugin to be general enough so that anyone in my company can use this plugin and know for sure that this gets executed last.
Is there any way I can ensure a particular plugin gets executed last? Either in the grails-plugin project (ie a property of the plugin class) or configuration of the grails application project.
Thanks,
Does the grails application install plugins using the install-plugin command? If so, try declaring them in BuildConfig.groovy instead.
plugins {
runtime ':weceem:0.8'
runtime ':hibernate:latest.release'
}
It's possible that plugins declared here are loaded in the same order they're listed, though I haven't tested this theory.
It might be easier to find a way to make your plugin append it's filters differently to ensure they get appended to the position you want them in. I would have to see the code for the plugin if I was going to try to help solve this in that way though.

Resources