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.