Code Monkey home page Code Monkey logo

arch-unit-maven-plugin's Introduction

ArchUnit Maven plugin

Build Status codecov Maven Central

ArchUnit Maven plugin is a simple Maven wrapper around ArchUnit that enables you to easily make sure that all your projects follow the same architecture rules.

ArchUnit is an awesome tool to implement some tricky checks that other static analysis tools can't implement at all : these checks run as unit tests, and guarantee that build will break if any violation is introduced, giving developers very fast feedback on their work.

Now, imagine you have 3 architecture rules, and you want 10 repositories to apply them... By default, you'll have no choice but copy/paste the rules (ie unit tests) in the 10 repositories. And if somebody removes one of these tests later, it may take months to realize it.

ArchUnit Maven plugin comes with a couple of rules out of the box (but you can add your own) : all you need is a bit of Maven config in your root pom.xml to make sure the rules you want to enforce are actually run at every build ! it then becomes very easy to have a proper governance on dozens of repositories.

And if you want to have regular reporting on which projects are using ArchUnit Maven plugin, with which rules, you can use our GitHub crawler

How to use ArchUnit Maven plugin ?

Add below plugin in your root pom.xml : all available <rule> are mentioned, so remove the ones you don't need. If needed, specify in <projectPath> property the path of the directory where the rules will be asserted

<plugin>
	<groupId>com.societegenerale.commons</groupId>
    <artifactId>arch-unit-maven-plugin</artifactId>
    <version>4.0.2</version>
    <configuration>
        <properties>
            <archunit.propertyName>propertyValue</archunit.propertyName>
        </properties>
		<rules>
			<preConfiguredRules>
				<rule>com.societegenerale.commons.plugin.rules.NoStandardStreamRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoJunitAssertRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoJodaTimeRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoJavaUtilDateRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoPowerMockRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoPrefixForInterfacesRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoPublicFieldRuleTest</rule>
				
				<!-- you may want to use one of the below rules, but not both at same time -->
				<rule>com.societegenerale.commons.plugin.rules.NoTestIgnoreRuleTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoTestIgnoreWithoutCommentRuleTest</rule>

				<rule>com.societegenerale.commons.plugin.rules.NoInjectedFieldTest</rule>
				<rule>com.societegenerale.commons.plugin.rules.NoAutowiredFieldTest</rule>
			</preConfiguredRules>
		</rules>
	</configuration>
	<executions>
		<execution>
			<phase>test</phase>
			<goals>
				<goal>arch-test</goal>
			</goals>
		</execution>
	</executions>
    <dependencies>
       <dependency>
           <!-- 
                A version of the core jar is included by default, but don't hesitate 
                to upgrade to a later one if you need :
                we will be able to add rules and behavior in arch-unit-build-plugin-core
                without releasing a new version of arch-unit-maven-plugin
            -->
            <groupId>com.societegenerale.commons</groupId>
            <artifactId>arch-unit-build-plugin-core</artifactId>
            <version>SOME_CORE_VERSION_GREATER_THAN_THE_PLUGIN</version>
       </dependency>
    </dependencies>
</plugin>

Dependency on arch-unit-build-plugin-core

Since v2.3.0, a lot of the original code from this repository has been moved to https://github.com/societe-generale/arch-unit-build-plugin-core , so that we can build a Maven or a Gradle plugin on top of a (common) core logic.

Therefore, since then, this repository is greatly simplified as it contains only Maven specific code and the adapters between Maven world and arch-unit-build-plugin-core.

This Maven plugin ships with a default version of arch-unit-build-plugin-core, but if new rules are added in arch-unit-build-plugin-core, you'll need to declare it as a dependency (as in the example above) to benefit from them. As long as there's no major change in the core API that would force us to update the Maven plugin, we won't have to release a new version of the plugin.

Adding custom rules

Add a single rule, for a given project

If you need to add a rule that is specific to a project, just add a regular ArchUnit test, as described on ArchUnit's homepage. You'll need to import yourself archUnit dependency, so please make sure to use the same version as in the plugin, otherwise there may be strange behaviors. ArchUnit Maven plugin will not be involved.

Add a rule, and share it across projects

