Search code examples
mavenmaven-3reflections

Google Reflections & Maven - not finding data in Maven but works in IDE


Problem

Simple process request: find all extensions of List.class in the java.util package.

Here is the source I am using:

Reflections reflections = new Reflections("java.util");
Set<Class<?>> subtypes = reflections.getSubTypesOf(List.class);

Pretty simple, right?

It works in both IntelliJ IDEA and in Eclipse, but is not working when I run my tests via Maven. I tried adding things using the org.reflections.util.ConfigurationBuilder's provided methods for adding URLs and filtering on package names with no luck.

Any suggestions?

I looked through this post but was not able to get things working: "Unit test using the Reflections google library fails only when executed by Maven"

Code

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>ohno</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>org.reflections</groupId>
      <artifactId>reflections</artifactId>
      <version>0.9.10</version>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.9.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Sample.java

package com.example.uhoh;

import org.reflections.Reflections;
import java.util.Set;

public class Sample {

  @SuppressWarnings ("unchecked")
  public static Set<Class<?>> lookup(Class<?> type) {
    Reflections reflections = new Reflections("java.util");
    return (Set<Class<?>>) reflections.getSubTypesOf(type);
  }
}

SampleTest.java

package com.example.uhoh;

import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.List;
import java.util.Set;

@Test
public class SampleTest {

  public void testSample() {
    Set<Class<?>> result = Sample.lookup(List.class);
    Assert.assertNotNull(result, "NULL returned.");
    Assert.assertFalse(result.isEmpty(), "Unable to find any extensions of java.util.List");
  }
}

Output

Working in IDE Sample Working in IDE

Maven Output

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.example.uhoh.SampleTest
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNG652Configurator@4e515669
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.261 sec <<< FAILURE!
(com.example.uhoh.SampleTest)  Time elapsed: 0.071 sec  <<< FAILURE!
java.lang.AssertionError: Unable to find any extensions of java.util.List expected [false] but found [true]
    at org.testng.Assert.fail(Assert.java:94)
    at org.testng.Assert.failNotEquals(Assert.java:513)
    at org.testng.Assert.assertFalse(Assert.java:63)
    at com.example.uhoh.SampleTest.testSample(SampleTest.java:15)


Results :

Failed tests:   (com.example.uhoh.SampleTest): Unable to find any extensions of java.util.List expected [false] but found [true]

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0

Parallel Error

Code public void testSample() { Class[] dataTypes = { ArrayList.class, LinkedList.class, List.class, AbstractList.class, Collection.class, Map.class, Properties.class };

  Arrays.stream(dataTypes).parallel().forEach(next -> {
    Set<Class<?>> result = Sample.lookup(next);
    Assert.assertNotNull(result, "NULL returned.");
    Assert.assertFalse(result.isEmpty(), "Unable to find any extensions of java.util.List");
  });
}

Maven Output

java.lang.IllegalStateException: java.lang.IllegalStateException: zip file closed


Solution

  • To fix your issue, use Reflections' ConfigurationBuilder to manually set the URL for the jar that contains the class. This works in IntelliJ, and when invoking the Surefire plugin using command line Maven, mvn test.

    Sample.java

    public static Set<Class<?>> lookup(Class<?> type) {
        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
    
        // For List.class, this will be a path to rt.jar.
        configurationBuilder.addUrls(ClasspathHelper.forClass(type));
    
        Reflections reflections = new Reflections(configurationBuilder);
        return (Set<Class<?>>) reflections.getSubTypesOf(type);
    }