Today I have been inspired by reading I Fought The Gorm to blog something. So I will blog to share how I use JDepend in an ANT target to fail the build if a package cycle is detected (yes I really hate circular dependencies).

The basic logic of what the target does is:

  • Run JDepend to generate the XML data
  • Generate an HTML report
  • Run XSL to detect cycles in the XML data
  • Fail if cycles have been found.

The ANT target is:

  <target name="jdepend" depends="-init"
          description="Run JDepend to detect cycles"
          >
    <!-- Run JDepend to collect data -->
    <mkdir dir="${mother.target}/jdepend"/>
    <jdepend outputfile="${mother.target}/jdepend/mldef-jdepend.xml"
             format="xml"
             >
      <exclude name="java.*"/>
      <exclude name="javax.*"/>

      <classespath>
        <pathelement location="${mother.target}/dist/shared-${build.revision}.jar"/>
        <pathelement location="${mother.target}/dist/datareceipt-DO-NOT-USE-${build.revision}.jar"/>
        <pathelement location="${mother.target}/dist/webapp-DO-NOT-USE-${build.revision}.jar"/>
      </classespath>
    </jdepend>

    <!-- Generate HTML report -->
    <xslt in="${mother.target}/jdepend/mldef-jdepend.xml"
          out="${mother.target}/jdepend/mldef-jdepend.html"
          style="${ant.home}/etc/jdepend.xsl"
          />

    <!-- Detect if cycles -->
    <xslt in="${mother.target}/jdepend/mldef-jdepend.xml"
          out="${mother.target}/jdepend/cycle-check.txt"
          style="${project.root}/build-stuff/ant/jdepend-cycles-check.xsl"
          />

    <!-- Fail if cycles -->
    <fail message="There are cycles in the packages, see ${mother.target}/jdepend/mldef-jdepend.html"
          >
      <condition>
        <length file="${mother.target}/jdepend/cycle-check.txt"
                when="gt" length="0"
                />
      </condition>
    </fail>

  </target>

The contents of jdepend-cycles-check.xsl is:

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      >
      <xsl:output method="text" indent="no"/>

      <xsl:template match="/JDepend">
        <xsl:apply-templates select="Cycles/Package"/>
      </xsl:template>

      <xsl:template match="Cycles/Package">
    Cycle involving <xsl:value-of select="@Name"/>
      </xsl:template>
    </xsl:stylesheet>