You can share custom rules by packaging the respective classes containing the rules in a jar. Such classes can either contain fields of type ArchRule or methods taking a single parameter of type JavaClasses (compare JUnit support at https://www.archunit.org/userguide/html/000_Index.html#_junit_4_5_support). The classes those rules will be checked against are configured within the plugin. Add the jar containing your classes to your classpath (by mentioning it as a plugin's dependency for instance), and then mention the <rule> with its fully qualified name the <rules> block, so that ArchUnit Maven plugin can instantiate it and run it.

So your config would become something like :

<plugin>
    <groupId>com.societegenerale.commons</groupId>
    <artifactId>arch-unit-maven-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>

        <!-- optional - you can avoid build fail if there is issue. True to avoid build failure, default is false -->
        <noFailOnError>true</noFailOnError>

        <!-- optional - you can exclude classes that have a path containing any of the mentioned paths -->
        <excludedPaths>
            <excludedPath>my/package/to/exclude</excludedPath>
        </excludedPaths>

        <rules>
            <!-- using a rule available out of the box... -->
            <preConfiguredRules>
                <rule>com.societegenerale.commons.plugin.rules.NoJunitAssertRuleTest</rule>
            </preConfiguredRules>
            <!-- ... and a custom one, coming from a dependency of the plugin -->
            <configurableRules>
                <configurableRule>
                    <rule>com.tngtech.archunit.library.GeneralCodingRules</rule>
                    <applyOn>
                        <packageName>com.myproject.mypackage</packageName>
                        <!-- scope can be "main" or "test" -->
                        <scope>main</scope>
                    </applyOn>

                    <checks>
       	 	        <!-- otherwise you can specify either field or method names here. If no checks block is defined, all are executed -->
       	 		    <check>NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS</check>
       	 	    </checks>
            </configurableRule>
       </configurableRules>

    </rules>
  </configuration>
  <executions>
    <execution>
      <phase>test</phase>
      <goals>
        <goal>arch-test</goal>
      </goals>
    </execution>
  </executions>
  <dependencies>
    <dependency>
        <!-- dependency contains com.mycompany.rules.CustomArchRule -->
        <groupId>com.myCompany</groupId>
        <artifactId>custom-quality-rules</artifactId>
        <version>1.0.0</version>
    </dependency>
  </dependencies>
</plugin>

Skipping rules

In case of adding ArchUnit Maven plugin to a legacy code base you might not be able to enforce all rules immediately. You may add ArchUnit Maven plugin to a parent POM of your Maven artifacts and still be able to skip execution in child projects by using the skip-configuration.

Skipping just one rule

Most of the time you add a new rule to your ArchUnit Maven plugin (which might immediately be available in all of your artifacts) but the issues ArchUnit reveals using your rule may not be fixed as soon as you need to release the next version of your artifacts.

To skip a rule temporarily, configure it like

<properties>
  <archunit.customrule.skip>false</archunit.customrule.skip>
</properties>
<!-- and inside your plugin's configuration -->
<configurableRule>
  <rule>com.mycompany.rules.CustomArchRule</rule>
  <skip>${archunit.customrule.skip}</skip>
  <!-- detailed configuration omitted -->
</configurableRule>

and then your slow-to-be-fixed-artifacts my override the property <archunit.customrule.skip>true</archunit.customrule.skip>

Skipping the whole plugin

If even skipping certain rules doesn't fit your needs, configure to skip the whole plugin execution:

<properties>
    <archunit.skip>false</archunit.skip>
</properties>
        <!-- and then inside the ArchUnit Maven plugin -->
<configuration>
<skip>${archunit.skip}</skip>
</configuration>

and then you can switch the parameter archunit.skip either on runtime (via -Darchunit.skip=true) or statically in child modules.

ArchUnit advanced configuration

Since v2.2.0, you can benefit from ArchUnit advanced configuration, as the plugin can find archunit.properties file. More infos in ArchUnit's user guide

Using archunit.properties file

ArchUnit loads its configuration once using the first archunit.properties file found as a resource in the classpath, then it's cached and reused. This can cause surprises in multi-module Maven projects since the ArchUnit instance is in use takes its configuration from the first module it's used with, and doesn't get reconfigured for each module as might be expected.

For example, if you are packaging a freezing rule for use in a multi-module project, the violation store location is configured once and isn't reconfigured for each module. As a workaround the rule can be adapted to overwrite the configuration before triggering the freezing rule, as described in #37.

Using Maven <properties> configuration

Since v3.0.0, an alternative approach is to configure properties using the Maven plugin where properties can be configured without writing to an archunit.properties file. The plugin will reconfigure ArchUnit for each module, complete with standard maven property expansion, before triggering the configured rules.

For example, if you are packaging a freezing rule for use in a multi-module project, you can enable store creation and set the location relative to each module:

<plugin>
    <groupId>com.societegenerale.commons</groupId>
    <artifactId>arch-unit-maven-plugin</artifactId>
    <configuration>
        <properties>
            <freeze.store.default.allowStoreCreation>true</freeze.store.default.allowStoreCreation>
            <freeze.store.default.path>${project.basedir}/src/archunit/</freeze.store.default.path>
        </properties>
        <rules>
        ...
        </rules>
    </configuration>
</plugin>

See here for a workaround : you need to overwrite the store location value in the cached configuration before triggering the freezing rule.

Excluding paths

Since v2.4.0, configuration can take an optional excludedPaths element. All classes that have a location that contains one the mentioned Strings will be excluded from the ArchUnit checks : can be useful in case some classes are generated (Lombok, Mapstruct, ..) and you have little or no control on what gets generated.

See ExclusionImportOption.java for details on the (very simple) logic.

Since v2.8.0, we can exclude something like generated-sources, even if the code ends up in the same package(S) as the regular code. See the discussion in #44 for more details

Disable fallback for wrongly configured paths

When no class files have been found using the configured paths, all folders of the current maven module are scanned for analysable classes. This could be a problem in multi-modules projects when some modules do not contain analyzable code (e.g. for packaging of web applications), if you don't want to override the plugin config (by disabling it entirely) in some modules

This behavior can be disabled by setting the optional fallbackToRootDirectory element of the configuration to false.

Contribute !

If you want to make changes in the Maven specific behavior, don't hesitate to open on issue on this repository and/or create a pull request.

If you don't want to package your rules separately and/or feel they could be useful to others, we can make your rules part of arch-unit-build-plugin-core, so that they can be used out of the box by anyone : don't hesitate to send us a pull request ! have a look at the code , it's very easy to add one.

Official maintainers

  • Arpit Garg
  • Vincent Fuchs

arch-unit-maven-plugin's People

Contributors

arpitgarg9168 avatar bvedrenne avatar chenzhang22 avatar codecholeric avatar croesch avatar fanjups avatar khmarbaise avatar purnhar avatar roqueit avatar roxspring avatar vincent-fuchs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arch-unit-maven-plugin's Issues

How share the rules between services

I have my lib called arch-rules with my rules like this:

    @ArchTest
    public void layerController(JavaClasses javaClasses) {
        layeredArchitecture()
                .consideringAllDependencies()
                .layer(CONTROLLER).definedBy(CONTROLLER_PACKAGE)
                .layer(SERVICE).definedBy(SERVICE_PACKAGE)
                .layer(REPOSITORY).definedBy(REPOSITORY_PACKAGE)
                .layer(MAPPER).definedBy(MAPPER_PACKAGE)
                .whereLayer(CONTROLLER).mayNotBeAccessedByAnyLayer()
                .allowEmptyShould(true)
                .check(javaClasses);
    }

I added this library in another internal lib called parent as a dependency
I have my service with my parent lib as a dependency

In my service I have this test:

@AnalyzeClasses(packages = "my package", importOptions = ImportOption.DoNotIncludeTests.class)
public class ProductionScopeArchTest {

    @ArchTest
    static final ArchTests validateProdScope = ArchTests.in(ArchValidationProdScopeTest.class);

}

My question is:
How can run my arch tests in the maven build and remove this test class and pass my package in the plugin? because for the moment, I need create this test class for all my services that I want apply the rules. Is it possible or Did I understand wrong the goal of the plugin?

Thank you!

Question: should my custom rules extend the class com.societegenerale.commons.plugin.rules.ArchRuleTest?

I'm trying to run a bunch of custom rules we created with the plugin instead of copy pasting them on a new test in every repo but I'm having issues

[ERROR] Failed to execute goal com.societegenerale.commons:arch-unit-maven-plugin:4.0.2:arch-test (default) on project holamundo-spring: class com.kalyp.buildingblocks.archunit.ArchitectureRules cannot be cast to class com.societegenerale.commons.plugin.rules.ArchRuleTest (com.kalyp.buildingblocks.archunit.ArchitectureRules and com.societegenerale.commons.plugin.rules.ArchRuleTest are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @1ee5792a)

The class is simple:

`
public class ArchitectureRules {

public static final ArchRule CONTROLLER_CLASSES_SHOULD_BE_IN_APPROPRIATE_PACKAGE = classes().that()
    .areAnnotatedWith(RestController.class)
    .or().haveNameMatching(".*Controller*")
    .should().resideInAPackage(API_PACKAGE)
    .orShould().resideInAPackage(REST_PACKAGE)
    .orShould().resideInAPackage(CONTROLLER_PACKAGE);

public static final ArchRule SERVICE_CLASSES_SHOULD_BE_IN_APPROPRIATE_PACKAGE = classes().that()
    .areAnnotatedWith(Service.class)
    .or().haveNameMatching(".*Service*")
    .should().resideInAPackage(SERVICE_PACKAGE);

}`

Thanks in advance

Configuration get's mixed up in multi module build

Summary

When using the arch-unit-maven-plugin in a multi module build together with archunit.properties file for each module, only the archunit.properties of the first module is loaded and used for all modules.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

I try to use ArchUnit in a multi module build where some tests are using FreezingArchRule. On the first run they all should "freeze" the current violations to a store. One for each module as only the classes for that module are tested.

Current Behavior

When running a multi module build with the plugin activated in multiple modules, the ArchUnit tests for the first module read the archunit.properties for that module and create a new store for the freezed violations. The ArchUnit tests of the second module do not create their own new store but the existing one of the first module. This store is then emptied as the violations stored in it do not exist in the second module and the violations of the second module are not stored but cause the build to fail.
Without setting the freeze.store.default.path the store is placed in the parent module of the two modules.
I explicitly set the freeze.store.default.path to ${project.basedir/archunit_store to force the usage of a separate store for each module. But then the store is just placed n the first module but still used for every module. Apparently only the ArchUnit tests of the first module run by the plugin do read the configuration and those of the next module don't read their own configuration but use the one of the first.

When running the same ArchUnit tests as JUnit5 tests using the maven-surefire-plugin, every module uses it's own archunit.properties. But that way causes other inconveniences as it is harder to reuse the same rules for multiple modules and mixes architecture tests with unit tests.

Expected Behavior

For each module in a multi module build, its own archunit.properties and a separate store for freezing should be used.

Steps to Reproduce (for bugs)

my archunit.properties in src/test/resources of each module (filterung in activated):

freeze.store.default.path=${project.basedir}/archunit_store
freeze.store.default.allowStoreCreation=true

My plugin configuration in the parent pom:

...
<modules>
  <module>mod1</module>
  <module>mod2</module>
</modules>
...
<build>
  <testResources>
    <testResource>
      <directory>src/test/resources</directory>
      <filtering>true</filtering>
    </testResource>
  </testResources>
  ...
  <plugins>
    ...
    <plugin>
      <groupId>com.societegenerale.commons</groupId>
      <artifactId>arch-unit-maven-plugin</artifactId>
      <version>2.4.0</version>
      <configuration>
        <!--force current "target" as project path for submodules -->
        <projectPath>${project.build.directory}</projectPath>
        <excludedPaths>playground</excludedPaths>
        <rules>
          <preConfiguredRules>
            ...
          </preConfiguredRules>
          <configurableRules>
            <configurableRule>
              <!-- ArchUnit test using freezing -->
              <rule>my.project.architecture.MainClassesArchTest</rule>
              <applyOn>
                <scope>main</scope>
              </applyOn>
            </configurableRule>
            <configurableRule>
              <rule>my.project.architecture.TestClassesArchTest</rule>
              <applyOn>
                <scope>test</scope>
              </applyOn>
            </configurableRule>
          </configurableRules>
        </rules>
      </configuration>
      <executions>
        <execution>
          <phase>test</phase>
          <goals>
            <goal>arch-test</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    ...
  <plugins>
  ...
</build>

Your Environment

  • Version used: 2.4.0
  • OS and version: Windows 10
  • Version of libs used: Java 8, Maven 3.6.3, archunit-junit5 0.14.1

How to import package in JAR?

How can I configure arch-unit-maven-plugin to include JARs for a rule? It seems to imply ImportOption.DoNotIncludeJars by default.

Classes under excluded paths are checked by configurableRules.

Summary

Classes under excluded paths are checked by configurableRules.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

It's the first time that i'm using arch-unit-maven-plugin so maybe it's not a bug but a misconfiguration.

Current Behavior

Classes under excluded paths are checked by configurableRules. I have a multi module maven projekt and one of the sub modules generates classes in the folder generated-sources\annotations\my.packages which are checked by a configurable rules.

Expected Behavior

Classes under excluded path are ignored by configurableRules.

Steps to Reproduce (for bugs)

this is the plugin configuration in my main pom:


<plugins>
	<plugin>
		<groupId>com.societegenerale.commons</groupId>
		<artifactId>arch-unit-maven-plugin</artifactId>
		<version>2.4.0</version>
		<configuration>
			<projectPath>${project.basedir}/target</projectPath>

			<!-- optional - you can exclude classes that have a path containing any of the mentioned paths -->
			<excludedPaths>
				<excludedPath>generated-sources</excludedPath>                    
			</excludedPaths>

			<rules>
				<!-- using a rule available out of the box... -->
				<preConfiguredRules>
					<rule>com.societegenerale.commons.plugin.rules.NoPublicFieldRuleTest</rule>
					<rule>com.societegenerale.commons.plugin.rules.NoStandardStreamRuleTest</rule>
					<rule>com.societegenerale.commons.plugin.rules.NoJodaTimeRuleTest</rule>
					<rule>com.societegenerale.commons.plugin.rules.NoPrefixForInterfacesRuleTest</rule>
				</preConfiguredRules>
				<!-- ... and a custom one, coming from a dependency of the plugin -->
				<configurableRules>
					<configurableRule>
						<rule>com.tngtech.archunit.library.GeneralCodingRules</rule>
						<applyOn>
							<packageName>my.packages</packageName>
							<!-- scope can be "main" or "test" -->
							<scope>main</scope>

						</applyOn>

						<checks>
							<!-- otherwise you can specify either field or method names here. If no checks block is defined, all are executed -->
							<!-- <check>NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS</check>-->
						</checks>
					</configurableRule>
				</configurableRules>

			</rules>
		</configuration>
		<executions>
			<execution>
				<phase>test</phase>
				<goals>
					<goal>arch-test</goal>
				</goals>
			</execution>
		</executions>               
	</plugin>
</plugins>

Your Environment

  • Version used: 2,4,0
  • OS and version: Window 10
  • Version of libs used: Java 11, Maven 3.6.3, archunit 0.14.1

2.6.x no longer works with aggregate POM

Summary

Before version 2.6.x, if the projectPath is not specified, if the plugin is run from the aggregate POM level, it will default to /target, relative to the path the plugin is run from, in this case the aggregate POM level instead of the module level (eg. /target instead of /module/target), which will fail. The workaround was to explicitly configure projectPath as ${project.build.directory}, which would cause it to run relative to the project base directory, regardless of where the plugin was run from.

With version 2.6.x, #39 is automatically getting the output directory and test output directory from Build#getOutputDirectory() and Build#getTestOutpuDirectory, which is great, however both of these paths are still used relative to the path the plugin was run from. Hence if the plugin is run from the aggregate POM level, it will again use the wrong path (/target instead of /module/target). And since projectPath is removed, there is currently no workaround for this as well.

A solution would be to resolve the output directory and test output directory to the project base directory, which can be obtained using MavenProject#getBasedir().

If you want, I can create a PR for this.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Your Environment

  • Version used: 2.6.1

Allow ignoring rule errors

Summary

Regarding #17 it would be nice to have something like

<failOnPriority>LOW|MEDIUM|HIGH</failOnPriority>

to let the rules run, check, but give warnings instead of errors if the failOnPriority is set higher than the rules priority.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

#17 allows skipping a certain rule which allows adding new rules to the ArchUnit Maven Plugin configuration for a large set of artifacts: you could just skip the rule in all artifacts where it doesn't pass (at the moment).

But normally what you don't see is hard to remember, so it would be nice to run the rule, see the problem but still have the build passing.

Current Behavior

You can either skip a rule or stick to it with all the consequences like failing builds.

Expected Behavior

Allow successful builds even if a rule fails.

ArchUnit has the priority available for the rules - is it used somewhere? Normally I would expect that you could define a certain level (like with logging) and rule violations above that level make the build fail and rule violations below that level appear as warnings.

What's your opinion? And would you rather add it to ArchUnit and make it available here (maybe with the same problems like the configuration file as mentioned in #13 ) or would you completely add the functionality here in the Maven plugin? Or even not at all? ;-)

Change log level from info to warning when noFailOnError=true

Summary

When there are some errors, however noFailOnError is set to true. It should log errors as Warning, so that developers will actually see it.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

When there are some validation errors, and the property noFailOnError, an error is logged on the info level. Thus, it can be easily lost, instead it should be logged as warning. This way it would bring attention.
Change is trivial, should be done on the line:

getLog().info(PREFIX_ARCH_VIOLATION_MESSAGE + ruleFailureMessage);

Current Behavior

When there are some validation errors, it is logged as info:
[INFO] Merging properties: The following properties have been overwritten by system properties: {noFailOnError=true}
[INFO] applying rules on 12 classe(s). To see the details, enable debug logs
SKIPPED
[INFO] ArchUnit Maven plugin reported architecture failures listed below :Rule Violated - SKIPPED
[INFO]

Expected Behavior

When there are some validation errors, it should be logged as warning:
[INFO] Merging properties: The following properties have been overwritten by system properties: {noFailOnError=true}
[INFO] applying rules on 12 classe(s). To see the details, enable debug logs
SKIPPED
[WARNING] ArchUnit Maven plugin reported architecture failures listed below :Rule Violated - SKIPPED
[INFO]

Steps to Reproduce (for bugs)

Set property true
Make sure there are some validation errors.

Your Environment

  • Version used: 3.0.0
  • OS and version: Any
  • Version of libs used:

Skip analysis for projects without source files

Summary

If no source files are found in a module of a multi module project, no analysis should be done (e.g. in modules which just assemble war files or docker images).

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

The plugin is used in a multi module project and defined in the root POM. Some of our modules only contain test code (integration tests) or they don't contain any java code at all (e.g. modules for building docker images). When building these modules the plugin adds all possible directories for analysis and therefore analyses the whole classpath of our application (including 3rd party libs). Unfortunately this behavior can't be switched off and the plugin definition has to be overridden in the client modules.

It would be very helpful to have the possibility to switch off this behavior in the plugin configuration.

Your Environment

  • Version used: 3.0.0
  • OS and version:
  • Version of libs used:

@ArchTest of type ArchTests are not picked up by plugin

Summary

Grouped Tests of type ArchTests (instead of ArchRule) are not picked up by the maven plugin

@ArchTest
public static final ArchTests TESTS_SUITE = ArchTests.in(RulesLibrary.class);

Type of Issue

It is a :

  • [x ] bug

Current Behavior

When executing this test the maven plugin do not load CODING_RULES ; only MY_RULE

@AnalyzeClasses(  packages = xxx,  importOptions = xxx)
public class GroupedTest {
   @ArchTest
    public static final ArchTests TESTS_SUITE = ArchTests.in(CodingRulesLibrary.class);
   @ArchTest
    public static final ArchRule MY_RULE = classes().xxx ;
}

Expected Behavior

Tests inside CodingRulesLibrary.class must be executed

Steps to Reproduce (for bugs)

Try to run Tests grouped with ArchTests.in

Your Environment

  • Version used:
  • Version of libs used: archunit 0.21.0 ; maven-plugin 2.8.0

can we mark this plugin @threadSafe

Summary

when run maven in multi-thread, it warns 'The following plugins are not marked@threadSafe'
if this plugin is thread safe, I think the solution is just add threadSafe=true as following

@mojo(... threadSafe=true)

Type of Issue

It is a :

  • bug
  • [ x] request
  • question regarding the documentation

Motivation

to support multi-thread without warning msg

Current Behavior

warn msg

Expected Behavior

no warning msg

Steps to Reproduce (for bugs)

run a multi module maven project in multi-thread mode

Allow to exclude single checks from a configurable rule

Summary

Hi,

We would like to suggest a feature allowing us to exclude certain rules from a configured rule "package".

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

We enforce certain architecture rules across various projects. Those are part of a platform used by said projects. Those rules are static fields contained in a single class so that we only have to include a single rule.

configurableRules>
  <configurableRule>
    <rule>our.custom.Rules</rule>
  </configurableRule>
</configurableRules>

This is working for 90% of our use cases. However, we have some projects that are doing things slightly different and need to exclude some of those rules. Let's assume that we have rules A, B and C and only C should not be applied. The projects in question can now configure those checks explicitly:

configurableRules>
  <configurableRule>
    <rule>our.custom.Rules</rule>
    <checks>
      <check>A</check>
      <check>B</check>
    </checks>
  </configurableRule>
</configurableRules>

This has two disadvantages:

  1. We have something like 20 rules, so the projects have to declare 19 of them just to exclude a single one.
  2. New rules, which are added to our.custom.Rules can easily be forgotten by the projects during an update of our platform.

Thus we would like to exclude certain checks from the rule set, like a negation of the check property.

configurableRules>
  <configurableRule>
    <rule>our.custom.Rules</rule>
    <excludedChecks>
      <excludedCheck>C</excludedCheck>
    </excludedChecks>
  </configurableRule>
</configurableRules>

Current Behavior

Either the whole rule set is executed or the given checks.

Expected Behavior

It should be possible to exclude single checks from the rule set.

Thank you and best regards

Nils

WARNINGs during Maven Build

Summary

Starting the build via mvn clean you will get a number of WARNING's about deprecated properties etc.

Type of Issue

You will face the following WARNINGs:

[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for com.societegenerale.commons:arch-unit-maven-plugin:maven-plugin:2.2.1-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-surefire-plugin is missing. @ line 187, column 21
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-javadoc-plugin is missing. @ line 204, column 21
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-resources-plugin is missing. @ line 280, column 21
[WARNING] The expression ${build.directory} is deprecated. Please use ${project.build.directory} instead.
[WARNING] The expression ${build.directory} is deprecated. Please use ${project.build.directory} instead.
[WARNING] The expression ${build.directory} is deprecated. Please use ${project.build.directory} instead.
[WARNING] The expression ${build.directory} is deprecated. Please use ${project.build.directory} instead.
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

A maven build should be without any WARNING.

Current Behavior

Expected Behavior

The build should be without any WARNING.

Your Environment

  • Version used: Mac OS / ANY OS
  • OS and version: JDK 8 / JDK 11
  • Version of libs used: current master.

excludedPath generated-sources leads to StringIndexOutOfBoundsException: String index out of range: -1

Summary

There are two classes inside target/generated-sources/api/src/main/java matching my ArchUnitRul that I'd like to filter.
In my multi-module project, I used this in the parent-pom as well as the sub-module pom.xml:

            <excludedPaths>
              <excludedPath>generated-sources</excludedPath>
            </excludedPaths>

But I get below error. Unfortunately, I cannot tell which of my classes causes the exception.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

Current Behavior

classes()
          .that().areAnnotatedWith(RestController.class)
          .should().bePackagePrivate()
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.tngtech.archunit</groupId>
        <artifactId>archunit</artifactId>
        <version>0.23.1</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>com.societegenerale.commons</groupId>
          <artifactId>arch-unit-maven-plugin</artifactId>
          <version>2.9.2</version>
          <configuration>
            <excludedPaths>
              <excludedPath>generated-sources</excludedPath>
            </excludedPaths>

            <rules>
              <configurableRules>
                <configurableRule>

                  <rule>foo.bar.ArchUnitRules</rule>
                  <applyOn>
                    <packageName>foo.bar</packageName>
                    <scope>main</scope>
                  </applyOn>

                  <checks>
                    <check>FOO</check>
                  </checks>
                </configurableRule>
                <configurableRule>
                  <rule>foo.bar.ArchUnitRules</rule>
                  <applyOn>
                    <packageName>foo.bar</packageName>
                    <scope>test</scope>
                  </applyOn>

                  <checks>
                    <check>BAR</check>
                  </checks>
                </configurableRule>
              </configurableRules>
            </rules>
          </configuration>

          <executions>
            <execution>
              <id>arch-test</id>
              <goals>
                <goal>arch-test</goal>
              </goals>
              <phase>test</phase>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
mvn -e test
[ERROR] Failed to execute goal com.societegenerale.commons:arch-unit-maven-plugin:2.9.2:arch-test (arch-test) on project foo: String index out of range: -1 -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.societegenerale.commons:arch-unit-maven-plugin:2.9.2:arch-test (arch-test) on project foo: String index out of range: -1
        at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:274)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:196)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:160)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
        at org.mvndaemon.mvnd.builder.SmartBuilderImpl.buildProject(SmartBuilderImpl.java:178)
        at org.mvndaemon.mvnd.builder.SmartBuilderImpl$ProjectBuildTask.run(SmartBuilderImpl.java:198)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.apache.maven.plugin.MojoFailureException: String index out of range: -1
        at com.societegenerale.commons.plugin.maven.ArchUnitMojo.execute(ArchUnitMojo.java:98)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
        at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:271)
        ... 11 common frames omitted
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
        at java.base/java.lang.String.substring(String.java:1837)
        at com.societegenerale.commons.plugin.service.JavaFileParser.extractClassName(JavaFileParser.java:124)
        at com.societegenerale.commons.plugin.service.JavaFileParser.parse(JavaFileParser.java:44)
        at com.societegenerale.commons.plugin.service.ExcludedPathsPreProcessor.determineClassNames(ExcludedPathsPreProcessor.java:194)
        at com.societegenerale.commons.plugin.service.ExcludedPathsPreProcessor.processExcludedPaths(ExcludedPathsPreProcessor.java:65)
        at com.societegenerale.commons.plugin.service.RuleInvokerService.<init>(RuleInvokerService.java:49)
        at com.societegenerale.commons.plugin.maven.ArchUnitMojo.execute(ArchUnitMojo.java:94)
        ... 13 common frames omitted

