SonarQube 5.2 的自定义插件产生 NoClassDefFoundError

Custom plugin for SonarQube 5.2 produces NoClassDefFoundError

我正在尝试为 SonarQube 5.2 开发一个插件,但是,当我部署该插件时,SonarQube 服务器无法启动。 日志显示 NoClassDefFound 异常,带有 Google Guava class:

Caused by: java.lang.NoClassDefFoundError: com/google/common/collect/ImmutableList
at br.gov.tcu.plugins.pmd.PmdTcuPlugin.getExtensions(PmdTcuPlugin.java:48) ~[na:na]
at org.sonar.server.plugins.ServerExtensionInstaller.installExtensions(ServerExtensionInstaller.java:55) ~[sonar-server-5.2.jar:na]
... 15 common frames omitted

当我运行mvn dependency:tree日志显示确实包含了Guava,但是打包插件后,却没有包含Guava jar:

[INFO] org.sonarsource.pmd:sonar-pmd-tcu-plugin:sonar-plugin:2.5
[INFO] +- org.sonarsource.sonarqube:sonar-plugin-api:jar:5.2:provided
[INFO] |  +- org.codehaus.woodstox:woodstox-core-lgpl:jar:4.4.0:provided
[INFO] |  |  \- javax.xml.stream:stax-api:jar:1.0-2:provided
[INFO] |  +- org.codehaus.woodstox:stax2-api:jar:3.1.4:provided
[INFO] |  \- org.codehaus.staxmate:staxmate:jar:2.0.1:provided
[INFO] +- org.sonarsource.java:sonar-java-plugin:sonar-plugin:3.7:provided
[INFO] |  +- org.sonarsource.java:java-surefire:jar:3.7:provided
[INFO] |  +- org.sonarsource.java:java-jacoco:jar:3.7:provided
[INFO] |  |  +- org.jacoco:org.jacoco.core:jar:0.7.5.201505241946:provided
[INFO] |  |  \- org.sonarsource.java:java-jacoco-previous:jar:3.7:provided
[INFO] |  +- org.sonarsource.java:java-squid:jar:3.7:provided
[INFO] |  |  +- org.sonarsource.sslr:sslr-core:jar:1.21:provided
[INFO] |  |  |  \- cglib:cglib-nodep:jar:3.1:provided
[INFO] |  |  +- org.codehaus.sonar.sslr-squid-bridge:sslr-squid-bridge:jar:2.6:provided
[INFO] |  |  \- org.ow2.asm:asm-debug-all:jar:5.0.3:provided
[INFO] |  \- org.sonarsource.java:java-checks:jar:3.7:provided
[INFO] +- org.sonarsource.xml:sonar-xml-plugin:sonar-plugin:1.4:provided
[INFO] |  +- xalan:xalan:jar:2.7.2:provided
[INFO] |  |  \- xalan:serializer:jar:2.7.2:provided
[INFO] |  +- xerces:xercesImpl:jar:2.8.1:provided
[INFO] |  |  \- xml-apis:xml-apis:jar:1.3.03:provided
[INFO] |  \- org.sonarsource.xml:xml-squid:jar:1.4:provided
[INFO] |     \- org.codehaus.sonar:sonar-colorizer:jar:4.5.4:provided
[INFO] |        \- org.codehaus.sonar:sonar-channel:jar:4.1:provided
[INFO] +- org.sonarsource.sslr-squid-bridge:sslr-squid-bridge:jar:2.6.1:compile
[INFO] |  +- org.codehaus.sonar.sslr:sslr-core:jar:1.20:compile
[INFO] |  |  +- com.google.guava:guava:jar:10.0.1:compile
[INFO] |  |  \- com.google.code.findbugs:jsr305:jar:1.3.9:compile
[INFO] |  +- org.codehaus.sonar.sslr:sslr-xpath:jar:1.20:compile
[INFO] |  +- org.picocontainer:picocontainer:jar:2.14.1:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.5.6:compile
[INFO] |  \- org.slf4j:jcl-over-slf4j:jar:1.5.6:compile
[INFO] +- net.sourceforge.pmd:pmd-core:jar:5.4.0:compile
[INFO] |  +- com.beust:jcommander:jar:1.48:compile
[INFO] |  +- jaxen:jaxen:jar:1.1.6:compile
[INFO] |  +- net.sourceforge.saxon:saxon:jar:9.1.0.8:compile
[INFO] |  +- org.apache.commons:commons-lang3:jar:3.4:compile
[INFO] |  +- org.ow2.asm:asm:jar:5.0.4:compile
[INFO] |  \- net.sourceforge.saxon:saxon:jar:dom:9.1.0.8:runtime
[INFO] +- net.sourceforge.pmd:pmd-java:jar:5.4.0:compile
[INFO] +- net.sourceforge.pmd:pmd-xml:jar:5.4.0:compile
[INFO] +- jdom:jdom:jar:1.0:compile
[INFO] +- org.apache.maven:maven-project:jar:2.0.7:test
[INFO] |  +- org.apache.maven:maven-settings:jar:2.0.7:test
[INFO] |  +- org.apache.maven:maven-profile:jar:2.0.7:test
[INFO] |  +- org.apache.maven:maven-model:jar:2.0.7:test
[INFO] |  +- org.apache.maven:maven-artifact-manager:jar:2.0.7:test
[INFO] |  |  +- org.apache.maven:maven-repository-metadata:jar:2.0.7:test
[INFO] |  |  \- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-2:test
[INFO] |  +- org.apache.maven:maven-plugin-registry:jar:2.0.7:test
[INFO] |  +- org.codehaus.plexus:plexus-utils:jar:1.4.1:test
[INFO] |  +- org.apache.maven:maven-artifact:jar:2.0.7:test
[INFO] |  \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:test
[INFO] |     \- classworlds:classworlds:jar:1.1-alpha-2:test
[INFO] +- org.sonarsource.sonarqube:sonar-testing-harness:jar:5.2:test
[INFO] |  +- org.assertj:assertj-guava:jar:1.3.1:test
[INFO] |  |  \- org.assertj:assertj-core:jar:1.7.1:test (version selected from constraint [1.7.1,1.8.0))
[INFO] |  +- com.googlecode.json-simple:json-simple:jar:1.1.1:test
[INFO] |  +- com.google.code.gson:gson:jar:2.3.1:test
[INFO] |  +- junit:junit:jar:4.12:test
[INFO] |  |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] |  +- com.tngtech.java:junit-dataprovider:jar:1.9.2:test
[INFO] |  +- org.hamcrest:hamcrest-all:jar:1.3:test
[INFO] |  +- org.mockito:mockito-core:jar:1.10.19:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.1:test
[INFO] |  \- commons-lang:commons-lang:jar:2.6:provided
[INFO] +- org.easytesting:fest-assert:jar:1.4:test
[INFO] |  \- org.easytesting:fest-util:jar:1.1.6:test
[INFO] +- org.mockito:mockito-all:jar:1.9.5:test
[INFO] \- commons-io:commons-io:jar:2.4:test

