I want to use a map in a Java programme and realized that using Leaflet in a JavaFX WebView component. This worked fine until I put the application and the web resources into a jar archive. Then, I could still load the home page, but images, scripts and stylesheets would not be resolved if their locations were specified using relative paths.
Here's a minimal example (the JavaScript code is not necessary, it is only for further inspection):
webfail/Main.java
package webfail;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
WebView root = new WebView();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
WebEngine webEngine = root.getEngine();
webEngine.load(getClass().getResource("/webfail/home.htm").toExternalForm());
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
webfail/home.htm
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Home</title>
</head>
<body>
<h1>Home</h1>
<p>Go to <a href="linked.htm">other page</a>.<br />
<script type="text/javascript">
/* target of hyperlink */
var links = document.getElementsByTagName("a");
document.writeln("Link href: "+links[0].href+"<br />");
/* location of website */
document.writeln("Location href: "+window.location.href+"<br />");
/* construct a link with an absolute reference */
lastSlash = window.location.href.lastIndexOf("/");
document.writeln("Go to <a href=\""+window.location.href.substr(0,lastSlash+1)+"linked.htm\">other page</a>.<br />")
</script>
<script type="text/javascript" src="test.js"></script>
</p>
</body>
</html>
webfail/test.js
document.writeln("test.js is loaded.<br />");
I left out webfail/linked.htm
. It could be any html file.
Now the webpage that I get as a result looks like this:
Home
Go to other page.
Link href: file:///some/path/bin/webfail/linked.htm
Location href: file:///some/path/bin/webfail/home.htm
Go to other page.
test.js is loaded.
If I click one of the two links, I get to the second page. However, if I export the project into a jar archive, I get the following result:
Home
Go to other page.
Link href: linked.htm
Location href: jar:file:/some/other/path/WebFail.jar!/webfail/home.htm
Go to other page.
As can be seen, the first hyperlink refers only to linked.htm and nothing happens when it is clicked. Using javascript the second link is pointed to jar:file:/some/other/path/WebFail.jar!/webfail/linked.htm
and it works just fine.
Why does Java behave in such a way and what is the cause? Is it the WebView component or the handler for jar:file protocol? This behaviour does not seem logical to me, especially since the problem is not loading images/scripts/stylesheets from the jar archive, but the resolution of the relative paths.
I also wonder if that problem does not exist in all Java/JavaFX versions. I use use the openjdk-8
and openjfx 8
packages on Ubuntu 16.04.3. In this question, it seems like the author can load a JS script via a relative URL: JavaFX WebView does not load upper folder script in jar . It seems that the author of this post javafx 2 webview custom url handler, don't work relative url dealt with the same issue and circumvented it by creating his own protocol handler. A better explanation of what to do can be found in this answer.
At the moment, my best option seems to be to not include my web resources in the jar archive, so that they can be accessed via the file
protocol.