Expected Behavior

See: #44

No exception, and generated code filtered.

Steps to Reproduce (for bugs)

See above

Your Environment

  • arch-unit-maven-plugin: 2.9.2
  • archunit: 0.23.1
  • Maven 3.8.3
  • JDK 11

Import classes from Main and Test scope

Summary

Some test scenarios rely on Main and Test classes as well. Is there a way to configure the scope for both? I guess no, because documentation says
<!-- scope can be "main" or "test" -->

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

For example have a look on this rule from GeneralCodingRules
https://github.com/TNG/ArchUnit/blob/43fe9e28f01ba0c781f56fed75977e62251f08e5/archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java#L434C33-L434C33

It requires Main and Test classes loaded together to compare them and tell if there is a violation.

I can't get this Rule running as intended with this Plugin. However, if i run the Rule as JUnit Test without the Plugin and import Main and Test classes, it works as expected:

@Test
public void testClassesShouldResideInTheSamePackageAsImplementation() {
    JavaClasses myClasses = new ClassFileImporter().importPaths("target/classes", "target/test-classes");
    com.tngtech.archunit.library.GeneralCodingRules.testClassesShouldResideInTheSamePackageAsImplementation().check(myClasses);
}

Current Behavior

Expected Behavior

Steps to Reproduce (for bugs)

