Encapsulating services in a plugin - grails

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.

Related

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.
}

Grails: Using "external configuration" to get a plugin's data source

I'm building a plugin that will contain sharable code and configuration for several applications. One things that I'm trying to share is the data source information. Basically I need the application to not have to define it's own data source and instead use the plugin's data source. The best way that I can think of doing this is to take advantage of the external configuration functionality that's available in Grails (http://grails.org/doc/latest/guide/conf.html#3.4%20Externalized%20Configuration). However, I'm not exactly sure how to do this. All the examples I can find online show you how to do this when using an external file on the file system somewhere. I want to use configuration files from the plugin.
According to the documentation linked to above you can specify a "config script" class to use like this:
grails.config.locations = [com.my.app.MyConfig]
This would probably work, however, I can't find documentation on what a "config script" class actually is and how to create one.
By default, the DataSource file of your plugin will not be used (it's ignored in the package stage) but you can create another file that ends with "DataSource" (eg MyPluginDataSource). This is also true for BootStrap and Config.
You will probably need to leave the application DataSource file empty.

How to access domain classes from a custom plugin to another?

I am currently working on grails project. I have created eight different plugins. Each having a set of Domain classes and other stuffs. Now, from one of my plugins, a certain Domain class needs to access a domain class from the other plugin. How will I do that? Do I have to import the domain classes from the other plugin? If so, how? or Shall I do that in BuildConfig.groovy?
Please help!
Thanks!
Simple make the plugin that need other plugin domains dependent from it in buildconfig
//buildConfig of plugins need other plugin domains
grails.project.dependency.plugins{
...
compile ':<other-plugin-name>:<other-plugin-version>'
...
}
The simply import the right package where you need it.
If you are constantly working on the depended plugin and you don't want to repackage it constantly you can connect it using grails.plugin.location instead of grails.project.dependency.plugins.
in buildConfig add
grails.plugin.location.'other-plugin-name' = "/path/to/other/plugin/folder"

Common backend Grails application

I have a Grails Application AppA. And I am planning to create a new Grails Application AppB, wherein AppB practically uses the same services and models of AppA.
How should I approach that?
Extract a Grails Application AppC which would have the common services and expose that service as a remote/web/rest service?
Extract a Groovy project ModC that will be a jar containing the common services and models and have AppA & AppB depend on ModC?
Just git clone and cherry-pick every now & then?
Other suggestions?
Note that AppA have some lazy-loaded relationship invocations (i.e. entity1.entity2.entity3.propName) & GORM invocations (i.e. Entity1.get(1L)) from the presentation layer (controllers & views) as well. Although I can probably push some of them back to the services, I'm concerned about the refactoring effort to have the relationship invocations from the view remain intact (i.e. I would need to eager loaded some associations, or create Data Transfer Objects)
The Grails way to share common functionalities, utilities and whatnot is to make a plugin that encapsulates those and install it to both projects.
A plugin can contain anything you can put in a regular Grails app -- i.e. Models, Service, Views, Controllers, config files, resources under web-app etc.
You can then either release it to an internal svn repository or just use it with package-plugin
Edit:
One way to do it while you are constantly updating the code is to have it as an inline plugin. So remove the plugin from your application.properties and add:
grails.plugin.location."name-of-plugin" = "/path/to/plugin/dir" // or "../plugin/"
This removes the necessity of reinstalling the plugin all the time. But this is for development time only.
Have you considered the option of separating your models and services (the ones used by both apps) into a plugin. I think that is the prefered way at least from what I have been following within the community.
You can take a look at this link. It is not exactly equivalent to your case, but should give you a good idea for the plugin approach.
I had this situation on a previous project and we used a plugin project to hold our common functionality and it worked really well. I don't think a jar file would work well since as far as I know you wouldn't be able to take advantage of things like auto-wiring dependency injection of services, the domain/GORM/dynamic finders on domain objects, etc.
I think I would put the functionality into a separate jar and use it in the two applications (so your suggestion no 2). I wouldn't make a new application (suggestion 1) because you just need some services not a whole web application, and I wouldn't do suggestion 3 because the services wouldn't be as reusable as with suggestion 2.

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