From 7ff972d1e1a2cd7ec6e310cba02fe2f8e6139553 Mon Sep 17 00:00:00 2001 From: Jun Sekine Date: Fri, 9 Oct 2026 16:44:28 +0900 Subject: [PATCH 1/3] Skip non-existent classpath entries when scanning with Reflections Gradle puts source set output directories on the classpath even when they were never created, e.g. build/classes/java/main in Kotlin-only projects. These entries made Reflections log NullPointerException and ReflectionsException stack traces for every scan. Signed-off-by: Jun Sekine --- .../thoughtworks/gauge/ClasspathHelper.java | 9 ++++- .../gauge/scan/ClasspathScanner.java | 2 +- .../gauge/ClasspathHelperTest.java | 40 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/thoughtworks/gauge/ClasspathHelperTest.java diff --git a/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java b/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java index 5128c22a..776d79c8 100644 --- a/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java +++ b/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java @@ -5,9 +5,12 @@ *----------------------------------------------------------------*/ package com.thoughtworks.gauge; +import org.reflections.vfs.Vfs; + import java.net.URL; import java.util.ArrayList; import java.util.Collection; +import java.util.stream.Collectors; public class ClasspathHelper { @@ -20,7 +23,11 @@ public static Collection getUrls() { } return urls; } - return org.reflections.util.ClasspathHelper.forJavaClassPath(); + // Gradle puts source set output dirs on the classpath even if they were never created, e.g. build/classes/java/main in Kotlin-only projects. + // Scanning such dirs logs NullPointerException stack traces, so skip entries that don't exist. + return org.reflections.util.ClasspathHelper.forJavaClassPath().stream() + .filter(url -> Vfs.getFile(url) != null) + .collect(Collectors.toList()); } } diff --git a/src/main/java/com/thoughtworks/gauge/scan/ClasspathScanner.java b/src/main/java/com/thoughtworks/gauge/scan/ClasspathScanner.java index 6191cdb5..e7b202d9 100644 --- a/src/main/java/com/thoughtworks/gauge/scan/ClasspathScanner.java +++ b/src/main/java/com/thoughtworks/gauge/scan/ClasspathScanner.java @@ -39,7 +39,7 @@ private Reflections createReflections() { Vfs.addDefaultURLTypes(new Vfs.UrlType() { @Override public boolean matches(URL url) { - return "file".equals(url.getProtocol()); + return "file".equals(url.getProtocol()) && Vfs.getFile(url) != null; } @Override diff --git a/src/test/java/com/thoughtworks/gauge/ClasspathHelperTest.java b/src/test/java/com/thoughtworks/gauge/ClasspathHelperTest.java new file mode 100644 index 00000000..c954d0af --- /dev/null +++ b/src/test/java/com/thoughtworks/gauge/ClasspathHelperTest.java @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------- + * Copyright (c) ThoughtWorks, Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE.txt in the project root for license information. + *----------------------------------------------------------------*/ +package com.thoughtworks.gauge; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.net.URL; +import java.util.Collection; +import java.util.List; + +import static com.thoughtworks.gauge.GaugeConstant.PACKAGE_TO_SCAN; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static uk.org.webcompere.systemstubs.SystemStubs.restoreSystemProperties; + +public class ClasspathHelperTest { + + @Test + public void testGetUrlsSkipsNonExistentClasspathEntries(@TempDir File tempDir) throws Exception { + assumeTrue(System.getenv(PACKAGE_TO_SCAN) == null); + File existingDir = new File(tempDir, "classes/kotlin/test"); + existingDir.mkdirs(); + File existingJar = new File(tempDir, "lib.jar"); + existingJar.createNewFile(); + File missingDir = new File(tempDir, "classes/java/test"); + String classpath = String.join(File.pathSeparator, + existingDir.getAbsolutePath(), missingDir.getAbsolutePath(), existingJar.getAbsolutePath()); + + restoreSystemProperties(() -> { + System.setProperty("java.class.path", classpath); + Collection urls = ClasspathHelper.getUrls(); + assertEquals(List.of(existingDir.toURI().toURL(), existingJar.toURI().toURL()), List.copyOf(urls)); + }); + } +} From e153bb20ed5c389e252c774985c2fd01f219cba2 Mon Sep 17 00:00:00 2001 From: Jun Sekine Date: Sat, 17 Oct 2026 08:56:08 +0900 Subject: [PATCH 2/3] Remove comment from ClasspathHelper Signed-off-by: Jun Sekine --- src/main/java/com/thoughtworks/gauge/ClasspathHelper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java b/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java index 776d79c8..161fae7b 100644 --- a/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java +++ b/src/main/java/com/thoughtworks/gauge/ClasspathHelper.java @@ -23,8 +23,6 @@ public static Collection getUrls() { } return urls; } - // Gradle puts source set output dirs on the classpath even if they were never created, e.g. build/classes/java/main in Kotlin-only projects. - // Scanning such dirs logs NullPointerException stack traces, so skip entries that don't exist. return org.reflections.util.ClasspathHelper.forJavaClassPath().stream() .filter(url -> Vfs.getFile(url) != null) .collect(Collectors.toList()); From 6c8945afe2c6a79d53a2a30a68e93085b5a8ffe3 Mon Sep 17 00:00:00 2001 From: Jun Sekine Date: Sat, 17 Oct 2026 18:07:58 +0900 Subject: [PATCH 3/3] chore: bump version to 1.0.4 Signed-off-by: Jun Sekine --- java.json | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java.json b/java.json index 71df71aa..1b10b2bd 100644 --- a/java.json +++ b/java.json @@ -1,6 +1,6 @@ { "id": "java", - "version": "1.0.3", + "version": "1.0.4", "description": "Java support for gauge", "install": { "windows": [], diff --git a/pom.xml b/pom.xml index 1b38dc4b..f522ed09 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ gauge-java com.thoughtworks.gauge gauge-java - 1.0.3 + 1.0.4 Java plugin for Gauge https://github.com/getgauge/gauge-java