Your Environment

  • Version used:
  • OS and version:
  • Version of libs used:

Preconfigured rules scan all classes on classpath, not only the ones from the project

Summary

When the plugin runs, we see that even the standard java classes are scanned

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

Execution would be faster if we were scanning only the classes from the project. Furthermore, it may happen that one standard java class has a violation for some rules.

Current Behavior

When I run the build I have this :

[INFO] Analysing class 'java/io/IOException'
[INFO] Analysing class 'java/time/format/TextStyle'
[INFO] Analysing class 'java/util/Locale'
[INFO] Analysing class 'java/time/ZoneOffset'
[INFO] Analysing class 'java/time/zone/ZoneRules'
[INFO] Analysing class 'java/io/ObjectInputStream'
[INFO] Analysing class 'java/io/InvalidObjectException'

(..my classes are also scanned)

Expected Behavior

Only "my" classes should be scanned.

Steps to Reproduce (for bugs)

I guess this happens in all projects..

Your Environment

  • Version used: 2.0.0

Plugin error when updating from 4.0.0 to 4.0.1

Summary

I've setup a configuration with plugin 4.0.0 that seems to works pretty well. However, I want the new feature fallbackToRootDirectoryso I updated to 4.0.1 but then the plugin fails.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

Current Behavior

mvn arch-unit:arch-test

