spring-gradle-plugins / dependency-management-plugin

A Gradle plugin that provides Maven-like dependency management functionality
692 stars 87 forks source link

Builds fails with "Cannot configure the 'publishing' extension after it has been accessed" when dependencyManagement.importedProperties is used #158

Closed xjarkrof closed 7 years ago

xjarkrof commented 7 years ago

gradle: 3.4.1 dependency-management: 1.0.1.RELEASE

using plug-in 'maven-publish' and 'dependency-management' together seems to cause:

A problem occurred evaluating project '"xxxxx'. Cannot configure the 'publishing' extension after it has been accessed.

org.gradle.api.InvalidUserDataException: Cannot configure the 'publishing' extension after it has been accessed.
        at org.gradle.api.internal.plugins.ExtensionsStorage$DeferredConfigurableExtensionHolder.configureLater(ExtensionsStorage.java:174)
        at org.gradle.api.internal.plugins.ExtensionsStorage$DeferredConfigurableExtensionHolder.configure(ExtensionsStorage.java:168)
        at org.gradle.api.internal.plugins.ExtensionsStorage.configureExtension(ExtensionsStorage.java:73)
        at org.gradle.api.internal.plugins.DefaultConvention.configure(DefaultConvention.java:129)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.configurePublishingExtension(DependencyManagementPlugin.java:90)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.access$100(DependencyManagementPlugin.java:37)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin$3.execute(DependencyManagementPlugin.java:83)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin$3.execute(DependencyManagementPlugin.java:79)
        at org.gradle.internal.Actions$FilteredAction.execute(Actions.java:205)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:135)
        at org.gradle.api.internal.DefaultDomainObjectCollection.withType(DefaultDomainObjectCollection.java:158)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.configurePomCustomization(DependencyManagementPlugin.java:79)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin.access$000(DependencyManagementPlugin.java:37)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin$1.execute(DependencyManagementPlugin.java:56)
        at io.spring.gradle.dependencymanagement.DependencyManagementPlugin$1.execute(DependencyManagementPlugin.java:52)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:93)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:82)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:44)
        at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:79)
        at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:30)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy15.afterEvaluate(Unknown Source)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:82)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.doConfigure(LifecycleProjectEvaluator.java:76)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.access$000(LifecycleProjectEvaluator.java:33)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:53)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:50)
        at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:50)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:599)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:125)
        at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:38)
        at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuildAction.execute(DefaultGradleLauncher.java:233)
        at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuildAction.execute(DefaultGradleLauncher.java:230)
        at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:160)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
        at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:49)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:31)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

WIthout maven-publish plugin: A problem occurred evaluating project ':xxxxx'. Could not find method publishing() for arguments [build_2710vfttb1cmod0gw9b3ody10$_run_closure12@596e6225] on project 'xxxx' of type org.gradle.api.Project.

Order of the plug-ins seems to be irrelevant (both orders causes 'accessing' issue).

wilkinsona commented 7 years ago

There's a test that verifies this works with a basic build. The problem is almost certainly in your build.gradle or another plugin you are using. If you'd like me to spend some time helping to track that down you'll need to spend some time providing a sample that reproduces the problem.

xjarkrof commented 7 years ago

Basically here is build.gradle:

buildscript {
    ext {
        springBootVersion = '1.5.2.RELEASE'
    }

    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
        classpath 'com.craigburke.gradle:client-dependencies:1.3.1'
    }
}

