4

I am refactoring a multimodule project that depends on one module -- shared-resources -- for both main and test resources.

parent
|_ shared-resources
|_ child

Currently, a module includes the shared-resources by using the maven-resource-plugin.

current child/pom.xml:

...
<resources>
  <resource>
    <directory>../shared-resources/src/main/resources</directory>
  </resource>
</resources>
<testResources>
  <testResource>
    <directory>../shared-resources/src/test/resources</directory>
  </testResource>
</testResources>
...

I would like to restructure the dependencies so that they are included via a jar and test-jar packaging of the shared-resources module, as some related questions (e.g. "Specify common resources in a multi-module maven project" and "Share test resources between maven projects") suggest.

new shared-resources/pom.xml:

...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>test-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
...

new child/pom.xml:

...
<dependency>
  <groupId>com.example</groupId>
  <artifactId>shared-resources</artifactId>
  <version>0.0.1</version>
</dependency>
<dependency>
  <groupId>com.example</groupId>
  <artifactId>shared-resources</artifactId>
  <version>0.0.1</version>
  <scope>test</scope>
  <type>test-jar</type>
</dependency>
...

When I run tests for child however, tests for lack of the resources.

I've run my build in a variety of ways:

maven clean test --projects child --also-make

maven clean install -DskipTests && mvn test --projects child

maven clean verify --projects child --also-make

My authoritative test has been mvn clean install -DskipTests -pl :child -am && mvn test -pl :child -Dtest='PropertiesAccessTest' where properties access test does:

  public class PropertiesAccessTest {

    @Test
    public void resourceAccessible() throws URISyntaxException, IOException {
        propertyExists(
                "abcdef=12345",
                "test.properties"
        );
    }

    private void propertyExists(String string, String fileName) throws IOException, URISyntaxException {
        URL url = getClass().getClassLoader().getResource(fileName);
        assertNotNull(url);
        assertTrue("file should exist", new File(url.getFile()).exists());

        assertTrue("file should contain property", Files.readAllLines(Paths.get(url.toURI()))
                .stream().anyMatch(l -> l.contains(string)));
    }
}

There is a corresponding test.properties in shared-resources/src/test/resources/ (which should be included as I understand the above config), but instead the test always fails with "file should exist."

I can verify that my local .m2 repository contains the test jar containing test resources as expected.

What am I doing wrong here?

jwilner
  • 6,348
  • 6
  • 35
  • 47
  • What kind of resources are those `shared-resource`? I have the impression that those resource belong to the appropriate moduels? – khmarbaise Nov 27 '17 at 09:35
  • What command do you run? Are you sure the `shared-resources` artifact is properly installed? Providing the entire POM for both project might help, art to said from the given elements. – Pierre B. Nov 27 '17 at 11:41
  • @PierreB. I elaborated on my build commands above. For what it's worth, I can confirm that the contents of the `share-resources` jar and test jar are as expected. – jwilner Nov 27 '17 at 14:12
  • @khmarbaise exploring the actual content of `shared-resources` seems off topic. No doubt it's not a perfect module structure and some stuff could be moved around, but it's out of scope for this question -- especially when, by all appearances, this is supported maven behavior. – jwilner Nov 27 '17 at 14:15
  • Thanks. By `When I run tests for child however, tests for lack of the resources. ` you mean the test lacks shared-resources, but the main app is able to access them properly? Or both main and tests lacks resources? – Pierre B. Nov 27 '17 at 14:22
  • @PierreB. the tests can't access the test resources; main app seems to work fine. – jwilner Nov 27 '17 at 14:25
  • Your commands and config seems fine. When you run `install`, is `test-resources` included in the build session? Is your `test-jar` present in your local `m2` repository? What code are you using to load the resources, and what is the error shown? (asking a lot of question to trace the source of your issue ;) – Pierre B. Nov 27 '17 at 14:41
  • @PierreB. I updated the body in response to your very reasonable debugging suggestions. Thanks for your help! – jwilner Nov 30 '17 at 20:22

1 Answers1

3

You placed your file into separate module. Which means that it's going to be embedded into JAR file now. You cannot create a File out of it anymore. But you can access it via URI and InputStream:

getClass().getClassLoader().getResource("test.properties").openStream()

It's even more interesting with production resources though. Maven will use target/classes/test.properties if you run mvn test. And this will work with File. But if you run mvn package instead - it won't. Because after package Maven will put jar file into classpath instead of target/classes.

Stanislav Bashkyrtsev
  • 14,470
  • 7
  • 42
  • 45