Running the normal plugin and goal throws the following exception:

[ERROR] Failed to execute goal com.societegenerale.commons:arch-unit-maven-plugin:4.0.1:arch-test (default-cli) on project rider-parent: Unable to retrieve component configurator include-project-dependencies for configuration of mojo com.societegenerale.commons:arch-unit-maven-plugin:4.0.1:arch-test: java.util.NoSuchElementException
[ERROR]       role: org.codehaus.plexus.component.configurator.ComponentConfigurator
[ERROR]   roleHint: include-project-dependencies
[ERROR] -> [Help 1]

Expected Behavior

Steps to Reproduce (for bugs)

Check out this example repository and change the plugin version from 4.0.0 to 4.0.1. I was able to reproduce the issue with this simple project that basically contains nothing else.

https://github.com/moneaOrg/archunit-example

Run with mvn arch-unit:arch-test

Your Environment

  • Version used: 4.0.1
  • OS and version: Mac Sonora 14.2.1
  • Version of libs used:
mvn -version
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: /opt/homebrew/Cellar/maven/3.9.6/libexec
Java version: 21.0.1, vendor: Homebrew, runtime: /opt/homebrew/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home
Default locale: en_SE, platform encoding: UTF-8
OS name: "mac os x", version: "14.2.1", arch: "aarch64", family: "mac"