plugins {
    id "com.palantir.docker" version "0.12.0"
    id "com.palantir.docker-run" version "0.12.0"
    id 'net.ltgt.apt' version '0.9'
    //id 'maven-publish'
    id 'io.spring.dependency-management' version '1.0.1.RELEASE'
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'idea'
apply plugin: 'application'
apply plugin: 'distribution'

ext {
    mavenJarArtifactDescription = 'Authorization/authentication server.'
}

repositories {
    maven {
        https://artifactory.local/artifactory/trusteca/
    }
    mavenCentral()
}
project.archivesBaseName = 'auth-server'

ext['spring-boot.version'] = '1.5.2.RELEASE'
ext['glassfish-el.version'] = '3.0.1-b08'

configurations {
    all {
        resolutionStrategy {
            force 'org.jboss.logging:jboss-logging:3.3.0.Final'
            force 'com.fasterxml:classmate:1.3.1'
            force 'xml-apis:xml-apis:1.4.01'
            force 'org.ow2.asm:asm-commons:5.0.3'
            force 'org.javassist:javassist:3.20.0-GA'
            force 'org.objenesis:objenesis:2.4'
        }
    }
}

ext {
    isSnapshot = version.toString().toUpperCase().endsWith("-SNAPSHOT")
    targetRepo = isSnapshot ? 'snapshots/' : 'releases/'

    targetRepoURL = 'https://artifactory.local/artifactory/' + targetRepo
}
dependencyManagement {
    imports {
        mavenBom("org.springframework.boot:spring-boot-dependencies:${project['spring-boot.version']}") {
            bomProperties ([
                'hibernate.version'             : '5.2.8.Final',
                'hibernate-validator.version'   : '5.4.0.Final',
                'log4j3.version'                : '2.8.1',
                'postgresql.version'            : '42.0.0',
                'ehcache3.version'              : '3.3.0',
                'mapstruct.version'             : '1.1.0.FINAL'
            ])
        }
    }

    dependencies {
        // Lombok
        dependency 'org.projectlombok:lombok:1.16.12'

        // hibernate jpa model generator
        dependency "org.hibernate:hibernate-jpamodelgen:${importedProperties['hibernate.version']}"

        // no entity-manager in hibernate 5.2.xx
        dependency ("org.springframework.boot:spring-boot-starter-data-jpa:${project['spring-boot.version']}") {
            exclude 'org.hibernate:hibernate-entitymanager'
        }

        // JWT support
        dependency 'com.nimbusds:nimbus-jose-jwt:4.34.2'

        // mapstruct
        dependency("org.mapstruct:mapstruct-processor:${importedProperties['mapstruct.version']}")
        dependency("org.mapstruct:mapstruct-jdk8:${importedProperties['mapstruct.version']}")

        // spring support
        dependency('org.springframework.security:spring-security-jwt:1.0.0.RELEASE')

        // javax specs
        dependency('javax.inject:javax.inject:1')

        // Hikari CP
        dependency("com.zaxxer:HikariCP:${importedProperties['hikaricp.version']}") {
            exclude(module: 'tools')
        }

    }
}

dependencies {
    compileOnly('org.projectlombok:lombok')
    compileOnly('org.hibernate:hibernate-jpamodelgen')
    compileOnly('org.mapstruct:mapstruct-processor')

    compile('org.springframework.boot:spring-boot-starter-web',
            'org.springframework.boot:spring-boot-starter-security',
            'org.springframework.boot:spring-boot-starter-logging',
            'org.springframework.boot:spring-boot-starter-cache',
            'org.springframework.boot:spring-boot-starter-jta-narayana',
            'org.springframework.security:spring-security-jwt',
            'org.springframework.security.oauth:spring-security-oauth2',
            'org.webjars:webjars-locator:0.32',
            'com.nimbusds:nimbus-jose-jwt:',
            'commons-codec:commons-codec',
            'javax.inject:javax.inject',
            'org.apache.logging.log4j:log4j-api',
            'org.mapstruct:mapstruct-jdk8',
            'javax.cache:cache-api',
            'org.ehcache:ehcache:3.2.0',
            'com.zaxxer:HikariCP:2.5.1',
            'org.bitbucket.simon_massey:thinbus-srp6a-js:1.4.0',
            'com.googlecode.libphonenumber:libphonenumber:8.0.1',
            'com.h2database:h2:1.4.193',
            'org.bouncycastle:bcprov-jdk15on:1.56',
            'org.passay:passay:1.2.0',
            'javax.validation:validation-api',
            'commons-validator:commons-validator:1.5.1'
    )
    compile('org.liquibase:liquibase-core:3.5.3') {
        exclude(module: 'jetty-servlet')
    }
    compile("org.springframework.boot:spring-boot-starter-data-jpa") {
        exclude (module: 'hibernate-entitymanager')
    }
    compile('com.zaxxer:HikariCP:2.5.1') {
    }
    compile('com.mattbertolini:liquibase-slf4j:2.0.0')
    compile project(':trusteca-frontend')
    runtime('org.hibernate:hibernate-validator')
    runtime("org.glassfish:javax.el:${project['glassfish-el.version']}")
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

docker {
    name project.name
    tags 'latest'
    dockerfile 'src/main/docker/Dockerfile'
    dependsOn tasks.distTar
    files 'src/main/docker/runApp.sh'
    buildArgs([JAR_NAME: project.name, JAR_VERSION: project.version])
    pull true
}

dockerRun {
    name project.name + '-container'
    image project.name
    daemonize true
}

// Deliver client resources into resource folder
task installClientApp(type: Copy,dependsOn: [':trusteca-frontend:build']){
    from project(':trusteca-frontend').file('build/dist/static/')
    into ('build/resources/main/static/')
    outputs.upToDateWhen { false }
}

processResources.dependsOn(installClientApp)

/**
 * Task for collecting all source files from project into single jar archive.
 */
task sourceJar(type: Jar, dependsOn: classes) {
    classifier = 'sources'
    baseName = "${project.archivesBaseName}-src"
    from sourceSets.main.allJava
}

/**
 * Task required for publishing java doc artifact.
 */
task javadocZip(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

publishing {
    def effectiveArtifactoryUsername = hasProperty('artifactoryUsername') ? "$artifactoryUsername" : 'anonymous'
    def effectiveArtifactoryPassword = hasProperty('artifactoryPassword') ? "$artifactoryPassword" : ''

    repositories {
        maven {
            name 'trusteca'
            url targetRepoURL
            credentials {
                username = effectiveArtifactoryUsername
                password = effectiveArtifactoryPassword
            }
        }
    }

    publications {
        mavenJava(MavenPublication) {
            groupId 'security'
            artifactId project.name

            from components.java

            artifact sourceJar
            artifact javadocZip

            pom.withXml {
                asNode().appendNode('description', mavenJarArtifactDescription)
            }
        }
    }
}

Hope this will help (It is not maybe completely correct, I'm updating build script to integrate dependency management plug-in). Script is semi-neutralized (no real URLs to private repositories, final artifact coordinates modified and project name as well). Nevertheless project is compilable (publishing section commented out and maven-publish plug-in commented as well)

wilkinsona commented 7 years ago

Thanks.

You need to move your publishing block into afterEvaluate. That's due to the change made for #149 which is working around https://github.com/gradle/gradle/issues/1373.

I'll keep this open for now. I'd like to see if there's a better workaround

xjarkrof commented 7 years ago

Thank you, I have to wrap whole publishing block to afterEvaluate including apply plugin: 'maven-publish', otherwise I got the accessed error twice... Nevertheless after that it is working properly.

wilkinsona commented 7 years ago

As workarounds go, that's pretty gross. Interestingly, if I add similar publishing configuration to the test that I linked to above it continues to pass. It would appear that there's a more complex interaction going on here that's triggering the problem.

wilkinsona commented 7 years ago

This is sufficient to reproduce the problem:

plugins {
    id 'maven-publish'
    id 'io.spring.dependency-management' version '1.0.1.RELEASE'
    id 'java'
}

repositories {
    mavenCentral()
}

dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-dependencies:1.5.2.RELEASE'
    }
    dependencies {
        dependency("com.zaxxer:HikariCP:${importedProperties['hikaricp.version']}")
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

The key thing appears to be the use of importedProperties when configuring the Hikari dependency management. If that's not there, the problem does not occur.

wilkinsona commented 7 years ago

Ok, I now understand what's happening. The underlying cause is a call to project.getProperties(). This has the side-effect of accessing all of the registered extensions and marks them as configured. As a result, the subsequent attempt to configure the publishing extension fails.

Here's a minimal reproduction:

plugins {
    id 'maven-publish'
    id 'java'
}

repositories {
    mavenCentral()
}

project.getProperties()

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

An arguably nicer workaround than the one I suggested above is to wrap the configuration of the dependency management in afterEvaluate instead. This means that the project.getProperties() call that's made as a result of accessing importedProperties doesn't occur until after the publishing configuration has been applied.

Now that I understand what's happening, this issue is somewhat similar to #56.

wilkinsona commented 7 years ago

@xjarkrof This should be fixed in the latest snapshots of the plugin so there's no need to use afterEvaluate. If you have a moment, it would be great if you could verify that it is fixed. You can get 1.0.2.BUILD-SNAPSHOT from https://repo.spring.io/plugins-snapshot.

citizenkahn commented 7 years ago

I ran into a similar issue. I used a dynamic version (if jenkins release, otherwise snapshot) and found I needed to set project version prior to apply of my plugins (probably java or maven-publish). My theory is that one of the plugins sets the publication which results in the problem if I redefine version after that point.