Gradle error: Cannot add extension with name 'sonarRunner', as there is an extension already registered with that name

When project B depends on project A and we invoke project A’s build from project B using the “settings.gradle” mechanism. The sonar-runner pluging fails with the following exception. Both project A and project B has the sonar-runner plugin applied.

A problem occurred evaluating script. > Cannot add extension with name ‘sonarRunner’, as there is an extension already registered with that name.

Is this a plugin bug? Since other plugins like findbug, pmd etc. works fine in similar configuration.

Thanks, PB

I don’t understand your setup. Please explain in detail, showing relevant code etc.

Note that the ‘sonar-runner’ plugin differs from all other code quality plugin in that it is only applied to the top-level project of the project hierarchy to be analyzed (typically the root project), not to every project. If you apply the plugin to project X, you have to be careful not to apply it to any one of its ancestors.

This is large enterprise setup where there are 70+ projects, with all different kinds of project types(simple java util jar, CLI, ejb, ear, war etc.) . All the projects are in flat structure as many ear/war projects pick and choose other dependent utility jars by going to something like …/my-util-jar project and building it when it needs it. Many ear projects share the common utility jar projects. In other words there is no fixed root project, as different team supporting the projects will run the build in their project which may be a utility jar project that also gets embedded into another teams ear project.

Why is sonar-runner plugin different than findbug or pmd?

Thanks, PB

Every Gradle build has a root project. (I’m talking about the lodical project hierarchy, not the physical directory structure.) More concrete information would help (‘settings.gradle’, is this one multi-project build or many single-project builds, show Sonar related code, etc.).

Why is sonar-runner plugin different than findbug or pmd?

Because Sonar can analyze project hierarchies as a whole, and this is usually the preferred approach. Of course you can also analyze projects individually. Assuming we are talking about a multi-project build, you’d achieve the latter by applying the plugin to each leaf project, but not to any parent project.

is this one multi-project build or many single-project builds

It is both many are single-project build but some are multi-project builds. Some of the multi-project builds call the single-project builds.

Assuming we are talking about a multi-project build, you’d achieve the latter by applying the plugin to each leaf project

The parent projects also have code as it may be a utility jar project say B. B java util project intern builds another project …/A as it depends on A’s jar. If I don’t put sonar-runner on parent(B) what will analyze the project B’s code?

Thanks, -PB

Some of the multi-project builds call the single-project builds.

How?

The parent projects also have code as it may be a utility jar project say B. B java util project intern builds another project …/A as it depends on A’s jar.

I can’t parse that sentence, but if you have code in parent projects (which is never required), it’s probably best to apply ‘sonar-runner’ just to the build’s root project. As I said, that’s usually best in any case.

Here is a sample workarea which contains three projects viz. project-a, project-b and project-c. In my example project-b depends on project-a, similarly project-c depends on project-a. This kind of dependencies can go two/three layers deep in our real build infrastructure. Each project can be maintained by a different teams so we must be able to run build tasks in each(project-a, project-b, project-c) project folders. Team A that owns project-a wants to see their sonar analysis for their project(project-a). Similarly team B and C that owns project b and c wants to see their sonar analysis for their projects(project-b and project-c).

.
├── project-a
│
 └── build.gradle
├── project-b
│
 ├── build.gradle
│
 └── settings.gradle
└── project-c
    ├── build.gradle
    └── settings.gradle
    $cat project-a/build.gradle
apply plugin: 'java'
apply plugin: 'sonar-runner'
    $cat project-b/build.gradle
apply plugin: 'java'
apply plugin: 'sonar-runner'
  dependencies {
     compile project(':project-a')
}
  $cat project-c/build.gradle
apply plugin: 'java'
apply plugin: 'sonar-runner'
  dependencies {
     compile project(':project-a')
}

I have uploaded a sample here(https://www.dropbox.com/s/mxbqe11dmhowu0d/gradle_sonar_issue.zip).

Thanks, PB

How many builds are these? Why is there a ‘settings.gradle’ under ‘project-b’?

These are three independent build. I should be able to run “gradle jar” in each folder.

-PB

They can’t be three independent builds, because ‘b’ and ‘c’ have a project dependency on ‘a’.

Why not? You will have to think large enterprise builds, multiple teams own different pieces/projects but there is sharing between the teams. This is not a theoretical problem, we have our enterprise build working like this. All other gradle plugins work fine in this setup, except this sonar-runner plugin.

-PB

Because it’s technically impossible. Please show the ‘settings.gradle’ files for these builds.

The settings file is already in the sample zip file I provided before. But here it is one more

$cat project-b/settings.gradle
 includeFlat 'project-a'
$cat project-c/settings.gradle
 includeFlat 'project-a'

Note: I appreciate your quick response and trying to help us out of this situation.

Thanks, PB

So you have two builds, both of which independently build ‘project-a’. And apparently some folks don’t check out b and c, and build a on its own. That complicates matters. Basically you’ll have to check in which context a is currently run (b, c, or standalone) and configure things accordingly. Something like:

  • If run standalone, apply plugin ‘sonar-runner’ * (Optional) If run via b or c, exclude project a from Sonar analysis (see Gradle User Guide for details)

The current context can be determined by, say, checking if ‘rootProject == project’.

You got it, can you please provide some code snippet how to do it.

Thanks, PB

Hi guys, I stumbled on the same issue and being very new to Gradle I must admit I have difficulties making sense from Peter’s suggestion.

Any code snippet would be much appreciated, many thanks in advance…

JM

Are you sure that you are having the same issue? It stems from using Gradle multi-project builds in a very special (and unsupported) way.

I was able to solve it by using the following code.

allprojects {
         if( rootProject == project ) {
        //Add sonar plugin to only root projects not subprojects.
        apply plugin: 'sonar-runner'
    }
        }

Hi Peter, I am not sure this is special but this is definitely multi-projects (as sibbling projects). I described my setup here : http://forums.gradle.org/gradle/topics/how_to_declare_dependent_project_that_are_not_side_by_side_built_with_jenkins

I have tinkered a bit more since my post and it seems I have a solution that works. I apply the sonarRunner plugin this way :

/* We only want to apply the sonarRunner pluggin if we are running standalone (vs as a subproject) */
if (rootProject == project) {
 apply plugin: 'sonar-runner'
}

This way when I build from Eclipse, the plugin is only loaded by the root project and when I build in jenkins (independent builds), the plugin is loaded for each build…

This all started with the problem of project directory layout in Jenkins that is different from Eclipse (projects are not “side by side” anymore in the Jenkins directory structure).

Hope this is clear enough…

Sorry, you lost me here, just for my personnal understanding, what does the “allproject” thingy means and in what file do you put it ?

Many thanks, JM