Does not scan classes of POM modules

Summary

If you use POM modules, the ArchUnit Maven Plugin does not search the correct path.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

If you have your project separated into different modules and define ArchUnit Maven Plugin in the root, then the module classes are not scanned.

Current Behavior

It looks like ArchUnit Maven Plugin by default searches ./target if you don't specify another directory in the plugin's configuration.

Expected Behavior

IMO the plugin should always use the configured values for build directory, output directory and test output directory.

This would not only allow to use the plugin with module builds but also allow using the -f switch of Maven (which currently also seems to break the ArchUnit Maven Plugin).

Steps to Reproduce (for bugs)

  1. Create a POM with a rule and two modules.
  2. Place code in that modules that would not pass the specified rules
  3. Run mvn clean verify

Your Environment

Using Maven 3.6.1 and the plugin's newest 2.2.0 release.

Is there a ImportOption donotincludeTests option?

Summary

Looking at the documentation i dont' see a way to ignore the units test as part of the scan.
on AnalyzeClasses we have importOptions = ImportOption.DoNotIncludeTests.class Is this something simular to this in the plugin? for defaults.

parallel execution of arch-test gives maven warning

Summary

Parallel execution of arch-test show some warnings.
It would be nice to check the possibility of parallel execution and mark methods as @threadsafe to eliminate the maven warnings.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

