profile
viewpoint
Roland Weisleder rweisleder data experts gmbh Berlin, Germany http://blog.rweisleder.de/

rweisleder/jfairy-junit-extension 14

Extension for JUnit which provides injection of random data

rweisleder/ArchUnit 0

A Java architecture test library, to specify and assert architecture rules in plain Java

rweisleder/assertj-core 0

AssertJ is a library providing easy to use rich typed assertions

rweisleder/baeldung-tutorials 0

Just Announced - "Learn Spring Security OAuth":

rweisleder/java-client-api 0

A Jenkins API client for Java

rweisleder/jfairy 0

Java fake data generator

PR opened TNG/ArchUnit

Run task archunit:jdk9Test on all CI builds

The default CI build gradlew build didn't execute the task jdk9Test and therefore the tests located in src/jdk9test/java are not executed regularly.

This PR also fixes the task jdk9Test itself, which is currently not executable during a Gradle build. This is also my current showstopper for #311.

+8 -5

0 comment

4 changed files

pr created time in an hour

push eventrweisleder/ArchUnit

Roland Weisleder

commit sha 3396ee37af55e028b1fdedefdae30b85f36ffbcb

Set explicit line endings for all *.java files Commit 5b250e2b introduced the Spotless plugin to our build process. From this commit on I was not able to run `gradlew build` on my Windows machine. Spotless failed because it expected all *.java files to have the CRLF line endings (system default), but due to Git's core.autocrlf=false these files had LF line endings. Spotless uses by default the Git settings to determine the expected line endings for the checked files. Instead of configure Spotless to use an explicit line ending, their recommendation is to set them via the .gitattributes file. [1] [1] https://github.com/diffplug/spotless/tree/main/plugin-gradle#line-endings-and-encodings-invisible-stuff Signed-off-by: Roland Weisleder <roland.weisleder@googlemail.com>

view details

Roland Weisleder

commit sha ac2187de24c8c418993e8674fe91a6a3cb2685ce

Run task archunit:jdk9Test on every CI build Before this commit, the default CI build `gradlew build` didn't execute the task jdk9Test. This means that tests located in src/jdk9test/java were not executed regularly and possible errors were not detected early. Furthermore, running `gradlew jdk9Test` failed with an error: com.tngtech.archunit.core.importer.ModuleLocationFactoryTest > initializationError FAILED org.gradle.api.GradleException: JUnit Categories defined but declared JUnit version does not support Categories. at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.verifyJUnitCategorySupport(JUnitTestClassExecutor.java:132) Executing all tests in src/jdk9test/java within the IDE succeeded. Signed-off-by: Roland Weisleder <roland.weisleder@googlemail.com>

view details

Roland Weisleder

commit sha 9d9ed8f25902ca4f36e8a3fa474f7e1c80689074

Run task archunit:jdk9Test during multi-jdk-matrix-build This commit ensures that the tests in src/jdk9test/java get executed against all JDKs >= 9. Signed-off-by: Roland Weisleder <roland.weisleder@googlemail.com>

view details

push time in an hour

create barnchrweisleder/ArchUnit

branch : fix-jdk9test-task

created branch time in an hour

issue commentTNG/ArchUnit

methods().that().areAnnotatedWith() does not match methods which have multiple instances of the same annotation type

This behavior is due to the fact of how Java handles repeatable annotations.

In your example, @ApiResponse is a repeatable annotation. Let me abbreviate that to

@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ApiResponses.class)
public @interface ApiResponse {
    int status();
}

@Retention(RetentionPolicy.RUNTIME)
public @interface ApiResponses {
    ApiResponse[] value();
}

Also, consider these two example usages:

@ApiResponse(status = 200)
static class FirstAnnotatedClass {
}

@ApiResponse(status = 200)
@ApiResponse(status = 404)
static class SecondAnnotatedClass {
}

If we use Java's Reflection API to get the annotations, we get the following result:

System.out.println(FirstAnnotatedClass.class.getAnnotation(ApiResponse.class)); // prints @org.example.ApiResponse(status=200)
System.out.println(SecondAnnotatedClass.class.getAnnotation(ApiResponse.class)); // prints null

