La tarea de pastoreo personalizada que accede al nivel superior falla con "El constructor ... debe ser anotado con @Inject"

Estoy tratando de crear una tarea de pastoreo reutilizable que acceda a algo desde el nivel superior. Esto funciona:

val foo = 42

tasks.register("foosimple") {
    println(foo)
}

Pero usando un ejemplo modificado Desarrollar tipos de tareas de grado personalizados no:

open class Foo : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}
tasks.register("foo")

que falla con:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'keycloak-spi'.
> Could not create task ':foo'.
   > Could not create task of type 'Foo'.
      > The constructor for type Build_gradle.Foo should be annotated with @Inject.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

¿Puede alguien echar luz sobre lo que estoy haciendo mal aquí? Si sustituyo foo()'s content with println(42) funciona, por supuesto. Pero en realidad # para acceder a algo desde el nivel superior...

Más detalles

--stacktrace no me fue útil:

* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'keycloak-spi'.
        at org.gradle.execution.TaskNameResolver.getExistingTask(TaskNameResolver.java:116)
        at org.gradle.execution.TaskNameResolver.access$000(TaskNameResolver.java:32)
        at org.gradle.execution.TaskNameResolver$MultiProjectTaskSelectionResult.collect(TaskNameResolver.java:177)
        at org.gradle.execution.TaskNameResolver$MultiProjectTaskSelectionResult.collectTasks(TaskNameResolver.java:169)
        at org.gradle.execution.TaskNameResolver.selectWithName(TaskNameResolver.java:55)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:104)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:82)
        at org.gradle.execution.commandline.CommandLineTaskParser.parseTasks(CommandLineTaskParser.java:42)

Por lo tanto, intenté añadir un @Inject anotación en el constructor una orden, pero aparentemente, como yo, el gris no sabe @Inject:

open class Foo @Inject constructor()  : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}

que falla con:

Line 70: class Foo @Inject constructor() {}
                  ^ Unresolved reference: Inject

Esta fue la única sugerencia de Intellij:

open class Foo @javax.inject.Inject constructor()  : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}

Ahora falla con:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'keycloak-spi'.
> Could not create task ':foo'.
   > Could not create task of type 'Foo'.
      > 0

Así que ahora acepta el @Inject anotación, pero todavía no funciona. Ahora me rindo y les pregunto...

Pregunta hecha hace 3 años, 4 meses, 28 días - Por devdynamox


3 Respuestas:

  • Kotlin compilador añade en secreto un parámetro generado Foo constructor cada vez que utiliza variables del script de construcción. Ese parámetro es una referencia al script de compilación adjunto.

    Como resultado, la clase de tarea no tiene constructores sin parámetro y Gradle asume que la inyección de dependencia debe comenzar. Pero no puede como constructor generado Foo(BuildScript_XXX) no @Inject anotación.

    Si desea utilizar variables de script en su tarea debe utilizar propiedades de entrada, por ejemplo:

    val foo = 42
    
    open class Foo : DefaultTask() {
        @Input
        var fooToPrint: Int = 0
    
        @TaskAction
        fun foo() {
            println(fooToPrint)
        }
    }
    tasks.register("foo") {
        fooToPrint = foo
    }
    

    Respondida el Dec 18, 2020 a las 16:17 - por debugduke

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás viendo está relacionado con la forma en que estás creando tu tarea personalizada en Gradle. La anotación @Inject se utiliza para indicar a Dagger u otros frameworks de inyección de dependencias que deben usar ese constructor para instanciar la clase.

    En el caso de Gradle, no necesitas usar la anotación @Inject en el constructor de tu tarea personalizada. En su lugar, puedes hacer lo siguiente:

    kotlin
    open class Foo : DefaultTask() {
    
        init {
            group = "custom"
            description = "This is a custom task"
        }
    
        @TaskAction
        fun foo() {
            val fooValue = project.property("foo")
            println(fooValue)
        }
    }
    
    tasks.register("foo", Foo::class)
    

    En este ejemplo, estamos definiendo una tarea personalizada llamada Foo que extiende de DefaultTask. En el método foo(), accedemos a la propiedad foo del proyecto utilizando project.property("foo") en lugar de intentar acceder directamente a la variable foo.

    Al registrar la tarea, debes pasar la referencia a la clase Foo::class en lugar de solo el nombre de la tarea. De esta manera, Gradle podrá instanciar tu clase correctamente cuando se ejecute la tarea.

    Espero que esta solución te ayude a resolver el problema. ¡Déjame saber si tienes alguna otra duda!

    Respondida el Dec 19, 2020 a las 16:14 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema es que estás intentando acceder a la variable foo desde dentro de la tarea personalizada, pero esta variable no está definida dentro del alcance de la tarea.

    Para resolver este problema, puedes pasar la variable foo a la tarea como una entrada. Aquí tienes un ejemplo de cómo puedes hacerlo:

    kotlin
    import org.gradle.api.DefaultTask
    import org.gradle.api.tasks.Input
    import org.gradle.api.tasks.TaskAction
    
    class FooTask : DefaultTask() {
    
        @Input
        var foo: Int = 0
    
        @TaskAction
        fun foo() {
            println(foo)
        }
    }
    
    tasks.register("foo") {
        foo = 42
    }
    

    En este ejemplo, la variable foo se pasa a la tarea como una entrada y se puede acceder a ella desde dentro de la tarea utilizando la propiedad foo.

    Ten en cuenta que también es necesario anotar la variable foo con @Input para indicar que es una entrada de la tarea.

    Respondida el Dec 19, 2020 a las 16:25 - por Gemini

    Votos positivos: 0 | Votos negativos: 0