# First plugin failed to get extension properties

**URL:** <https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723>\
**Category:** Help/Discuss\
**Created:** [January 24, 2023, 12:35pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723 "2023-01-24T12:35:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mavarazo](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mavarazo/32/10195_2.png) [@mavarazo](https://discuss.gradle.org/u/mavarazo)\
**Post date:** [January 24, 2023, 12:35pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/1 "2023-01-24T12:35:03Z")

</div>

Hello, I’m try write my first plugin to capture the total buildtime and can’t figure out, why my extensions properties are always default / not set. Thanks for your advies.

GradlePlugin:

```gradle
public class GradlePlugin implements Plugin<Project> {
    
    @Override
    public void apply(final Project project) {
       final GradleExtension extension = project.getExtensions().create("gradleplugin", GradleExtension.class, project.getObjects());
        project.getLogger().lifecycle("isEnabled: " + extension.isEnabled());
        project.getLogger().lifecycle("getFoo: " + extension.getFoo());
        registerBuildService(extension, gradle);
    }

```

GradleExtension:

```gradle
public class GradleExtension {
    private final Property<Boolean> enabled;
    private final Property<String> foo;
    
    public GradleExtension(final ObjectFactory objects) {
        enabled = objects.property(Boolean.class).convention(Boolean.TRUE);
        foo = objects.property(String.class);
    }

   // getters

```

build.gradle.kts

```gradle
plugins {
    id("...gradleplugin") version "0.0.1-SNAPSHOT"
}

gradleplugin {
    foo("bar")
}

```

Output:

```gradle
> Configure project :gradle-plugin
isEnabled: true
getFoo: null
... many other tasks
BUILD SUCCESSFUL in 712ms

```

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [January 24, 2023, 12:44pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/2 "2023-01-24T12:44:29Z")

</div>

Because you register the extension and then immediately query the values and only after your apply method finishes the buildscript has a chance to set the values. Because of that you have the lazy `Property`s and wire them to other properties that you then evaluate at execution time after the buildscript has a chance to set them.

---

<div class="post-metadata">

**Author:** ![mavarazo](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mavarazo/32/10195_2.png) [@mavarazo](https://discuss.gradle.org/u/mavarazo)\
**Post date:** [January 24, 2023, 12:56pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/3 "2023-01-24T12:56:23Z")

</div>

Thanks @Vampire: I changed as suggestest the evaluation into the buildservice, but still no success

```gradle
public class GradlePlugin implements Plugin<Project> {
    
    @Override
    public void apply(final Project project) {
        final GradleExtension extension = project.getExtensions().create("gradleplugin", GradleExtension.class, project.getObjects());
        
        final GradleInternal gradle = (GradleInternal) project.getGradle();
        registerBuildService(extension, gradle);
    }

    private void registerBuildService(final GradleExtension extension, final GradleInternal gradle) {
        final BuildEventListenerRegistryInternal registry = gradle.getServices().get(BuildEventListenerRegistryInternal.class);
        final Provider<BuildService> buildServiceProvider = gradle.getSharedServices().registerIfAbsent("build-service", BuildService.class, service -> {
            service.getParameters().getEnabled().set(extension.getEnabled());
            service.getParameters().getFoo().set(extension.getFoo());
        });
        registry.onOperationCompletion(buildServiceProvider);
    }
}

```

BuildService

```gradle
public abstract class BuildService extends AbstractBuildService implements BuildService<BuildService.Params>, BuildOperationListener, AutoCloseable {
    
    public interface Params extends BuildParameters {
        Property<Boolean> getEnabled();
        Property<String> getFoo();
    }
    
    private static final Logger LOGGER = Logging.getLogger(BuildService .class);
    
    @Override
    public void close() throws Exception {
        LOGGER.lifecycle("isEnabled: " + getParameters().getEnabled().get());
        LOGGER.lifecycle("getFoo: " + getParameters().getFoo().getOrElse("unset"));
     }
}

```

Output:

```gradle
> Task :gradleplugin:assemble UP-TO-DATE
isEnabled: true
getFoo: unset

BUILD SUCCESSFUL in 346ms

```

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [January 24, 2023, 1:29pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/4 "2023-01-24T13:29:09Z")

</div>

You do various bad things with internal classes and also implement the wrong listener type.  
You should reread the [Shared Build Services](https://docs.gradle.org/current/userguide/build_services.html) documentation.  
Don’t use `GradleInternal` and `BuildEventListenerRegistryInternal` but simply inject `BuildEventsListenerRegistry`.  
Don’t implement `BuildOperationListener`, but `OperationCompletionListener`.  
Do not use `registry.onOperationCompletion`, but `registry.onTaskCompletion`.

Now your build service should probably be seen as used until the build finished and your `close` method properly be called in the end of the build and seeing the configured values.

---

<div class="post-metadata">

**Author:** ![mavarazo](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mavarazo/32/10195_2.png) [@mavarazo](https://discuss.gradle.org/u/mavarazo)\
**Post date:** [January 24, 2023, 3:33pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/5 "2023-01-24T15:33:30Z")

</div>

Thanks @Vampire, I reworked all my bad things 🙂 and it works now.  
Sadly with less info than from parameters of `BuildOperationListener`

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [January 24, 2023, 3:52pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/6 "2023-01-24T15:52:56Z")

</div>

What info do you miss?

---

<div class="post-metadata">

**Author:** ![mavarazo](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mavarazo/32/10195_2.png) [@mavarazo](https://discuss.gradle.org/u/mavarazo)\
**Post date:** [January 25, 2023, 5:26am UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/7 "2023-01-25T05:26:03Z")

</div>

Actually I’m just missing the info about when the entire task finished as `RunRootBuildWorkBuildOperationType`.  
Other things I found with `DefaultTaskSuccessResult` and `DefaultTaskSkippedResult`

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [January 25, 2023, 1:03pm UTC](https://discuss.gradle.org/t/first-plugin-failed-to-get-extension-properties/44723/8 "2023-01-25T13:03:46Z")

</div>

I see.  
I guess you just need to take the start time of the first `OperationResult` and have roughly the same information.