What happened? Somewhere between your code and the reflective call, the repeatable annotation is wrapped into the containing annotation type, but only if the annotation is repeated. (I'm not sure if this happens during compile time or during runtime, but it doesn't matter.)

If we try to read the containing annotation type with Java's Reflection API, we get:

System.out.println(FirstAnnotatedClass.class.getAnnotation(ApiResponses.class)); // prints null
System.out.println(SecondAnnotatedClass.class.getAnnotation(ApiResponses.class)); // @org.example.ApiResponses(value=[@org.example.ApiResponse(status=200), @org.example.ApiResponse(status=404)])

And now compared to the behavior of ArchUnit:

JavaClasses classes = new ClassFileImporter().importClasses(FirstAnnotatedClass.class, SecondAnnotatedClass.class);

System.out.println(classes.get(FirstAnnotatedClass.class).tryGetAnnotationOfType(ApiResponse.class).orNull()); // prints @org.example.ApiResponse(status=200)
System.out.println(classes.get(SecondAnnotatedClass.class).tryGetAnnotationOfType(ApiResponse.class).orNull()); // prints null

System.out.println(classes.get(FirstAnnotatedClass.class).tryGetAnnotationOfType(ApiResponses.class).orNull()); // prints null
System.out.println(classes.get(SecondAnnotatedClass.class).tryGetAnnotationOfType(ApiResponses.class).orNull()); // @org.example.ApiResponses(value=[@org.example.ApiResponse(status=200), @org.example.ApiResponse(status=404)])

Compared to Java's Reflection API, ArchUnit produces the same results. So I would say this is the intended behavior.

My summary is, if you have to deal with repeatable annotations, you have to check both the annotation type and the containing annotation type.

m-ismar

comment created time in 18 days

startedcreditdatamw/zerocell

started time in a month

delete branch rweisleder/ArchUnit

delete branch : gh-386

delete time in 2 months

issue openedTNG/ArchUnit

Add support for sealed classes (Java 15 preview feature)

Java 15 will bring us JEP 360 (preview feature) which introduces sealed classes and permitted subclasses.

Currently, we are using ASM 8.0.1 which already contains experimental support for permitted subtypes. This merge request for ASM 9 contains the official support for this feature.

To do: Which API methods should be added? And should the permitted subclasses be considered as dependencies (if so, in which direction)?

created time in 3 months

push eventrweisleder/ArchUnit

Markus Spanier

commit sha cf69c4d391dcd5e4a847bfb7ee8d51c2c1890bb1

Use Github Actions for build Signed-off-by: Markus Spanier <markus.spanier@tngtech.com>

view details

Peter Gafert

commit sha 15e5df6dc9c2ef0672b854e1bd627ad518fc2920

Use Github Actions for build #362 Use Github actions to check whether the build runs on all OS.

view details

Peter Gafert

commit sha e6d9d359d624dc3689cf5675b8fd25a01e69a321

fix broken classpath scanning for manifest classpaths Tools often have an option to specify the classpath as manifest entry, i.e. to run tests the tool will create an empty JAR only containing a manifest with an `Class-Path` attribute containing the actual classpath. This is useful if the classpath is long and the platform (e.g. Windows) does not support a sufficiently long command line, thus limiting the length of the classpath supplied on the command line. Unfortunately the recent fix for Android, switching from loading the classpath through the respective Classloader to resolving the classpath manually, did not take this case into account anymore and it slipped through the tests, since no environment would specify the classpath via manifest. Now we also resolve those manifest attributes when manually resolving the classpath. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha bc353f4f742f396e58851c16f4f5c2c7dd2c6f04

avoid calling `getClass().getSimpleName()` repeatedly Surprisingly when I tested this locally, the JVM did not optimize it and lost some performance just for this statement. The value of using `getSimpleName()` here is not that great, so I simply hard-coded the value (I thought about making it a constant, but then went for simplicity, since the probability that this class will change and we overlook this renaming and it will actually cause a real problem / confusion is IMHO not that great). Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 8f882df93e00a36e471f01107638caee290b6be9

