How to handle Closure in Gradle 9 for Groovy DSL support?

I try to make my plugin (written in Java) compatible with the coming Gradle 9. In Gradle 9 the class org.gradle.util.ConfigureUtil was removed.

For Groovy DSL support I have many code like:

    public void xyz( Closure<MyXyz> closure ) {
        this.xyz= ConfigureUtil.configure( closure, new MyXyz() );
    }

    public void notarization( Action<? super MyXyz> action ) {
        this.xyz = new MyXyz();
        action.execute(this.xyz);
    }

I know that Action should be favoured over Closure, but I can’t break the scripts from thousand customers. What is the replacement for ConfigureUtil?

I look into the class ClosureBackedAction. There is the note: Deprecated. Will be removed in Gradle 9.0.

The I found Object configure(Object object, Closure closure). Is this now the recommended solution? This can look like:

    public void xyz( Closure<MyXyz> closure ) {
        this.xyz= new MyXyz();
        getProject().configure( this.xyz, closure );
    }

Or is there another recommended solution that will work in the future?

Why would you “break the scripts from thousand customers”?

If someone built a binary plugin using that API, it might break if you replace one by the other. But usage on build scripts should be the same and work the same, shouldn’t they?

Why would you “break the scripts from thousand customers”?

Since starting of the plugin (thinking Gradle 2.x) there was the syntax with Closure for the Groovy DSL syntax. Later the action syntax was added. If we remove the Closure API from the plugin and support only the new Action API then all the scripts that use the DSL syntax will be break.

Please read my last comment again, still the same question

If I remove the methods with Closure parameter from the “binary” plugin then in the scripts with Groovy syntax it does not work anymore. I does not understand your question over a binary plugin. All plugins are binary. My question is about a plugin which is hosted at https://plugins.gradle.org/.

Closure syntax:

xyy {
    name = 'foobar'
}

Action syntax:

xyz( myXyz -> {
  myXyz.name = 'foobar'
}

But I does not wand discuss the different syntax. I want to know what are the best to handle it in the future.

But I does not wand discuss the different syntax. I want to know what are the best to handle it in the future.

But discussing the syntax is my point. I’m pretty sure the syntax should be the same in Groovy DSL, whether it is Closure or Action, so there should but be a breakage when talking about build scripts. I cannot technically verify right now though, as I’m on vacation without computer at hand.

The binary plugin I referred to is not your plugin, but other plugins that use / configure your plugin, so are compiled against the Closure API.

I had test it. I had remove all methods with Closure syntax. Only the action syntax was available. And there come errors like no method xyz found …Closure… We use Gradle 8.3 or equals on our build system.

Can you show an MCVE that shows that?
I just verified in a Codespaces workspace that it is like I said, so there must be some detail you omitted or similar.

No, I can’t give an MCVE. I have try it locally and then I have see the errors. I have all reverted before I checkin. The project is GitHub - i-net-software/SetupBuilder: Gradle plugin for building setups for different platforms.

Since which Gradle version there should there no difference between Closure or Action?

Since like always. (Just tried with 4.10.3)
The import part is, that you do not instantiate the class yourself but let Gradle instantiate it.
If you don’t do that it does not work.
But as long as Gradle instantiates, it adds some magic.

One for example is, that it makes the instances ExtensionAware whether you explicitly declare it with implements or not, so you can always cast to ExtensionAware and add extensions to the instances, thus I’d always explicitly declare the ExtensionAware anyway.

Another example is exactly your case, if there is a method that takes an Action but no overload for Closure it automatically adds a Closure overload on-the-fly that delegates to the Action one, so that in Groovy DSL the syntax works like you are used to.