Discussion:
JI-9056801 : Scene: Allow to add a stylesheet using a typed URL, not a stringified URL
Michael Binz
2018-08-22 18:47:09 UTC
Permalink
Hi all,

I opened a proposal for an extension of the javafx.scene.Scene API to allow
to add a stylesheet using a typed java.net.URL.

Currently the Scene class offers a list of stylesheet URLs in their
stringified representation accessible by Scene.getStylesheets().

The problem is that in some cases an URL instance encapsulates internal
state that gets lost in the conversion into its external form and back into
an URL instance, namely information on an URL handler. This ultimately
results in a failure (IOException file not found) when the Screen class
tries to load a stylesheet though code that loads the file contents using
URL#openStream() on the original URL instance can read the file contents
successfully.

In my case the problem showed up when creating an executable jar file
containing my JavaFX application (using OneJar). The application startup
in this case installs a customized Classloader that implements special
logic for accessing the jars contained classes, This works transparently
for classes and resources, but the URLs returned by Class#getResource( name
) do not survive the conversion to string and back because of the described
reason.

There is a workaround that caches the resource in a temporary file and
passes this file's URL to the Scene's list of stylesheets, but this poses
other problems.
As a remark, other APIs in JavaFX use the same pattern of expecting
stringified URLs like the Image() constructor and have the same problem,
but offer alternative constructors accepting a stream which allows to solve
the problem nicely.

Please discuss and decide if the proposal can be added as a change request
for JavaFX.

Best wishes,
Michael.
Nir Lisker
2018-09-14 12:22:38 UTC
Permalink
Hi Michael,

The issue in the JBS is JDK-8209921 [1].

getStylesheets() returns an ObservableList<String>, it cannot be changed to
ObservableList<URL>. What solution do you propose?

[1] https://bugs.openjdk.java.net/browse/JDK-8209921

- Nir
Post by Michael Binz
Hi all,
I opened a proposal for an extension of the javafx.scene.Scene API to allow
to add a stylesheet using a typed java.net.URL.
Currently the Scene class offers a list of stylesheet URLs in their
stringified representation accessible by Scene.getStylesheets().
The problem is that in some cases an URL instance encapsulates internal
state that gets lost in the conversion into its external form and back into
an URL instance, namely information on an URL handler. This ultimately
results in a failure (IOException file not found) when the Screen class
tries to load a stylesheet though code that loads the file contents using
URL#openStream() on the original URL instance can read the file contents
successfully.
In my case the problem showed up when creating an executable jar file
containing my JavaFX application (using OneJar). The application startup
in this case installs a customized Classloader that implements special
logic for accessing the jars contained classes, This works transparently
for classes and resources, but the URLs returned by Class#getResource( name
) do not survive the conversion to string and back because of the described
reason.
There is a workaround that caches the resource in a temporary file and
passes this file's URL to the Scene's list of stylesheets, but this poses
other problems.
As a remark, other APIs in JavaFX use the same pattern of expecting
stringified URLs like the Image() constructor and have the same problem,
but offer alternative constructors accepting a stream which allows to solve
the problem nicely.
Please discuss and decide if the proposal can be added as a change request
for JavaFX.
Best wishes,
Michael.
Nir Lisker
2018-09-16 13:01:33 UTC
Permalink
I think this needs to be discussed with a project lead - Kevin or Johan.
Hi Nir,
I understand that switching the API to use net.URL is not trivial.
The only idea that comes to mind is to offer two list properties, the one
existing as today, holding stringified URLs for backwards compatibility,
and a second one that holds typed .net.URLs. The existing version can be
deprecated in favour of the typed version.
Before starting such an effort it would be interesting if it is common
understanding that an URL instance is preferrable over a string URL.
Was there a special reason that JavaFX uses in its interfaces in many
places stringified URLs instead of the existing java.net.URL?
Best wishes,
Michael.
Post by Nir Lisker
Hi Michael,
The issue in the JBS is JDK-8209921 [1].
getStylesheets() returns an ObservableList<String>, it cannot be changed
to ObservableList<URL>. What solution do you propose?
[1] https://bugs.openjdk.java.net/browse/JDK-8209921
- Nir
Post by Michael Binz
Hi all,
I opened a proposal for an extension of the javafx.scene.Scene API to allow
to add a stylesheet using a typed java.net.URL.
Currently the Scene class offers a list of stylesheet URLs in their
stringified representation accessible by Scene.getStylesheets().
The problem is that in some cases an URL instance encapsulates internal
state that gets lost in the conversion into its external form and back into
an URL instance, namely information on an URL handler. This ultimately
results in a failure (IOException file not found) when the Screen class
tries to load a stylesheet though code that loads the file contents using
URL#openStream() on the original URL instance can read the file contents
successfully.
In my case the problem showed up when creating an executable jar file
containing my JavaFX application (using OneJar). The application startup
in this case installs a customized Classloader that implements special
logic for accessing the jars contained classes, This works transparently
for classes and resources, but the URLs returned by Class#getResource( name
) do not survive the conversion to string and back because of the described
reason.
There is a workaround that caches the resource in a temporary file and
passes this file's URL to the Scene's list of stylesheets, but this poses
other problems.
As a remark, other APIs in JavaFX use the same pattern of expecting
stringified URLs like the Image() constructor and have the same problem,
but offer alternative constructors accepting a stream which allows to solve
the problem nicely.
Please discuss and decide if the proposal can be added as a change request
for JavaFX.
Best wishes,
Michael.
Tom Schindl
2018-09-15 18:39:36 UTC
Permalink
Hi,

