Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 604
el n00b Avatar asked Jul 08 '16 15:07

el n00b


2 Answers

I just encountered the same problem with Reflections library (version 0.9.11), only when executing unit tests from Maven builds. A simple POM file change to my Surefire plugin fixed this for me.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.21.0</version>
            <configuration>
                <useSystemClassLoader>false</useSystemClassLoader>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.21.0</version>
            <configuration>
                <useSystemClassLoader>false</useSystemClassLoader>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

The <useSystemClassLoader> config parameter defaults to 'true'. Forcing it to 'false' seems to resolve the classloader problem in my unit tests.

like image 113
Jim Tough Avatar answered Sep 19 '22 14:09

Jim Tough


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);
}
like image 31
ck1 Avatar answered Sep 20 '22 14:09

ck1