1

I am trying to build and test a JavaFX application on a headless build server. Locally I am using TestFX and Monocle https://github.com/TestFX/Monocle and its working fine. However, I had to manually install Monocle into the java Extensions folder as per this question: JavaFX + maven + TestFX + monocle don't work together

Now I need to use a headless build server to automate our deployment. I can't figure out how to get this Java extension installed correctly with Maven, without doing it manually. This seemed to be the right feature: https://maven.apache.org/pom.html#Extensions,

<extensions>
    <extension>
        <groupId>org.testfx</groupId>
        <artifactId>openjfx-monocle</artifactId>
        <version>8u76-b04</version>
    </extension>
</extensions>  

but the tests fail with a NoClassDefFoundException (which doesn't happen if I manually build the jar into the Extensions). I don't know how to debug this, or if I'm even using the right feature. Any suggestions?

Trevor
  • 995
  • 3
  • 10
  • 25

1 Answers1

0

I had a similar headache some time ago. I solved it by copying both openjfx-monocle and all extensions from the extensions folder in a folder under /target and then set the extensions system property to that path. This way I could avoid the NoClassDefFoundException and also successfully run all test on Jenkins. Here is the profile part:

<!--
  This profile is used to make headless tests work with the Monocle Platform.
  It first copies the extensions from the JDK to the target/java-extensions folder.
  Then copies the openjfx-monocle implementation to the same folder.
  Afterwards it sets the extensions path to the folder with the copied extensions and the monocle platform.
-->
<profile>
  <id>headless-tests</id>
  <activation>
    <property>
      <name>headless.tests</name>
      <value>true</value>
    </property>
  </activation>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.7</version>
        <executions>

          <execution>
            <id>copy-external-jars</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>target/java-extensions</outputDirectory>
              <resources>
                <resource>
                  <directory>${java.home}/lib/ext/</directory>
                </resource>
              </resources>
            </configuration>

          </execution>

          <execution>
            <id>copy-monocle-to-extensions</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>target/java-extensions</outputDirectory>
              <resources>
                <resource>
                  <directory>src/test/resources/test-lib</directory>
                  <includes>
                    <include>openjfx-monocle-8u76-b04.jar</include>
                  </includes>
                </resource>
              </resources>
            </configuration>
          </execution>

        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
          <argLine>-Djava.ext.dirs=${project.basedir}/target/java-extensions</argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>
</profile>

In my case I copied the monocle jar from maven in the src/test/resources folder. This can further be improved by using Maven Dependency Plugin to copy the monocle jar directly with maven instead having it in src/test/resources.

vl4d1m1r4
  • 1,688
  • 12
  • 21
  • seems like a good solution. However, for me the extensions folder only has openjfx-monocle in it, it doesn't have any other JARs that would need to be copied. I wonder what the actual cause of that `NoClassDefFound` error is... it seems like this shouldn't fix it since there isn't anything else in that folder. But I will try it out to confirm. – Trevor Sep 26 '18 at 19:03
  • It should work for your case too even if you don't have other extensions. The reason why you get the `NoClassDefFoundException` is because the factory is handled in class loader that is parent of the System-Classpath class loader that normal java/maven applications use. Therefore since it only scans for classes upwards and the monocle platform is not in the extensions or in the runtime classes it throws the exception. I think it would work just by specifying the extensions folder system property to a folder that contains the monocle platform jar. – vl4d1m1r4 Sep 26 '18 at 19:57