Integration of jQAssistant into a Spring Boot project which is built using Apache Maven.

Note
This tutorial has been written for jQAssistant 1.4.0

1. Prerequisites

2. Overview

jQAssistant comes with a plugin for Spring based applications that provides rules for enforcing best practices, e.g.

  • allowed dependencies between Controllers, Services and Repositories

  • correct usage of transactional methods

  • enforcing constructor injection instead of field injection.

  • …​

Detected violations will be printed as warnings at the end of the build or might even break it if required.

The steps in this tutorial illustrate:

3. jQAssistant Maven Plugin

jQAssistant runs as part of the build process and therefore needs to be integrated as Maven plugin. This is done by adding the following setup to the build/plugins section of the file pom.xml:

pom.xml
<plugin>
    <groupId>com.buschmais.jqassistant</groupId>
    <artifactId>jqassistant-maven-plugin</artifactId>
    <version>${jqassistant.version}</version>
    <executions>
        <execution>
            <id>default-cli</id>
            <goals>
                <goal>scan</goal>
                <goal>analyze</goal>
            </goals>
            <configuration>
                <groups>
                    <group>spring-boot:Strict</group>
                    <!--
                    <group>spring-boot:Default</group>
                    -->
                    <group>package:Default</group>
                </groups>
                <warnOnSeverity>MINOR</warnOnSeverity>
                <failOnSeverity>MAJOR</failOnSeverity>
                <rule>
                    <defaultConceptSeverity>INFO</defaultConceptSeverity>
                </rule>
            </configuration>
        </execution>
    </executions>
</plugin>

The configuration above…​

  • activates the goals scan and analyze during a build

  • defines the rule group spring-boot:Strict to be executed during analysis (alternatively spring-boot:Default, for package:Default see Project Specific Rules)

  • sets severity thresholds for printing warnings and breaking the build to MINOR (concepts) and MAJOR (constraints)

  • sets the default severity for concepts that cannot be applied to INFO

The Maven build can be triggered as usual on the command line:

mvn clean install
Note
The default severity of concepts is MINOR and therefore the default setup of jQAssistant would issue a warning for each concept that could not be applied (e.g. if there are @Configuration annotated beans present in the code). For this reason this configuration sets the default concept severity to INFO.

4. Pre-Defined Rules

The setup above activates the pre-defined group spring-boot:Strict that provides recommended constraints for the structure and architecture of the project.

Executing the goal effective-rules on the command line using

mvn jqassistant:effective-rules

prints a summary of the activated rules including their descriptions:

[INFO] Groups [7]
[INFO]   "spring-boot:Default"
[INFO]   "spring-boot:Strict"
[INFO]   "spring-component:Default"
[INFO]   "spring-component:Strict"
[INFO]   "spring-injection:Default"
[INFO]   "spring-injection:Strict"
[INFO]   "spring-transaction:Default"
[INFO] Constraints [15]
[INFO]   "spring-boot:AllTypesInApplicationPackage" - All types of of a Spring Boot application must be located in the same package or a sub-package of
            the application class.

[INFO]   "spring-component:ControllerMustOnlyDependOnServicesRepositoriesOrComponents" - A Spring controller can only have dependencies to other Spring components that are services or
            repositories.
...
Tip
There is also a pre-defined group activating a smalle and less strict set of rules. For using it just replace spring-boot:Strict with spring-boot:Default in your pom.xml (see above). For a detailed description of available concepts and constraints refer to the plugin documentation.

5. Project Specific Rules

The concepts defined by the Spring plugin are also a good base for project specific rules. Such rules must be located in the directory /jqassistant and can be written either in XML or Asciidoc files.

The latter is recommended and used in the following example. It defines:

  • a group package:Default including the constraint `package:ServicePackage┬┤

  • the constraint package:ServicePackage that ensures that Spring services (i.e. classes annotated with @Service) are located in packages named service

jqassistant/package.adoc
[[package:Default]]
[role=group,includesConstraints="package:ServicePackage"]
== Package Rules

[[package:ServicePackage]]
[source,cypher,role=constraint,requiresConcepts="spring-component:Service"]
.Spring Services must be located in packages named `service`.
----
MATCH
  (package:Package)-[:CONTAINS]->(service:Spring:Service)
WHERE
  package.name <> "service"
RETURN
  package as WrongPackage, collect(service) as ServicesInWrongPackage
----

Finally the group package:Default must be activated, therefore the comment for this group in the file pom.xml (see above) must be removed.

The project can be built and verified by running the following command:

mvn clean install

6. Resources