How to use inplace plugins with Grails 3

Before Grails 3, it was possible to use inplace plugins by declaring grails.plugin.location."my-plugin" = "../my-plugin". However Grails 3 projects are built using gradle and this approach no longer works. This example shows how to use inplace plugins with grails 3 using gradle multi module projects.

Step 1

Modify the settings.gradle file of your application as shown below. Assuming that both application and plugin are in same parent directory.

include ':my-plugin'

If plugin is not in the same directory as the application, the plugin can be included as shown below.

include ':my-plugin'
project(':my-plugin').projectDir = new File('PATH TO PLUGIN')

//Or if you want to use path relative the application.
//do it like this
include ':my-plugin'
project(':my-plugin').projectDir = new File(settingsDir, '../../my-plugin')

Step 2

Modify the application's build.gradle and add dependency on plugin module as exploded grails plugin.

grails {
    exploded = true
    plugins {
        compile project(':my-plugin')
    }
}

Note: Adding dependency as exploded plugin is required for code reloading to work. code reloading will not work, if you add the dependency as a regular gradle dependency inside dependencies block. 

That's it. and now you can build the project. Code reloading will work when running application with grails run-app command.

Make it flexible with conditional inplace

The above setup works, but it always uses the plugin as inplace. What if we want to use inplace only on developers box, but use the plugin as jar dependency on build box and when creating war. It can be done by including the inplce plugin conditionally as shown below.

File: settings.gradle

boolean inplace = "true" == System.getenv("IN_PLACE")

if(inplace) {
  include ':my-plugin'
}

File: build.gradle

boolean inplace = "true" == System.getenv("IN_PLACE")

if (inplace) {
    grails {
        plugins {
            compile project(':my-plugin')
        }
    }
}

dependencies {
 .....
 if(!inplace) compile('grais.plugins:my-plugin:xxx')
}

Now you can turn the inplace on or off with the system environment variable IN_PLACE.

export IN_PLACE=true //turn inplace on
export IN_PLACE=false //turn inplace off