Control the scope of your Maven dependencies

Control the scope of your Maven dependencies

2 Kommentare zu Control the scope of your Maven dependencies

Dependency management is one of the most powerful Maven features, just add

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.6.Final</version>
</dependency>

to your pom.xml and Maven will fetch all the required artifacts (APIs, implementations, required libraries, etc.) for getting started with JPA and Hibernate – no need to care about it. Really?

If you’re deploying your application as a WAR or EAR file to an application server (e.g. JBoss) you’ll need these dependencies only at compile time – at runtime they are provided by the application server. Therefore Maven offers the option of specifying so called scopes for dependencies – „provided“ is one of them. In daily work it can often be noticed that developers add dependencies to Maven descriptors without caring about the correct scope. Uncontrolled growth of EAR/WAR files is just one effect but there might also be unexpected errors at runtime because classes are loaded from JAR files which just shouldn’t be there.
jQAssistant allows controlling the scope of dependencies. Let’s create a quite common rule: All dependencies to JUnit must be declared with scope ‚test‘:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope> <!-- The scope for this dependency -->
</dependency>

Thus JUnit will not be packaged into whatever we distribute to our production system. The constraint would be defined as follows:

<constraint id="test:JUnitScope">
    <description>All dependencies to JUnit must be declared with scope 'test'.</description>
    <cypher><![CDATA[
        MATCH
          (module:Maven:Project)-[:CREATES]->(artifact:Artifact),
          (artifact)-[dependency:DEPENDS_ON]->(junitArtifact:Artifact)
        WHERE
          junitArtifact.group="junit"
          and junitArtifact.name="junit"
          and not dependency.scope in ['test'] // more allowed scopes may be specified here.
        RETURN
          module.fqn
    ]]></cypher>
</constraint>

Note an important detail of the data model: the dependency which provides the property „scope“ is defined between artifacts and not between Maven projects as one could expect. The reason is that a Maven project may create more than one artifact which can be installed or deployed and which can have different depencencies, e.g. a main (which is the default) and a test artifact.

About the author:

@dirkmahler

2 Comments

  1. Michael Hunger  - 2. Oktober 2014 - 9:04

    Would be cool to have a `fqn` on `:Artifact` too, so you can do

    WHERE junit.fqn = „junit:junit“

    which can be indexed for fast lookups.

    • Dirk Mahler  - 2. Oktober 2014 - 9:17

      Artifact already provides a fqn which is indexed. But beside group and name it also contains type and version – the latter one shouldn’t be part of the constraint. The only way would be to work with a regular expression here but this prevents index lookups:

      WHERE junit.fqn =~ „junit:junit:.*“

Leave a comment

Back to Top