restore the old way of resolving classes from the classpath I measured this and found no noticeable performance impact. Thus I think it is safer to still use the current Classloader to resolve class files as well. In the end we will ignore duplicates in the set of locations anyway, and if the lookup time has no real impact, we are still safer in case there is some other quirk (like the manifest classpath that I forgot about when I refactored this to fix the Android problem). Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 0c3eb533b23561d5a9b205308933130f0ec5b9ff

adjust workflow to only run on either "push to master" or PR Otherwise for a PR from a branch of the archunit repo itself this will trigger duplicate builds, since both events trigger. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 6a2de78daf391d9215893c194420ccbb9e35facd

Fix classpath scanning #363 Unfortunately #347 broke the possibility to use a manifest `Class-Path` attribute to specify the classpath. Since this is a feature that many tools use to avoid "command line too long" problems (e.g. on Windows) when the classpath grows in size, I have added support for this to the new way of scanning the classpath. I have also added back the old way to resolve files through the context classloader, since I could not measure a real performance impact and using both sources seems safer in case there is some other classpath quirk I have overlooked. The set will remove duplicates anyway, before starting to import the classes.

view details

Peter Gafert

commit sha c8363d28a2058b1ab18fa3484bc2a3d1a096cd70

prepare release `0.14.0` Consistently set version to `0.14.0` in user guide by using an attribute reference to `{revnumber}`. Also upgraded dependencies of AsciiDoctor to current versions and included `/docs` into the core build, so attributes like the version are automatically consistent and we have a task in the root project to create the user guide. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha f86b87ae36504415e63f09c91ac1547ec0ed7107

prepare release `0.14.0` #364 Consistently set version to `0.14.0` in user guide by using an attribute reference to `{revnumber}`. Also upgraded dependencies of AsciiDoctor to current versions and included `/docs` into the core build, so attributes like the version are automatically consistent and we have a task in the root project to create the user guide.

view details

Peter Gafert

commit sha fb5fbb90e5b49299922621aa70bbab9812572850

disable Gradle meta-data for releases Unfortunately the Gradle meta-data does not match the way the release artifacts are composed, i.e. that `archunit-junit` is completely merged into `archunit-junitx` and does not exist as an artifact itself. Thus at the moment as soon as Gradle is used with the current release `0.14.0`, the build breaks because of a supposedly missing artifact `archunit-junit`. Since I do not see any value the Gradle meta-data would provide, I have disabled it in general until we find any benefit. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 2b84aaff421ac3d511291fef6f906445b2cb785b

prepare release `0.14.1` Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 00ea9edb80ccf61a02244598665fb22c3626bce4

fix split repos when publishing to Sonatype Nexus Unfortunately the Gradle Publish Plugin behaves erratically in combination with Sonatype Nexus. In particular if timing is bad, split repositories will be created. The only way I could find to mitigate this problem is the `de.marcphilipp.nexus-publish` plugin, which will create a Sonatype repository in a pre-step, then publish all artifacts to this repository. As far as I could see it works fine for releases and snapshots, has a shorter config and solves the problem at hand. Also compare https://github.com/gradle/gradle/issues/5711 Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha fd5e3586d1de1da0943627aa8f80ed13fa0bdb47

Release 0.14.1 #365 Unfortunately with `0.14.0` some broken Gradle meta data was published to Maven Central :frowning_face: Should not play a role for projects using Maven or another build tool, but for Gradle builds it will now complain that the artifact `archunit-junit` does not exist. I do not see any benefit from using the Gradle meta data in our case, since the Maven artifacts and their POMs are the single source of truth and those are built correctly. Thus I have disabled publishing the meta data. Also I have noticed that the Gradle Publish plugin behaves really erratically (I could not publish at all anymore, when I tried to publish `0.14.1`), i.e. there were always split repositories on Sonatype Nexus. I found https://github.com/gradle/gradle/issues/5711 and from there https://github.com/marcphilipp/nexus-publish-plugin which seems to nicely solve the problem.

view details

Peter Gafert

commit sha 68b12b086cdca6af418572d73789263d2bc1c7c2

set next SNAPSHOT version Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha eacee80749f97efb0663cac0eca5a4cdd13deaa5

execute GitHub build action for push on release branches Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Kamer Elciyar

commit sha b49351837d824f87e8f66e9db0e0a976329e0501