I don't understand why something should be lost but anyways I don't
think JavaFX API is not the right place to fix a short coming of OneJar.
As Nir pointed out it is next to impossible to retrofit the JavaFX API
to URL with breaking it.

Tom
Post by Michael Binz
Hi all,
I opened a proposal for an extension of the javafx.scene.Scene API to allow
to add a stylesheet using a typed java.net.URL.
Currently the Scene class offers a list of stylesheet URLs in their
stringified representation accessible by Scene.getStylesheets().
The problem is that in some cases an URL instance encapsulates internal
state that gets lost in the conversion into its external form and back into
an URL instance, namely information on an URL handler. This ultimately
results in a failure (IOException file not found) when the Screen class
tries to load a stylesheet though code that loads the file contents using
URL#openStream() on the original URL instance can read the file contents
successfully.
In my case the problem showed up when creating an executable jar file
containing my JavaFX application (using OneJar). The application startup
in this case installs a customized Classloader that implements special
logic for accessing the jars contained classes, This works transparently
for classes and resources, but the URLs returned by Class#getResource( name
) do not survive the conversion to string and back because of the described
reason.
There is a workaround that caches the resource in a temporary file and
passes this file's URL to the Scene's list of stylesheets, but this poses
other problems.
As a remark, other APIs in JavaFX use the same pattern of expecting
stringified URLs like the Image() constructor and have the same problem,
but offer alternative constructors accepting a stream which allows to solve
the problem nicely.
Please discuss and decide if the proposal can be added as a change request
for JavaFX.
Best wishes,
Michael.
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Tom Schindl
2018-09-17 05:27:42 UTC
Permalink
[you replied offlist but I guess that was an oversight so I bring it back]

Reading through the document I don't see what concept is not working,
but indeed the URL-constructor says that the protocol handler is
resolved when constructing the URL. Does OneJar rely on that fact?

The Stackoverflow problem who talks about Felix is strange as Felix
returns in the toExternalForm() approach a custom protocol (bundle:) and
Felix like eg Equinox installs an URLHandler for that protocol.

URL-Handlers work prefectly fine - I know that because I maintain
e(fx)clipse who is based on Equinox and we there make extensive usage of
that and never had any trouble.

I also found: http://one-jar.sourceforge.net/index.php?page=frameworks
who talks about a custom protocol supported by OneJar but as I've never
used OneJar (we use maven-shade for stuff like this) I don't know if
this applies to this problem.

Tom
Hi,
actually this is not a problem with a particular tool we use.  The
problem is that some of the concepts described in [1] that are used for
resource loading do not longer work. This impacts all tools that base
their functionality on this,  See [2] for other situations where
classloader-based resource-loading fails.
Michael.
[1]
https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html
[2]
https://stackoverflow.com/questions/20000897/javafx-stylesheets-inside-osgi-bundle
Am Sa., 15. Sep. 2018 um 20:40 Uhr schrieb Tom Schindl
Hi,
I don't understand why something should be lost but anyways I don't
think JavaFX API is not the right place to fix a short coming of OneJar.
As Nir pointed out it is next to impossible to retrofit the JavaFX API
to URL with breaking it.
Tom
Post by Michael Binz
Hi all,
I opened a proposal for an extension of the javafx.scene.Scene API
to allow
Post by Michael Binz
to add a stylesheet using a typed java.net.URL.
Currently the Scene class offers a list of stylesheet URLs in their
stringified representation accessible by Scene.getStylesheets().
The problem is that in some cases an URL instance encapsulates
internal
Post by Michael Binz
state that gets lost in the conversion into its external form and
back into
Post by Michael Binz
an URL instance, namely information on an URL handler. This ultimately
results in a failure (IOException file not found) when the Screen
class
Post by Michael Binz
tries to load a stylesheet though code that loads the file
contents using
Post by Michael Binz
URL#openStream() on the original URL instance can read the file
contents
Post by Michael Binz
successfully.
In my case the problem showed up when creating an executable jar file
containing my JavaFX application (using OneJar).  The application
startup
Post by Michael Binz
in this case installs a customized Classloader that implements special
logic for accessing the jars contained classes,  This works
transparently
Post by Michael Binz
for classes and resources, but the URLs returned by
Class#getResource( name
Post by Michael Binz
) do not survive the conversion to string and back because of the
described
Post by Michael Binz
reason.
There is a workaround that caches the resource in a temporary file and
passes this file's URL to the Scene's list of stylesheets, but
this poses
Post by Michael Binz
other problems.
As a remark, other APIs in JavaFX use the same pattern of expecting
stringified URLs like the Image() constructor and have the same
problem,
Post by Michael Binz
but offer alternative constructors accepting a stream which allows
to solve
Post by Michael Binz
the problem nicely.
Please discuss and decide if the proposal can be added as a change
request
Post by Michael Binz
for JavaFX.
Best wishes,
Michael.
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
--
Tom Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7. A-6020 Innsbruck
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck
Loading...