
Your Software. Your Structures. Your Rules.
This document describes the concepts of jQAssistant and usage information. To download jQAssistant, go to Get Started.
Overview
jQAssistant is a QA tool which allows the definition and validation of project specific rules on a structural level. It is built upon the graph database Neo4j and can easily be plugged into the build process to automate detection of constraint violations and generate reports about user defined concepts and metrics.
Example use cases:
-
Enforce naming conventions, e.g. EJBs, JPA entities, test classes, packages, maven modules etc.
-
Validate dependencies between modules of your project
-
Separate API and implementation packages
-
Detect common problems like cyclic dependencies or tests without assertions
The rules are expressed in Cypher - the easy-to-learn query language of Neo4j:
MATCH
(t:Test:Method)
WHERE NOT
(t)-[:INVOKES]->(:Assert:Method)
RETURN
t AS TestWithoutAssertion
1. License
jQAssistant is contributed under GNU General Public License, v3.
2. Requirements
-
Java Runtime Environment 8 (64 bit recommended) or later (it is still possible to scan & analyze applications which have been compiled with older Java versions)
-
at least 1GB of RAM
Note
|
Adjusting memory settings can be achieved by setting the environment variables JQASSISTANT_OPTS (command line) or MAVEN_OPTS (Maven), e.g.
|
set JQASSISTANT_OPTS=-Xmx1024M set MAVEN_OPTS=-Xmx1024M
export JQASSISTANT_OPTS=-Xmx1024M export MAVEN_OPTS=-Xmx1024M
3. Quickstart
3.1. Command Line
3.1.1. Requirements
-
Java Development Kit 8 or later
-
the environment variable JQASSISTANT_OPTS can be used to provide JVM arguments:
Windowsset JQASSISTANT_OPTS=-Xmx1024M
Linuxexport JQASSISTANT_OPTS=-Xmx1024M
-
the following JVM parameters are required if
Java 16
or later is used as runtime environment:Windowsset JQASSISTANT_OPTS=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
Linuxexport JQASSISTANT_OPTS=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
3.1.2. Installation
-
Download and unpack the distribution, a directory
jqassistant-commandline-neo4jvx-version
will be created.
3.1.3. Scan
bin\jqassistant.cmd scan -f lib
bin/jqassistant.sh scan -f lib
-
The JAR files contained in the lib/ folder will be scanned.
3.1.4. Explore
bin\jqassistant.cmd server
bin/jqassistant.sh server
-
Open a browser and navigate to http://localhost:7474
-
Enter the following query in the top level area and hit Ctrl-Enter:
MATCH
(a:Artifact)-[:CONTAINS]->(t:Type)-[:DECLARES]->(m:Method)
RETURN
a.fileName as Artifact, t.fqn AS Type, count(t) AS DeclaredMethods
ORDER BY
DeclaredMethods DESC
LIMIT 20
3.2. Maven
3.2.1. Requirements
-
Maven 3.5 or later
-
Java Development Kit 8 or later
-
the environment variable MAVEN_OPTS can be used to provide JVM arguments
Windowsset MAVEN_OPTS=-Xmx1024M
Linuxexport MAVEN_OPTS=-Xmx1024M
-
the following JVM parameters are required if
Java 16
or later is used as runtime environment:Windowsset MAVEN_OPTS=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
Linuxexport MAVEN_OPTS=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
An alternative option is to place these settings into a file
.mvn/jvm.config
in the root Maven module:mvn/jvm.config--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
3.2.2. Add the plugin
Add the following lines to the parent pom.xml file of your project:
<properties>
<!-- Define your desired jQAssistant version here -->
<jqassistant.version>...</jqassistant.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>${jqassistant.version}</version>
<executions>
<execution>
<goals>
<goal>scan</goal>
<goal>analyze</goal>
</goals>
<configuration>
<failOnSeverity>MAJOR</failOnSeverity>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
3.2.3. Add a rule
Within your parent module create a directory jqassistant
and a file my-rules.adoc
:
= My Project
// Include a summary of all executed rules and their status
link:jQA:Summary[]
[[default]]
[role=group,includesConstraints="my-rules:*"]
== Default Rules
[[my-rules:TestClassName]]
[source,cypher,role=constraint,requiresConcepts="junit4:TestClass"]
----
MATCH
(t:Junit4:Test:Class)
WHERE NOT
t.name ends with "Test"
RETURN
t AS InvalidTestClass
----
== Imported Rules
// Include specific rules that have been executed and their results.
link:jQA:Rules[concepts="junit*:*"]
3.2.4. Run the build
Execute the following command from your parent module:
mvn install
The build will fail with the rule’s message if it is violated.
The HTML report generated from the Asciidoc file including all results is available from target/jqassistant/report/asciidoc/index.html
.
3.2.5. Explore your application
jQAssistant comes with an integrated Neo4j server, you can run it using
mvn jqassistant:server
-
Open a browser and navigate to http://localhost:7474
-
Enter the follwoing query in the top level area and hit Ctrl-Enter:
MATCH
(t:Type)-[:DECLARES]->(m:Method)
RETURN
t.fqn AS Type, count(t) AS DeclaredMethods
ORDER BY
DeclaredMethods DESC
LIMIT 20
4. Introduction
This chapter provides an introduction to the concepts of jQAssistant.
4.1. How it works
The basic idea behind jQAssistant is to integrate the following steps into the build process of a software system:
-
Scan the generated artifacts and store structural information about them into a database
-
Analyze the structures using rules which are represented by queries
-
Report violations
jQAssistant itself is a plugin based framework. It comes with a pre-defined set of plugins containing scanners, rules and reports but can be easily extended by custom rules or implementations.
As database an embedded instance of Neo4j Community Edition is managed and used by jQAssistant. This means that no setup or configuration of a dedicated server is required. Neo4j has been chosen because:
-
it is a mature open source graph database
-
it allows easy modelling of structural elements of a software and their relations
-
it comes with a very expressive and easy to learn query language (Cypher)
4.2. Scanner
Scanners are used to import software structures into the database. They are provided by plugins and may support several types of artifacts, e.g. Java classes, XML files or database structures. The jQAssistant framework (including the command line or Maven plugin) only provides the infrastructure to run a scan operation on a set of items, e.g. files, directories or URLs. Every active plugin decides itself if it accepts and imports a given item by checking several conditions, e.g. file name extensions or a provided scope. The latter is an extra information which provides specific context information like "java:classpath" for a directory containing Java classes or "maven:repository" for a URL.
4.3. Rules
Rules are expressed as Cypher queries and are specified either in XML or AsciiDoc files:
4.3.1. XML example
<jqassistant-rules xmlns="http://schema.jqassistant.org/rule/v1.10"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schema.jqassistant.org/rule/v1.10 https://schema.jqassistant.org/rule/jqassistant-rule-v1.10.xsd">
<group id="default">
<includeConstraint refId="my-rules:MyConstraint"/>
</group>
<concept id="my-rules:MyConcept">
<description>A human readable description of the concept.</description>
<cypher><![CDATA[
MATCH
...
WHERE
...
MERGE
...
SET
...
RETURN
...
]]></cypher>
</concept>
<concept id="my-rules:MyProvidingConcept">
<providesConcept refId="java:GeneratedType"/>
<description>A human readable description of the concept.</description>
<cypher><![CDATA[
MATCH
...
WHERE
...
SET
type:Generated
RETURN
...
]]></cypher>
</concept>
<constraint id="my-rules:MyConstraint" severity="blocker">
<requiresConcept refId="my-rules:MyConcept" />
<requiresConcept refId="java:GeneratedType" />
<description>A human readable description of the constraint.</description>
<cypher><![CDATA[
MATCH
...
WHERE
...
RETURN
...
]]></cypher>
</constraint>
</jqassistant-rules>
4.3.2. AsciiDoc example
[[my-rules:MyConcept]]
.A human readable description of the concept.
[source,cypher,role=concept]
----
MATCH
...
WHERE
...
MERGE
...
SET
...
RETURN
...
----
[[my-rules:MyConstraint]]
.A human readable description of the constraint.
[source,cypher,role=constraint,requiresConcepts="my-rules:MyConcept",severity=blocker]
----
MATCH
...
WHERE
...
RETURN
...
----
[[my-rules:MyProvidingConcept]]
.A human readable description of the concept.
[source,cypher,role=concept,providesConcepts="java:GeneratedType"]
----
MATCH
...
WHERE
...
SET
type:Generated
RETURN
...
----
[[my-rules:MyGroup]]
.A human readable description of the group.
[role=group,includesConstraints="my-rules:MyConstraint(minor),java:GeneratedType"]
== My Group
Each rule comes with an unique id (e.g. "my-rules:MyConstraint") which can be referenced by other rules. jQAssistant will take care about executing the rules in the correct order. Furthermore a human readable description shall help developers to understand the rationale behind them.
Tip
|
Despite rules are usually referenced by their id it is also possible to use the wildcards * and ? .
This is especially useful for defining groups and include all constraints that match a specific pattern, e.g. my-rules:* .
|
4.3.3. Groups
A group is a set of rules (i.e. concepts, constraints or other groups) that shall be executed together by including them with the option to overwrite their default severity. This allows to adjust analysis depth for different types of builds, e.g. a Continuous Integration build (CI) can be configured to only execute rules with low costs (i.e. execution times) whereas a report build is allowed to run for a longer time with more expensive checks.
4.3.4. Concepts
The information created by the scanner represents the structure of a software project on a raw level. Concept rules allow enriching the database with higher level information to ease the process of writing queries that check for violations (i.e. constraints) . This typically means adding labels, properties or relations.
jQAssistant comes with language and framework plugins which include general technical concepts, e.g.
-
"jpa2:Entity" provided by the JPA2 plugin adds a label "Entity" to a node if it represents a class which is annotated by "@javax.persistence.Entity".
-
"java:MethodOverrides" provided by the Java plugin adds a relation "OVERRIDES" between a method of a sub class to the super class methods it overrides.
It is recommended to use concepts to enrich the database with information which is specific for the concrete project, e.g. labels can be added to
-
package nodes representing modules of the application ("Module")
-
package nodes that represent technical layers ("UI", "EJB")
-
class nodes representing elements with a specific role ("Controller", "Model")
Note
|
Even if the primary intention of a concept is to enrich data it still must provide a return clause. If a concept returns an empty result a warning will be generated by jQAssistant. The rationale is that in such case the concept does not match the structure of the application and other rules which depend on it will probably not work as expected. |
Tip
|
The return clause of the concept shall preferably return a node/relation itself instead of an attribute of it. With this, XML and HTML reports can provide additional information about the concept. |
4.3.5. Constraints
A Constraint is a query which detects violations, e.g.
-
classes with specific roles (e.g. entity, controller, etc.) that are either located in the wrong packages or have names that do not fit defined conventions
-
invocations of methods which are deprecated and/or forbidden (e.g. constructors of java.util.Date)
-
dependencies to other modules which are not allowed
A constraint can depend on one or more concepts and usually is referenced by one or more groups.
Note
|
If a constraint returns a result jQAssistant will report an error including the provided description and information about the returned elements. This information shall help the developer to understand and fix the problem. |
4.3.6. Rule Dependencies
As shown in the snippets above concepts or constraints may define dependencies to other concepts. There are two approaches:
requiresConcept
(XML) orrequiresConcepts
(Asciidoc)-
A rule explicitly requires another concept to be executed before.
providesConcept
(XML) orprovidesConcepts
(Asciidoc)-
A concept extends another concept by adding the same labels or relationships.
The rules are referenced by their ids. jQAssistant will ensure that these rules are executed in the correct order.
Usually dependencies are expressed using requiresConcept(s)
, e.g. a constraint requires one or more specific concepts.
These concepts again might require other concepts.
There may be situation where pre-defined constraints and required concepts are defined within a plugin. In this case it can become necessary to extend such concepts with project-specific concepts, e.g. to work with generated code:
-
Constraints defined by the Spring plugin delivered with jQAssisatnt verify correct usage of dependency injection
-
These constraints exclude all Java types labeled with
:Type:Generated
and therefore require the conceptjava:GeneratedType
which is defined by the Java plugin -
This concept may be extended by project specific concepts adding labels
:Type:Generated
and declaring the provided conceptjava:GeneratedType
usingprovidesConcept(s)
4.3.7. Severity Of Rules
A rule may optionally define the severity level. jQAssistant allows to break the build if there are violations in the configured severity level (or higher). For example, if the severity is set to critical, and if there are violated constraints with blocker and/or critical severity; the build will break. This feature allows projects to pay down their technical debt in an iterative manner.
Following severity levels are supported:
-
info
-
minor (default for concepts)
-
major (default for constraints)
-
critical
-
blocker
There is no default severity for groups. If a severity is specified then it is applied to all included elements where no further severity is given, e.g.
<jqassistant-rules xmlns="http://schema.jqassistant.org/rule/v1.8"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schema.jqassistant.org/rule/v1.8 https://schema.jqassistant.org/rule/jqassistant-rule-v1.8.xsd">
<group id="my-rules:MyGroup" severity="blocker">
<includeConstraint refId="my-rules:MyConstraint1"/>
<includeConstraint refId="my-rules:MyConstraint2" severity="minor"/>
</group>
</jqassistant-rules>
or in Asciidoc:
[[my-rules:MyGroup]] .A human readable description of the group. [role=group,severity=blocker,requiresConstraints="my-rules:Constraint1,my-rules:Constraint2(minor)"] == My Group
Thus execution of the group 'my-rules:MyGroup' will report a violation of constraint…
-
…'my-rules-Constraint1' with severity 'blocker' (inherited from the group)
-
…'my-rules-Constraint2' with severity 'minor' (specified within the group)
4.3.8. Script Languages
Instead of cypher scripting languages like JavaScript, Ruby or Groovy may be used for writing concepts or constraints:
<constraint id="xmlExample:JavaScriptConstraint">
<description>JavaScript example constraint: returns a result containing the number
of declared methods for each class.</description>
<script language="JavaScript">
// Define the columns returned by the constraint
var columnNames = java.util.Arrays.asList("Type", "MethodsOfType");
// Define the list of rows returned by the constraint
var rows = new java.util.ArrayList();
// Execute a query using the store
var typeIterator = store.executeQuery("match (t:Type:Class) return t").iterator();
while(typeIterator.hasNext()) {
// Get the next row from the query result
var typeRow = typeIterator.next();
// Get the column "t" from the row, it represents a type
// descriptor as defined by the Java plugin
var type = typeRow.get("t",
com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor.class);
// Get the declared methods of the type and count them
var methodIterator = type.getDeclaredMethods().iterator();
var methodsOfType = 0;
while( methodIterator.hasNext()) {
methodIterator.next();
methodsOfType++;
}
// Define the row for the result and put the value for each defined column
var resultRow = new java.util.HashMap();
resultRow.put("Class", type);
resultRow.put("MethodsOfType", methodsOfType);
rows.add(resultRow);
}
// Return the result
var status = com.buschmais.jqassistant.core.analysis.api.Result.Status.SUCCESS;
new com.buschmais.jqassistant.core.analysis.api.Result(rule, status, severity, columnNames, rows);
</script>
</constraint>
or in Asciidoc:
[[asciiDocExample:JavaScriptConstraint]] .JavaScript example constraint: returns a result containing the number of declared methods for each class. [source,javascript,role=constraint] ---- // Define the columns returned by the constraint var columnNames = java.util.Arrays.asList("Type", "MethodsOfType"); // Define the list of rows returned by the constraint var rows = new java.util.ArrayList(); // Execute a query using the store var typeIterator = store.executeQuery("match (t:Type:Class) return t").iterator(); while(typeIterator.hasNext()) { // Get the next row from the query result var typeRow = typeIterator.next(); // Get the column "t" from the row, it represents a type // descriptor as defined by the Java plugin var type = typeRow.get("t", com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor.class); // Get the declared methods of the type and count them var methodIterator = type.getDeclaredMethods().iterator(); var methodsOfType = 0; while( methodIterator.hasNext()) { methodIterator.next(); methodsOfType++; } // Define the row for the result and put the value for each defined column var resultRow = new java.util.HashMap(); resultRow.put("Class", type); resultRow.put("MethodsOfType", methodsOfType); rows.add(resultRow); } // Return the result var status = com.buschmais.jqassistant.core.analysis.api.Result.Status.SUCCESS; new com.buschmais.jqassistant.core.analysis.api.Result(rule, status, severity, columnNames, rows); ----
4.3.9. Rule Parameters
Both concepts and constraints may define required parameters:
<jqassistant-rules xmlns="http://schema.jqassistant.org/rule/v1.8"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schema.jqassistant.org/rule/v1.8 https://schema.jqassistant.org/rule/jqassistant-rule-v1.8.xsd">
<concept id="my-rules:ApplicationRootPackage">
<requiresParameter name="rootPackage" type="String" defaultValue="com.buschmais"/> (1)
<description>Labels the root package of the application with "Root".</description>
<cypher><![CDATA[
MATCH
(root:Package)
WHERE
root.name = $rootPackage (2)
SET
root:Root
RETURN
root
]]></cypher>
</concept>
</jqassistant-rules>
-
Declaration of a required parameter with a default value.
-
Reference to a parameter in a Cypher query.
or in Asciidoc:
[[my-rules:my-rules:ApplicationRootPackage]]
.Labels the root package of the application with "Root".
[role=group,role=concept,requiresParameters="String rootPackage; int limit"] (1)
----
MATCH
(root:Package)
WHERE
root.name = $rootPackage (2)
SET
root:Root
RETURN
root
----
-
requiresParameters is a list of parameter declarations separated by
;
-
Reference to a parameter in a Cypher query.
The following parameter types are supported:
-
char
-
byte
-
short
-
int
-
long
-
float
-
double
-
boolean
-
String
The values for the required parameters must be provided by the execution context, e.g. the jQAssistant Maven plugin or the command line utility. A rule may specify a default value which is used if no concrete value is provided for an execution.
Note
|
Default values are currently not supported for rules in Asciidoc files. |
For rules expressed in Cypher the parameters are referenced by {…}
placeholders. For scripts the values are passed
as parameters, i.e. they may be used directly in the code.
4.3.10. Result verification
The default strategy (rowCount
) verifies a result of a concept or constraint by counting the number of returned rows, i.e.
-
a concept is valid if it returns at least one row
-
a constraint is valid if it returns no row
This behavior can be customized by specifing min
and max
thresholds:
<constraint id="my-rules:MyConstraint">
<description>A human readable description of the constraint.</description>
<cypher><![CDATA[
MATCH
(n)
WHERE
...
RETURN
n as Element
]]></cypher>
<verify>
<rowCount max="20"/>
</verify>
</concept>
[[my-rules:MyConstraint]]
.A human readable description of the constraint.
[source,cypher,role=constraint,rowCountMax=20]
----
MATCH
(n)
WHERE
...
RETURN
n as Element
----
It is also possible to verify aggregated results reported as numeric values in a column, e.g.
<concept id="my-rules:MyConstraint">
<description>A human readable description of the constraint.</description>
<cypher><![CDATA[
MATCH
(n)
WHERE
...
RETURN
count(n) as Count
]]></cypher>
<verify>
<aggregation column="Count" max="20"/>
</verify>
</concept>
[[my-rules:MyConstraint]]
.A human readable description of the constraint.
[source,cypher,role=constraint,verify=aggregation,aggregationMax=20,aggregationColumn="Count"]
----
MATCH
(n)
WHERE
...
SET
...
RETURN
count(n) as Count
----
-
For each returned row the value of the column "Count" will be verified following the same principles as described above
-
The rule fails if at least one returned row does not match the expected result
-
The attribute
column
/aggregationColumn
can be omitted, in this case the first column of the result is evaluated -
Similar to the row count verification the attributes
min
/aggregationMin
andmax
/aggregationMax
can be specified for individual thresholds
4.3.11. Report
A rule may select a specific report plugin and pass properties to it:
<concept id="my-rules:MyConcept">
<description>A human readable description of the concept.</description>
<cypher><![CDATA[
MATCH
(m)-[]->(n)
...
RETURN
m, n
]]></cypher>
<report reportType="myReport">
<property name="key">value</property>
</report>
</concept>
[[my-rules:MyConcept]]
.A human readable description of the concept.
[source,cypher,role=concept,reportType="myReport",reportProperties="key1=value1;key2=value2"]
----
MATCH
(m)-[]->(n)
...
RETURN
m, n
----
4.3.11.1. Primary Column
If a rule reports more than one column it might be necessary to specify the column which contains the primary element the rule refers to, e.g. the Java class. The information may be evaluated by reporting tools, e.g. for creating issues in SonarQube:
<concept id="my-rules:MyConcept">
<description>A human readable description of the concept.</description>
<cypher><![CDATA[
MATCH
(m)-[]->(n)
...
RETURN
m, n
]]></cypher>
<report primaryColumn="n" />
</concept>
[[my-rules:MyConcept]]
.A human readable description of the concept.
[source,cypher,role=concept,primaryReportColumn="n"]
----
MATCH
(m)-[]->(n)
...
RETURN
m, n
----
Note
|
The first column will be used automatically if no primary column is explicitly specified. |
5. Command Line
Shell scripts are provided for executing jQAssistant from the command line of Microsoft Windows® or Unix compatible systems. They are located in the bin/ directory of the distribution:
-
jqassistant.cmd
-
jqassistant.sh
The command line accepts tasks and their specific options:
jqassistant.sh <task1> <task2> <task3> -<option1> -<option2>
The following example will scan the content of the directories classes/ and test-classes/:
jqassistant.sh scan -f classes,test-classes
5.1. Tasks
5.1.1. scan
5.1.1.1. Description
Scans files or directories and stores the gathered information in database. Files or URLs are accepted and may be specified further by scopes, e.g.
jqassistant.sh scan -f lib/,plugins/
jqassistant.sh scan -f java:classpath::classes/
jqassistant.sh scan -u http://host/artifact.jar
jqassistant.sh scan -u http://user:secret@host/artifact.jar
jqassistant.sh scan -u maven:repository::http://my.maven.repository
5.1.1.2. Options
-
-f [<scope>::]<file1>,[<scope>::]<file2> or --files [<scope>::]<file1>,[<scope>::]<file2>
-
specifies a list of files or directories to scan
-
a scope may be used as prefix for each file argument
-
-
-u [<scope>::]<url1>,[<scope>::]<url2> or --urls [<scope>::]<url1>,[<scope>::]<url2>
-
specifies a list of URLs to scan
-
a scope may be used as prefix for each url argument
-
-
-reset
-
reset the database before scanning
-
-
-continueOnError
-
continue scanning even if a plugin fails with an unrecoverable error
-
Note
|
Using -continueOnError might create inconsistent data. Any reported errors should be reported to the plugin developer. |
5.1.2. available-scopes
5.1.2.1. Description
List all available scopes which may be specified for scanning.
5.1.3. analyze
5.1.3.1. Description
Executes an analysis.
5.1.3.2. Options
-
-warnOnSeverity
-
determines the severity level for issuing warnings for failed with equal or higher severities
-
values: 'info', 'minor', 'major', 'critical' or 'blocker'
-
default: 'minor'
-
-
-failOnSeverity (-Djqassistant.failOnSeverity)
-
determines the severity level for breaking the build if at least one rule with an equal or higher severity failed
-
values: 'info', 'minor', 'major', 'critical' or 'blocker'
-
default: 'major'
-
-
-severity <severity>
-
specifies the severity of a problem for the analysis to fail. The program will return with exit code 2.
-
values: 'info', 'minor', 'major', 'critical' or 'blocker'
-
Deprecated: use
-failOnSeverity
instead
-
-
-executeAppliedConcepts
-
Execute concepts which have already been applied before. The default is 'false' to save time on repeated runs of "analyze" on the same data. Setting this flag to 'true' is useful for creating and trying out new concepts.
-
-
-ruleParameters
-
specifies the path to a property file defining values for parameters declared by rules
-
-
-createReportArchive
-
Create a ZIP file
report/jqassistant-report.zip
containing the generated reports
-
5.1.4. available-rules
5.1.4.1. Description
List all available rules.
5.1.5. effective-rules
5.1.5.1. Description
List the rules which would be executed for an analysis and the given concepts, constraints or groups.
5.1.6. list-plugins
5.1.6.1. Description
Lists all plugins known to jQAssistant. Helpful to check which plugins are active during the scan and analysis.
jqassistant.sh list-plugins
5.1.7. report
5.1.7.1. Description
Transforms an XML report into HTML.
5.1.7.2. Options
5.1.8. server
5.1.8.1. Description
Starts the integrated Neo4j web server.
-
-embeddedListenAddress <address>
-
specifies the binding address for the server (default: localhost)
-
-
-embeddedHttpPort <port>
-
specifies the HTTP binding port for the server (default: 7474)
-
-
-embeddedBoltPort <port>
-
specifies the BOLT binding port for the server (default: 7687)
-
-
-daemon
-
terminate the server using <Ctrl-C> instead of waiting for standard input (allows to run the server on a machine as a background process / service)
-
5.1.9. Common options
5.1.9.1. -s, --storeDirectory <directory>
-
specifies the location of the database to use
-
default: './jqassistant/store'
-
Deprecated: use -storeUri <uri> instead
5.1.9.2. -storeUri <uri>
-
specifies the URI of the database to use, for remote databases 'bolt://localhost:7687'
-
default: 'file:jqassistant/store'
5.1.9.3. -storeUsername <username>
-
specifies the user name for authentication against remote databases
5.1.9.4. -storePassword <password>
-
specifies the password for authentication against remote databases
5.1.9.5. -storeEncryption <true|false>
-
the encryption level for bolt connections
5.1.9.6. -storeTrustStrategy <trustAllCertificates|trustCustomCaSignedCertificates|trustSystemCaSignedCertificates>
-
the trust strategy for bolt connections
5.1.9.7. -storeTrustCertificate <file>
-
the file containing the custom CA certificate for trust strategy
trustCustomCaSignedCertificates
5.1.9.8. -groups <group1>,<group2>
-
specifies the ids of the groups to be executed
-
default: 'default'
5.1.9.9. -concepts <concept1>,<concept2>
-
specifies the ids of the concepts to be applied
5.1.9.10. -constraints <constraint1>,<constraint2>
-
specifies the ids of the constraints to be validated
5.1.9.11. -defaultConceptSeverity
-
specifies the default severity of concepts without an explicit severity
-
default: 'minor'
5.1.9.12. -defaultConstraintSeverity
-
specifies the default severity of constraints without an explicit severity
-
default: 'major'
5.1.9.13. -defaultGroupSeverity
-
specifies the default severity of groups without an explicit severity
-
default: 'none'
5.1.9.14. -r, --ruleDirectory <directory>
-
specifies the directory where rule files are located
-
default: './jqassistant/rules'
5.1.9.15. -rulesUrl <url>
-
specifies the URL of a file containing rules
-
this option is exclusive, i.e. it will disable loading rules from plugins or rule directories
5.1.9.16. -reportDirectory
-
specifies the directory where reports (XML, HTML) will be stored
-
default: './jqassistant/report'
6. Maven Plugin
jQAssistant provides a plugin for Apache Maven which can be used to provide either fully automated scanning and analysis during the build process or manual execution from a command line.
6.1. Setup
6.1.1. Project Scope
Software projects often consist of several modules which are assembled to executable or deployable artifacts. In a Maven project, these modules are usually organized hierarchically with a common parent module which is referenced directly or indirectly by all sub-modules. For each project, jQAssistant uses a separate database with its own set of rules. Thus if a goal is executed within a Maven structure jQAssistant first determines the project scope, i.e. the root module, by searching within the tree starting from the current module following the parent relation until either a module is found where a directory "jqassistant/" exists or no parent is defined. The determined root module defines the location of
-
the set of rules to apply (from the directory "jqassistant/")
-
the database, default "{project.build.directory}/jqassistant/store"
-
the generated native report, default: "{project.build.directory}/jqassistant/jqassistant-report.xml")
-
and the generated HTML report, default "{project.build.directory}/site/jqassistant.html")
The following examples demonstrate different scenarios, the root modules as detected by jQAssistant are marked using asterisks.
root*
|-pom.xml
|
|-jqassistant
| |-rules.xml
|
|-module1
| |-pom.xml
|
|-module2
|-pom.xml
root
|-pom.xml
|
|-project1*
| |-jqassistant
| | |-rules1.xml
| |
| |-pom.xml
| |-module1
| | |-pom.xml
| |
| |-module2
| |-pom.xml
|
|-project2*
|-jqassistant
| |-rules2.xml
|-pom.xml
|-module1
| |-pom.xml
|
|-module2
|-pom.xml
Note
|
The described mechanism is designed to work for Maven module structures which are organized in hierarchies with consistent parent relations. For other setups, it is possible to enforce using the module where the mvn goal is invoked as root module by setting the configuration option useExecutionRootAsProjectRoot (-Djqassistant.useExecutionRootAsProjectRoot). |
6.1.2. Plugin Configuration
The jQAssistant Maven plugin must be configured in the pom.xml of the root module, it should not be overwritten by sub-modules.
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>1.11.0-RC-1</version>
<executions>
<execution>
<!-- The id "default-cli" is used to allow execution of the goals with the given configuration from the command line -->
<id>default-cli</id>
<goals>
<goal>scan</goal>
<goal>analyze</goal>
</goals>
<!--
<extensions>false</extensions>
-->
<configuration>
<!-- Store/Database -->
<!--
<store>
<uri>file:target/jqassistant/store</uri>
<username></username>
<password></password>
<encryption>false</encryption>
<trustStrategy></trustStrategy>
<trustCertificate></trustCertificate>
<embedded>
<listenAddress>localhost</listenAddress>
<httpPort>7474</httpPort>
<boltPort>7687</boltPort>
</embedded>
</store>
<storeLifecycle>REACTOR</storeLifecycle>
-->
<!-- Scan -->
<!--
<reset>true</reset>
<scanIncludes>
<scanInclude>
<path>config</path>
</scanInclude>
<scanInclude>
<path>${project.build.directory}/extra-classes</path>
<scope>java:classpath</scope>
</scanInclude>
<scanInclude>
<url>https://repo1.maven.org/maven2</url>
<scope>maven:repository</scope>
</scanInclude>
</scanIncludes>
<scanProperties>
<customScanner.property>value</customScanner.property>
</scanProperties>
<continueOnError>false</continueOnError>
-->
<!-- Analysis configuration -->
<!--
<warnOnSeverity>MINOR</warnOnSeverity>
<failOnSeverity>MAJOR</failOnSeverity>
<concepts>
<concept>junit4:TestClass</concept>
</concepts>
<constraints>
<constraint>junit4:TestMethodWithoutAssertion</constraint>
</constraints>
<groups>
<group>default</group>
</groups>
<ruleParameters>
<myRuleParameter>com.buschmais</myRuleParameter>
</ruleParameters>
<rule>
<defaultConceptSeverity>MINOR</defaultConceptSeverity>
<defaultConstraintSeverity>MAJOR</defaultConstraintSeverity>
<defaultGroupSeverity></defaultGroupSeverity>
</rule>
<rulesDirectory>jqassistant</rulesDirectory>
<rulesDirectories>
<rulesDirectory>${project.build.directory}/generated-rules</rulesDirectory>
</rulesDirectories>
-->
<!-- Report -->
<!--
<reportProperties>
<customReport.fileName>
${project.build.directory}/customReport.txt
</customReport.fileName>
</reportProperties>
<attachReportArchive>false</attachReportArchive>
<xmlReportFile>${project.build.directory}/jqassistant/jqassistant-report.xml</xmlReportFile>
-->
<!-- Misc -->
<!--
<skip>false</skip>
<useExecutionRootAsProjectRoot>false</useExecutionRootAsProjectRoot>
-->
</configuration>
</execution>
</executions>
<!-- Plugins are declared as dependencies of the Maven plugin -->
<!--
<dependencies>
<dependency>
<groupId>org.jqassistant.contrib.plugin</groupId>
<artifactId>jqassistant-test-impact-analysis-plugin</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
-->
</plugin>
</plugins>
</build>
<!-- The following section is only required if a Maven site shall be generated including a jQAssistant report -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>com.buschmais.jqassistant</groupId>
<artifactId>jqassistant-maven-plugin</artifactId>
<version>1.11.0-RC-1</version>
<reportSets>
<reportSet>
<reports>
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
...
</project>
6.1.3. Command Line
Goals may also be executed from the command line:
mvn ${project.groupId}:${project.artifactId}:available-rules
Adding the following lines to the file settings.xml (usually located in the $HOME/.m2) eases execution of jQAssistant goals from the command line:
<pluginGroups>
<pluginGroup>com.buschmais.jqassistant</pluginGroup>
</pluginGroups>
The same goal can now be executed using the following command line statement:
mvn jqassistant:available-rules
6.2. Goals
6.2.1. jqassistant:scan
6.2.1.1. Description
Scans the project directories according to the given configuration (e.g. compiled classes and test classes) and stores the gathered information in the database.
6.2.1.2. Configuration
-
useExecutionRootAsProjectRoot (-Djqassistant.useExecutionRootAsProjectRoot)
-
reset (-Djqassistant.store.reset)
-
indicates whether the store shall be reset (i.e. cleaned up) before scanning
-
default: 'true'
-
-
scanIncludes
-
add directories, files or URLs to be included while scanning (optionally qualifed with a scope)
-
wildcards are not supported
-
-
scanProperties
-
allows passing properties to scanner plugins
-
-
continueOnError
-
continue scanning even if a plugin fails with an unrecoverable error
-
default:
false
-
Warning
|
Using 'continueOnError' might create inconsistent data. Any reported errors should be reported to the plugin developer. |
6.2.2. jqassistant:available-scopes
6.2.2.1. Description
List all available scopes which may be specified for scanInclude properties.
6.2.3. jqassistant:reset
6.2.3.1. Description
Resets the database by deleting all nodes and relationships.
6.2.4. jqassistant:server
6.2.4.1. Description
Starts the integrated Neo4j web server (default address: http://localhost:7474).
6.2.5. jqassistant:analyze
6.2.5.1. Description
Executes an analysis.
6.2.5.2. Configuration
-
useExecutionRootAsProjectRoot (-Djqassistant.useExecutionRootAsProjectRoot)
-
warnOnSeverity (-Djqassistant.warnOnSeverity)
-
determines the severity level for issuing warnings for failed with equal or higher severities
-
default: 'MINOR'
-
-
failOnSeverity (-Djqassistant.failOnSeverity)
-
determines the severity level for breaking the build if at least one rule with an equal or higher severity failed
-
default: 'MAJOR'
-
-
executeAppliedConcepts (-Djqassistant.executeAppliedConcepts)
-
Execute concepts which have already been applied before. The default is 'false' to save time on repeated runs of "analyze" on the same data. Setting this flag to 'true' is useful for creating and trying out new concepts.
-
default 'false'
-
-
ruleParameters
-
The values for rules that require parameters
-
-
reportProperties
-
The properties to be passed to report plugins
-
-
attachReportArchive
-
If
true
a ZIP filejqassistant-report.zip
containing the generated reports is created in the foldertarget/jqassistant
of the root module and attached using the classifierjqassistant-report
.
-
Note
|
If for a multi-module project the report archive shall be installed into the local repository the Maven Install Plugin
must be configured to use installAtEnd .
In a similar way for deploying the report archive to a remote repository deployAtEnd must be actived for the Maven Deploy Plugin.
|
6.2.6. jqassistant:effective-rules
6.2.6.1. Description
List the rules which would be executed for an analysis and the given concepts, constraints or groups.
6.2.6.2. Configuration
6.2.7. jqassistant:available-rules
6.2.7.1. Description
List all available rules.
6.2.8. jqassistant:report
6.2.8.1. Description
Transforms the XML report into HTML (i.e. for generating a Maven site).
6.2.8.2. Configuration
6.3. Common Configuration Properties
6.3.1. Execution
6.3.1.1. skip (-Djqassistant.skip)
-
skip execution of the plugin
-
default: 'false'
6.3.1.2. useExecutionRootAsProjectRoot (-Djqassistant.useExecutionRootAsProjectRoot)
-
force the module where 'mvn' is being executed to be used as root module
-
the database will be created in this module and contain all information of the reactor
-
rules will be read from the rulesDirectory (-Djqassistant.rules.directory) of this module
-
-
default: 'false'
6.3.2. Store
6.3.2.1. store
-
specifies the configuration of the database to use
-
uri (-Djqassistant.store.uri)
-
URI of the database, supported URI schemes are
-
'file' for embedded databases, e.g. 'file:target/mystore'
-
'bolt' for connecting to a running Neo4j instance (3.x+), e.g. 'bolt://localhost:7687'
-
-
username (-Djqassistant.store.username)
-
the username 'bolt' connections
-
-
password (-Djqassistant.store.password)
-
the password for 'bolt' connections
-
-
encryption (-Djqassistant.store.encryption)
-
the encryption level for 'bolt' connections:
false
(default) ortrue
-
-
trustStrategy (-Djqassistant.store.trustStrategy)
-
the trust strategy for 'bolt' connections:
trustAllCertificates
(default),trustCustomCaSignedCertificates
ortrustSystemCaSignedCertificates
-
-
trustCertificate (-Djqassistant.store.trustCertificate)
-
the file containing the custom CA certificate for trust strategy
trustCustomCaSignedCertificates
-
-
default: use embedded database at 'file:{rootModule}/target/jqassistant/store'
6.3.2.2. embedded
-
the configuration of the embedded Neo4j store
-
listenAddress (-Djqassistant.embedded.listenAddress)
-
the listen address to use for opening BOLT/HTTP connections
-
default:
localhost
-
-
httpPort (-Djqassistant.embedded.httpPort)
-
the HTTP port to be used by the Neo4j server
-
default:
7474
-
-
boltPort (-Djqassistant.embedded.boltPort)
-
the BOLT port to be used by the Neo4j server
-
default:
7687
-
6.3.2.3. storeDirectory (-Djqassistant.store.directory)
-
specifies the location of the database, either a relative path to the root module directory or an absolute path
-
default: '{rootModule}/target/jqassistant/store'
6.3.2.4. storeLifecycle (-Djqassistant.store.lifecycle)
-
specifies the lifecycle of the data store
-
'REACTOR': cache the store for the execution time of the reactor for fast execution
-
'MODULE': open and close the store for each module, slower but required for maven reactors containing extensions
-
-
default: 'REACTOR'
6.3.3. Analysis And Report
6.3.3.1. concepts (-Djqassistant.concepts)
-
specifies the ids of the concepts to be applied
6.3.3.2. constraints (-Djqassistant.constraints)
-
specifies the ids of the constraints to be validated
6.3.3.3. groups (-Djqassistant.groups)
-
specifies the ids of the groups to be executed
-
default: 'default'
6.3.3.4. rule
-
specifies rule-related settings
-
defaultConceptSeverity
-
the default severity of concepts without an explicit severity
-
default: 'MINOR'
-
-
defaultConstraintSeverity
-
the default severity of constraints without an explicit severity
-
default: 'MAJOR'
-
-
defaultGroupSeverity
-
the default severity of groups without an explicit severity
-
default: none
-
6.3.3.5. rulesDirectory (-Djqassistant.rules.directory)
-
specifies the name of the directory which contains rules
-
this directory is also used to identify the root module of a project, see Project Scope
-
default: 'jqassistant'
6.3.3.6. rulesDirectories (-Djqassistant.rules.directories)
-
specifies a list of directory names relative to the root module containing additional rules
6.3.3.7. rulesUrl <url> (-Djqassistant.rules.url)
-
specifies the URL of a file containing rules
-
this option is exclusive, i.e. it will disable loading rules from plugins or rule directories
6.3.3.8. xmlReportFile (-Djqassistant.report.xml)
-
specifies the target file for writing the XML report
-
default: '{rootModule}/target/jqassistant/jqassistant-report.xml'
7. Plugins
This section provides detailed descriptions of all distributed plugins.
7.1. jQAssistant Asciidoc Report Plugin Plugin
7.2. jQAssistant CDI Plugin Plugin
7.3. jQAssistant EJB 3 Plugin Plugin
7.4. jQAssistant GraphML Plugin Plugin
7.5. jQAssistant Java Plugin Plugin
Unresolved directive in include/plugins.adoc - include::/Users/obf/jqa-release-environment/jqa-manual/target/asciidoc-modules-documentation/com.buschmais.jqassistant.plugin/java8/asciidoc/plugin.adoc[]