JDK-8209180 : Media fails to load source from custom image, with jrt: URL
  • Type: Bug
  • Component: javafx
  • Sub-Component: media
  • Affected Version: 9,openjfx11
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2018-08-07
  • Updated: 2019-05-01
  • Resolved: 2019-05-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
openjfx13Fixed
Related Reports
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows 7 64-bit
OpenJDK 10.0.2
JavaFX SDK 11 11-ea+21

A DESCRIPTION OF THE PROBLEM :
In a modular JavaFX application developed with OpenJDK 10.0.2 and JavaFX SDK 11-ea+21, the FXML contains a MediaView that contains a MediaPlayer that contains a Media object whose source attribute is specified as a relative path.  The application runs as expected when executed inside the IDE, and when executed on the command line as a modular jar.  However, when a custom image is created out of the modular jar, the resulting application fails to load the FXML file.

My debugging shows that the source parameter used to construct the Media instance is a jrt URL: jrt:/demo/assets/TextInMotion-Sample-576p.mp4, and there is no provision in the Media class to support jrt URLs.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Build the project with
$ gradle clean build
Run the modular jar with
$ gradle run
Construct a custom image with
$ jlink --output demo --module-path C:/cygwin64/home/90019249/opt/javafx-jmods-11\;build/libs --add-modules demo --launcher demo=demo/foo.Main
Run the custom image with
$ demo/bin/demo

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The application runs as expected in both runs
ACTUAL -
The application runs as expected when ran as a modular jar.
The application fails to start with the following exception when ran from the custom image:

Exception in Application start method
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
Caused by: java.lang.RuntimeException: Exception in Application start method
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: javafx.fxml.LoadException: 
/demo/fxml/View.fxml:14

        at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
        at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
        at demo/foo.Main.start(Main.java:15)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
        at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
        ... 1 more
Caused by: java.lang.RuntimeException: Cannot create instance of javafx.scene.media.Media with given set of properties: [source]
        at javafx.fxml/com.sun.javafx.fxml.builder.ProxyBuilder.build(ProxyBuilder.java:272)
        at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:771)
        at javafx.fxml/javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557)
        ... 12 more


---------- BEGIN SOURCE ----------
The test case project contains 6 files:
build.gradle
src/main/java/foo/Main.java
src/main/java/foo/View.java
src/main/java/module-info.java
src/main/resources/assets/TextInMotion-Sample-576p.mp4
src/main/resources/fxml/View.fxml

// ****** build.gradle ****** //
plugins {
    id 'java'
    id 'application'
}

ext {
    javafxHome = "$System.env.JAVAFX_HOME"
}

mainClassName = 'foo.Main'
applicationDefaultJvmArgs = ['-p', "${javafxHome}/lib;build/libs", '--module', 'demo/foo.Main', '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005']
sourceCompatibility = '10'
targetCompatibility = '10'

compileJava {
    options.encoding = 'UTF-8'
    options.compilerArgs += ['-p', "${javafxHome}/lib", '--add-modules', 'javafx.graphics,javafx.fxml,javafx.media']
}

repositories {
    flatDir {
        dirs "${javafxHome}/lib"
    }
}

dependencies {
    implementation "org.openjfx:javafx.base",
        "org.openjfx:javafx.graphics",
        "org.openjfx:javafx.controls",
        "org.openjfx:javafx.fxml",
        "org.openjfx:javafx.media"
}

// ****** src/main/java/foo/Main.java ****** //
package foo;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.net.URL;

public class Main extends Application {
    public void start(Stage primaryStage) throws Exception {
        URL location = Main.class.getResource("/fxml/View.fxml");
        FXMLLoader fxmlLoader = new FXMLLoader(location);
        Parent root = fxmlLoader.load();
        Scene scene = new Scene(root, 1024, 576);
        primaryStage.setScene(scene);
        primaryStage.setTitle("FXML Demo");
        primaryStage.show();
    }
}

// ****** src/main/java/foo/View.java ****** //
package foo;

import javafx.scene.input.MouseEvent;
import javafx.scene.media.MediaPlayer;

public class View {
    public MediaPlayer mediaPlayer;

    public void play(MouseEvent mouseEvent) {
        System.out.println("Playing source:" + mediaPlayer.getMedia().getSource());
        mediaPlayer.play();
    }
}

// ****** src/main/java/module-info.java ****** //
module demo {
    requires javafx.base;
    requires javafx.graphics;
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.media;

    exports foo to javafx.graphics, javafx.fxml;

    opens foo to javafx.fxml;
}

// ****** src/main/resources/assets/TextInMotion-Sample-576p.mp4 ****** //
Obtained from https://d2qguwbxlx1sbt.cloudfront.net/TextInMotion-Sample-576p.mp4

// ****** src/main/resources/fxml/View.fxml ****** //
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.media.Media?>
<?import javafx.scene.media.MediaPlayer?>
<?import javafx.scene.media.MediaView?>
<AnchorPane prefHeight="576.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/8.0.121"
            xmlns:fx="http://javafx.com/fxml/1" fx:controller="foo.View">
    <MediaView fitHeight="576.0" fitWidth="1024.0" onMouseClicked="#play">
        <mediaPlayer>
            <MediaPlayer fx:id="mediaPlayer">
                <media>
                    <Media source="@../assets/TextInMotion-Sample-576p.mp4"/>
                </media>
            </MediaPlayer>
        </mediaPlayer>
    </MediaView>
</AnchorPane>

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The work around is to leave the media file outside of the custom image and load it using a file: an http: or an https: URL.  But that goes counter to the purpose of building a custom image.

FREQUENCY : always



Comments
http://hg.openjdk.java.net/openjfx/jfx-dev/rt/rev/c8cde739aa8e
01-05-2019

I was able to test the fix using the provided test program and local media files. We don't have any media unit tests nor the framework to run them, so we can file a follow-on issue for the test (although without a test harness we won't likely do it any time soon). +1 to push the current fix (webrev.00)
01-05-2019

Can you provide some sort of test program (manual would be OK) for this? Possibly using the embedded audioclip from Ensemble8 or some other small embedded audio or media file in a standalone modular test program?
29-04-2019

http://cr.openjdk.java.net/~almatvee/8209180/webrev.00/ - Added support for JRT protocol.
24-04-2019

We fixed a similar issue in WebEngine for JDK 9, JDK-8153681
21-08-2018