Executing the maven build with parameter -T 2.0C to speed up overall build time.

Current Behavior

With parameter -T 2.0C the warning is printed which shall be fixed.

Expected Behavior

Execution of the plugin in parallel without maven warning.

Steps to Reproduce (for bugs)

Call arch-test with maven parameter -T 2.0C.

Execute rule on the aggregator ('pom' packaging)

Summary

There is archunit test(Layering testing) that need to perform on 'pom' packaging but the default behavior of the plugin is skip 'pom' packaging by default.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

I want to perform Archunit Layer Check using the plugin on many of our projects.

Current Behavior

The plugin will skip 'pom' packaging by default

Expected Behavior

The plugin configuration should provide a way to execute archunit check on 'pom' packaging and all its sub-module projects instead of just skipping it.
For example we can provide a configuration in the applyOn like this.

<configurableRule>
    <rule>com.test.LayerTest</rule>
    <applyOn>
        <!-- can be "true" or "false" -->
        <aggregator>true</aggregator>
    </applyOn>

    <checks>
        <check>LAYER_CHECK</check>
    </checks>
</configurableRule>

Change log level

Currently every analyzed class is logged via INFO log level, looking like this:

[INFO] --- arch-unit-maven-plugin:1.0.2:arch-test (default) @ com.company.foobar ---
[INFO] Analysing class 'com/foo/class1'
[INFO] Analysing class 'com/foo/class2'
[INFO] Analysing class 'com/foo/class3'
[INFO] Analysing class 'com/foo/class4'

That is way to much, since INFO is the standard maven console log level. Please change that to DEBUG or similar. Other maven plugins do not output anything in case of working correctly or just the number of affected artifacts.

Update minimum build plugin core version in README

Summary

The README still specifies the minimum arch-unit-build-plugin-core version as SOME_VERSION_GREATER_THAN_2.3.0. It should be updated to SOME_VERSION_GREATER_THAN_2.6.0.

Ideally the major version of the arch-unit-build-plugin-core should be incremented for every breaking change.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Your Environment

  • Version used: 2.6.1

Trying to scan modules with packaging `pom`

Summary

In a multi module build which contains modules which have packaging pom. Basic example is the root of a multi module build and maybe other children could
be defined with <packaging>pom</packaging>.

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Current Behavior

The current behaviour is that it produces a warning like this for each module which <packaging>pom</packaging>

[INFO] --- arch-unit-maven-plugin:2.2.0:arch-test (default) @ xyz-parent ---
[WARNING] classpath ..../target/test-classes doesn't exist..

which is a litte bit misleading cause modules which have been defined <packaging>pom</packaging> could not have code which would be compiled etc.

Expected Behavior

Based on the convention in Maven there should not be a WARNING for a module which is defined with <packaging>pom</packaging> cause it could not contain code at all.

It would also be a good idea to have a configuration which could be turned on to support edge cases where people define life cycle bindings in a module with <packaging>pom</packaging> on their own.

Steps to Reproduce (for bugs)

Create a simple multi module build which contains a parent and two children. For the parent you will get the described WARNING.