Extend MembersThat and MembersShould to have starting, containing and ending functionality. (#239) Signed-off-by: Kamer Elciyar <kamer@kamerelciyar.com>

view details

Peter Gafert

commit sha 74dcc1b71cfd8590555e660644a4921c24d16cea

add negated version of `name{startingWith/containing/endingWith}` I have also added some tests for the failure details, since broken messages there would be undetected at the moment. The reason that some of these tests for members are missing for other methods is simply that we reuse those for classes, so they were not added in the past since those tests would have already caught it. If we have syntax methods explicitly for members (that are not also used for classes), then we should add a detailed test checking that the failure details indeed match. when I wrote those tests I also noticed that messages like `Constructor<very.long.fqn.<init>()> does not start with 'foo'` does also read slightly weird (because there is no focus on the "name" the "starts with" refers to) so I added "name" to the failure details, i.e. `Constructor<..> name does not start with...`. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 93b376712a22fbfaaff492dc310024c868e26d87

Extend MembersThat and MembersShould to have starting,… (Resolves #239) #314 … containing and ending functionality and their negations.

view details

Peter Gafert

commit sha 0d76ee22816f363858ddd214354d393fe5fe2604

make `Java{Class/Member}Assertion` only compare `@Retention(RUNTIME)` annotations In general with ArchUnit we will also import annotations of `@Retention(CLASS)`, but it never makes any sense to compare those to `Annotations` retrieved via Reflection, since those will always only be the ones with `@Retention(RUNTIME)`. Since this is a very generic assertion, it makes sense to make it robust against cases where a type is annotated with an `Annotation` with `@Retention(CLASS)`, i.e. we cannot ever check successfully for `@Retention(CLASS)`, so we might as well ignore them to make the assertion usable in those cases and still get some test coverage of the `@Retention(RUNTIME)` cases. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

Peter Gafert

commit sha 1b3a73fd935032869642ca78a20304040da0340a

update docs dependencies to fix security vulnerability Problem was `gem activesupport < 5.2.4.3`, but meanwhile many dependencies were pretty outdated so I have upgraded them all (and verified that the page still works, at least locally). Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>

view details

push time in 3 months

Pull request review commentTNG/ArchUnit

Add JavaClass.tryGetConstructor(..) methods

 public JavaMethod getMethod(String name, String... parameters) {         return allMethods.get();     } +    /**+     * @return The constructor with zero parameters (the default constructor).

Ah, you're right, I forgot the inner classes. In this case the "default constructor"-note would be confusing.

rweisleder

comment created time in 3 months

push eventrweisleder/ArchUnit

Roland Weisleder

commit sha 2e6379d8255dbc6346db3d77660e42db75f2f783

Add JavaClass.tryGetConstructor(..) methods Before this commit, JavaClass had the methods * getField(..) and tryGetField(..) * getMethod(..) and tryGetMethod(..) * getConstructor(..) This commit adds the equivalent tryGetConstructor(..) methods. Issue #386 Signed-off-by: Roland Weisleder <roland.weisleder@googlemail.com>

view details

push time in 3 months

PR opened TNG/ArchUnit

Add JavaClass.tryGetConstructor(..) methods

Before this commit, JavaClass had the methods

  • getField(..) and tryGetField(..)
  • getMethod(..) and tryGetMethod(..)
  • getConstructor(..)

This PR adds the equivalent tryGetConstructor(..) methods.

Resolves #386

+75 -2

0 comment

2 changed files

pr created time in 3 months

create barnchrweisleder/ArchUnit

branch : gh-386

created branch time in 3 months

issue openedTNG/ArchUnit

Avoid using Optional.getOrThrow(RuntimeException) in our code

Currently, we have some usages of Optional.getOrThrow(RuntimeException) in our code like this: https://github.com/TNG/ArchUnit/blob/38f6748c4e5d5758cfb3c6509aefb616cf83e475/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java#L677-L679

The usage of this method requires to create a new Throwable object and fill the stack trace, whether the exception is needed or not. See also The hidden performance costs of instantiating Throwables.

It may not have a big impact, but I think we should avoid the usage of this method in our code.

created time in 3 months

more