我的 pom 看起来像这样:

  <parent>
    <groupId>org.sonarsource.parent</groupId>
    <artifactId>parent</artifactId>
    <version>29</version>
  </parent>

  ...

  <properties>   
    <!-- Configuration for sonar-packaging-plugin -->
    <sonar.pluginKey>pmd-tcu</sonar.pluginKey>
    <sonar.pluginName>PMD-TCU</sonar.pluginName>
    <sonar.pluginClass>br.gov.tcu.plugins.pmd.PmdTcuPlugin</sonar.pluginClass>
    <sonar.pluginDescription><![CDATA[Analyze Java code with <a href="http://pmd.sourceforge.net/">PMD</a>.]]></sonar.pluginDescription>
    <sonar.requiresPlugin>java:${sonar-java.version}</sonar.requiresPlugin>
    <sonar.requiresPlugin>xml:${sonar-xml.version}</sonar.requiresPlugin>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.sonarsource.sonarqube</groupId>
      <artifactId>sonar-plugin-api</artifactId>
      <scope>provided</scope>
      <version>5.2</version>
    </dependency>
    <dependency>
      <groupId>org.sonarsource.java</groupId>
      <artifactId>sonar-java-plugin</artifactId>
      <type>sonar-plugin</type>
      <version>3.7</version>
      <scope>provided</scope>
      <exclusions>
        <exclusion>
            <groupId>org.codehaus.sonar</groupId>
            <artifactId>sonar-plugin-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.sonarsource.xml</groupId>
      <artifactId>sonar-xml-plugin</artifactId>
      <type>sonar-plugin</type>
      <version>1.4</version>
      <scope>provided</scope>
      <exclusions>
        <exclusion>
            <groupId>org.codehaus.sonar</groupId>
            <artifactId>sonar-plugin-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.sonarsource.sslr-squid-bridge</groupId>
      <artifactId>sslr-squid-bridge</artifactId>
      <version>2.6.1</version>
      <exclusions>
        <exclusion>
            <groupId>org.codehaus.sonar</groupId>
            <artifactId>sonar-plugin-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    ...
  </dependencies>
  ...

你可以看到我尝试删除旧版本的sonar-plugin-api,但仍然没有用。

我在这里错过了什么?

谢谢!

我在这里发现了问题。 问题出在 sonar-xml-plugin 的依赖层次结构中。 我不仅要排除较旧的 sonar-plugin-api,还要排除 sonar-colorizer 依赖项。

所以,为了解决这个问题,我只需要将依赖项更改为:

<dependency>
  <groupId>org.sonarsource.xml</groupId>
  <artifactId>sonar-xml-plugin</artifactId>
  <type>sonar-plugin</type>
  <version>1.4</version>
  <scope>provided</scope>
  <exclusions>
    <exclusion>
        <groupId>org.codehaus.sonar</groupId>
        <artifactId>sonar-plugin-api</artifactId>
    </exclusion>
    <exclusion>
        <groupId>org.codehaus.sonar</groupId>
        <artifactId>sonar-colorizer</artifactId>
    </exclusion>
  </exclusions>
</dependency>

随着这一变化,Guava jar 与所需的其余库打包在一起。