ArchUnit: FreezingArchRule breaks when executed from IDE and maven
Environment:
- JDK11
Expected behavior: When the store files are generated, the tests should all pass independent of the test execution (here: IntelliJ or maven)
Actual behavior:
- When the store files were generated through IntelliJ, the tests only pass when they are executed through IntelliJ. Executing the tests through maven will result in test failures.
- When the store files were generated through maven, the tests only pass when they are executed through maven. Executing the tests through IntelliJ will result in test failures.
How to reproduce:
- Check out this PR: https://github.com/Taskana/taskana/pull/1971 where we’ve enabled our architecture tests (store files were generated through IntelliJ)
- Execute the ArchitectureTest class through IntelliJ. All tests should pass.
- Execute the ArchitectureTest class through maven. Some tests should fail. Execution command (from project root directory):
#build dependencies
./mvnw clean install -pl :taskana-core-test -am -DskipTests
#execute tests from ArchitectureTest class
./mvnw clean verify -pl :taskana-core-test -Dtest="ArchitectureTest"
Further notes:
As of right now we’ve disabled the tests, since this behavior is blocking us. You can find our test class here: https://github.com/Taskana/taskana/blob/master/lib/taskana-core-test/src/test/java/acceptance/ArchitectureTest.java The tests packagesShouldBeFreeOfCyclicDependencies and classesShouldBeFreeOfCyclicDependencies will fail. We’ve already set the following properties to an unreasonable high amount in order to make sure that all errors are detected.
cycles.maxNumberToDetect=100000
cycles.maxNumberOfDependenciesPerEdge=10000
During our initial debugging we’ve found out that the line numbers differ between the execution through maven and IntelliJ. Furthermore we’ve seen that IntelliJ and maven name lambda’s differently, which is a second difference in the store files.

About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 16
Commits related to this issue
- fix bug where origins of synthetic method calls override each other Calls to lambda methods `lambda$abc$123` seem to have unique origins with current JDK versions. I.e. even two identical consecutive... — committed to TNG/ArchUnit by codecholeric 2 years ago
- fix bug where origins of synthetic method calls override each other (#957) Calls to lambda methods `lambda$abc$123` seem to have unique origins with current JDK versions. I.e. even two identical cons... — committed to TNG/ArchUnit by codecholeric 2 years ago
Hey @codecholeric,
I’ve provided a video where I showcase what I did. Hopefully this helps you. https://drive.google.com/file/d/1KRMzIp7ipZYZxynLzKX8HZ1XMx7YTafJ/view?usp=sharing
I am using linux myself.
sure thing 😃 In the video you can see how I created these files. archunit_store_maven.zip archunit_store_intellij.zip output_intellij.txt output_maven.txt
Alright. I don’t want to be the blocking factor. Therefore I will try to reply as fast as I can 😃
Okay, this was quite the rabbit hole 😂 The first thing I noticed was that while some cycles between these classes were missing, this would not happen anymore if I would disable the AspectJ weaving. Looking into the bytecode I noticed that applying AspectJ would make the call to
TaskanaConfigurationInitializer.parseProperty(..)invisible in the bytecode of the classes. This is because AspectJ would weave in some additional synthetic access methodsTaskanaConfigurationInitializer.access$123which would then callparseProperty. So the question at this point was only, why was one cycle always detected if this call was missing, or more precisely, why was only one cycle detected, since normally ArchUnit would be supposed to transparently replace those calls toaccess$123with the call users would expect from the source code (compare #889). Turns out that1.0.0-rc1actually contains a bug there 🙈 So, I’m really glad that this issue brought this to surface. Basically, the implementation to remove thoseaccess$123methods was the same as forlambda$xyz$123methods, but for the latter the origins of the calls would be unique. But, foraccess$123they actually overrode each other, which lead to a non-deterministic behavior which access would be imported in the end (but seemingly deterministic enough so that it would be the same as long as the system and the environment would not change). You can see more details and (hopefully) a fix here (#957). In any case, I also published the version with the fix as1.0.0-SNAPSHOT, so maybe you can test this, if it solves your problem? It should now detect all 6 cycles for all 6 inner classes ofTaskanaConfigurationInitializerand thus not have different frozen cycles on different environments anymore. You have to add the snapshot repository to test it:Can you let me know if this now behaves reasonable for you?