Your Environment

  • Version used: 2.2.0
  • OS and version: MacOS / JDK 11.0.3

Generate HTML Report

Summary

Generate HTML Report like junit or checkstyle

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Current Behavior

Only stdout logs report the arch-unit errors : it is not user friednly and not useable in jenkins pipeline.

Expected Behavior

it would be great if the errors detected by the plugin/archunit rules generate an html report

Ignore generated-sources

Summary

Currently the predefined rules are also scanning class files in generated-sources, which I have no control over. Is there a way to configure the plugin to ignore generated-sources?

Type of Issue

It is a :

  • bug
  • request
  • question regarding the documentation

Motivation

I don't have any control over the class files generated in generated-sources, thus have no way to resolve violations in the generated class files.

Make it easier to use custom rules

Thanks a lot for the cool initiative to create this plugin ๐Ÿ˜ƒ

As far as I can see, you have to add arch-unit-maven-plugin to your dependencies and implement ArchRuleTest if you want to execute your own rules?

I think it would be cool to allow to specify something like

<rule>
    <class>com.my.CustomRule</class>
    <check>
        <package>com.my.app</package>
        <scope>main</scope>
    </check>
</rule>

Especially since the classes to import maybe vary under certain conditions (projects are pretty diverse...).

Yes, I know, a PR would be nicer, but I'm completely full at the moment โ˜น๏ธ

is there any plan to support jdk15?

When I build my project by using jdk15, there are tons of logs like that;

[WARNING] Couldn't import class from ...class-name...
java.lang.IllegalArgumentException: Unsupported class file major version 59
at com.tngtech.archunit.thirdparty.org.objectweb.asm.ClassReader. (ClassReader.java:195)
at com.tngtech.archunit.thirdparty.org.objectweb.asm.ClassReader. (ClassReader.java:176)
at com.tngtech.archunit.thirdparty.org.objectweb.asm.ClassReader. (ClassReader.java:162)
at com.tngtech.archunit.thirdparty.org.objectweb.asm.ClassReader. (ClassReader.java:283)
at com.tngtech.archunit.core.importer.ClassFileProcessor.process (ClassFileProcessor.java:56)
at com.tngtech.archunit.core.importer.ClassFileImporter.importLocations (ClassFileImporter.java:336)
at com.tngtech.archunit.core.importer.ClassFileImporter.importPaths (ClassFileImporter.java:158)
at com.tngtech.archunit.core.importer.ClassFileImporter.importPaths (ClassFileImporter.java:141)
at com.tngtech.archunit.core.importer.ClassFileImporter.importPath (ClassFileImporter.java:120)
at com.societegenerale.commons.plugin.utils.ArchUtils.importAllClassesInPackage (ArchUtils.java:66)
at com.societegenerale.commons.plugin.service.RuleInvokerService.invokeConfigurableRules (RuleInvokerService.java:110)
at com.societegenerale.commons.plugin.service.RuleInvokerService.invokeRules (RuleInvokerService.java:64)
at com.societegenerale.commons.plugin.maven.ArchUnitMojo.execute (ArchUnitMojo.java:88)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:64)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)

There is no issue on jdk11, it works as expected. there is also no information about supported java versions on readme (only information is 1.8 on pom.xml). am i missing something or there is no support? thanks

Type of Issue

  • request
  • question regarding the documentation

Your Environment

  • Version used: 2.6.1
  • OS and version: Windows 10
  • Version of libs used: Java 15, archunit-junit5 0.17.0

Unify treatment of predefined and configurable rules

Summary

Back when I played around with the code to adjust the behavior of configurable rules, I started to get the impression, that the handling of preconfigured rules could be unified (and thus simplified).

Also the naming seemed slightly inconsistent now, for predefined rules, a <rule> is a single ArchRule, for configurable rules, <rule> is the class where the rules are contained and <check> is a single ArchRule. I know it would break the syntax, but I would still propose the following adjustments.

Unify the handling of predefined rule and configurable rule

If you look at <configurableRule> it has all the necessary infrastructure to execute predefined rules as well. I could imagine to just declare a class

public class PreconfiguredRules{
    static final ArchRule do_not_write_to_standard_streams = ...;
    static final ArchRule do_not_use_PowerMock = ...;
}

Then simply adjust the POM configuration

<rules>
    <preConfiguredRules>
        <rule>do_not_write_to_standard_streams</rule>
        <rule>do_not_use_PowerMock</rule>
    </preConfiguredRules>
</rules>

And the rest of the infrastructure is already there, because that's exactly how configurable rules are evaluated (would probably need to add some meta data for scope though, so a little more is needed). As a benefit you would not need any boiler plate like the extra interface all preconfigured rules have to implement at the moment, and future extensions would be limited to the very bare minimum, adding an ArchRule field to PreconfiguredRules. As far as I saw from comments on PRs, this would eliminate the confusion of how to import which path and how to test the execute(..) method.

Adjust the naming of configurable rule

To be consistent with <predefinedRule> I would suggest to rename the tag the specifies where the rules are declared to either <ruleLocation> or <declaringClass>.

Then the configurable rules could be defined like

<rules>
    <configurableRules>
        <ruleSet>
            <ruleLocation>com.mylibrary.MyCustomArchRules<ruleLocation>
            <rules>
                <rule>my_custom_rule_one</rule>
                <rule>my_custom_rule_two</rule>
            </rules>
        </ruleSet>
    </customRules>
</rules>

A little fuzzy about the extensive plurals ๐Ÿ˜‰ Because in the end the child of <condigurableRules> is a plural again because it can house many <rules>.

What do you think? I would be willing to contribute / pitch in a PR if you're open to this, but I realize that it would be a major version upgrade since it would break the existing syntax of clients.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.