How to convert DSL to Plugin code?

plugins
(Srinivas Anumala) #1

Hi,

I am trying to create custom gradle plugin which required to use Spring Boot gradle plugin.

For that I am trying to convert below DSL into Plugin code .

pluginManagement {
	repositories {
		 maven {
		   url "${customURL}"
			credentials {
				username "${user}"
				password "${password}"
			}
		}
	}
	resolutionStrategy {
		eachPlugin {
			if (requested.id.id == 'org.springframework.boot') {
				useModule "org.springframework.boot:spring-boot-gradle-plugin:${requested.version}"
			} else if (requested.id.id == 'io.spring.dependency-management') {
				useModule "io.spring.gradle:dependency-management-plugin:${requested.version}"
			}
		}
	}
}

=================================

plugins {
	id "org.springframework.boot" version '1.5.19.RELEASE'
}

Are there any suggestion on how to convert this into plugin code ?

(uklance) #2

Gradle scripts implicitly delegate to the project instance so a simple way to start is to wrap the dsl in a project.with { ... } block.

Eg

class MyPlugin implements Plugin<Project> {
   void apply(Project project) {
      project.with {
         pluginManagement {
            repositories { ... } 
            resolutionStrategy { ... } 
         }
      }
   } 
} 

Or you could explicitly call methods on the project instance instead.

Eg

class MyPlugin implements Plugin<Project> {
   void apply(Project project) {
      project.pluginManagement {
         repositories { ... } 
         resolutionStrategy { ... } 
      }
   } 
} 
(Srinivas Anumala) #3

@Lance … Any other build configuration can work using ‘project.with {}’.
I believe, PluginManagment is special and can’t be applied as you suggested.

I am getting below Error.
Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method pluginManagement() for arguments [PluginClass$_apply_closure2$_closure5@4a55f617] on root project 'plugin-test' of type org.gradle.api.Project.

I could find ‘org.gradle.plugin.management.PluginManagementSpec’ from Gradle API which can do this… However, I could not find details on how to apply PluginMangementSpec to Gradle Project or Plugin.

Update:
I can able to add buildScript (old way) using

 project.buildscript.with { }
 project.pluginManager.apply("org.springframework.boot")

However, its failing while apply spring boot plugin due to below error .

 Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id 'org.springframework.boot' not found.
    	at org.gradle.api.internal.plugins.DefaultPluginContainer.apply(DefaultPluginContainer.java:81)
(uklance) #4

I’m guessing that pluginManagement is an extension object which is added by the spring boot plugin so you’ll need to apply this first

org.gradle.api.plugins.UnknownPluginException: Plugin with id ‘org.springframework.boot’ not found

Your plugin is built by gradle and has its own dependencies. You’ll need to add spring boot as a dependency in the build.gradle for your plugin (possibly buildSrc/build.gradle)

Eg:

dependencies {
   compile 'org.springframework.boot:spring-boot-gradle-plugin:2.1.4.RELEASE' 
} 
(Srinivas Anumala) #5

I added ‘Spring Boot Plugin’ as dependency and still getting same error that Plugin Not Found or ClassNotFound. .

pluginMangement is from gradle itself… not from spring-boot plugin.

https://docs.gradle.org/current/userguide/plugins.html#sec:custom_plugin_repositories

(uklance) #6

Ah! That pluginManagement is for settings.gradle and not build.gradle. If you want to do this as a plugin you’ll need to implement Plugin<Settings> and apply the plugin in your settings.gradle instead of build.gradle

Eg:

class MyPlugin implements Plugin<Settings> {
   void apply(Settings settings) {
      settings.pluginManagement {
         repositories { ... } 
         resolutionStrategy { ... } 
      }
   } 
} 

I added ‘Spring Boot Plugin’ as dependency and still getting same error that Plugin Not Found or ClassNotFound.

You could try the class name instead of the plugin id which I looked up from here

Eg:

project.apply from: org.springframework.boot.gradle.plugin.SpringBootPlugin

Note: If you want to do stuff in both build.gradle and settings.gradle you’ll need two plugins

  • Plugin<Settings> to apply in settings.gradle
  • Plugin<Project> to apply in build.gradle
(Srinivas Anumala) #7

Can this API be useful to update Settings , instead of another Plugin for Settings?

https://docs.gradle.org/current/javadoc/org/gradle/api/invocation/Gradle.html#settingsEvaluated-org.gradle.api.Action-

(uklance) #9

By the time your Plugin<Project> is applied, you are past that event. You might as well just mutate project.gradle.settings at that point.

But I don’t suggest doing this as you’ll have ordering issues. If your plugin is applied second, the first plugin won’t “see” your settings changes.

You could do everything in a single Plugin<Settings> instead. You could use a project listener to mutate the root project (or perhaps every project).