Moritz
Moritz

Reputation: 41

Browser HEAVYWEIGHT not visible on the scene

I'm trying to embedd the JXBrowser into a SpringBoot JavaFX Application running with Java11. My Problem is that the browser is not shown on the scene when I run the application from the created executable jar. The browser is loaded, gives feedback about the loaded website and is already part of the scene, but not visible. Running inside IntelliJ or with Maven exec is currently working. When I switch the browser mod to LIGHTWEIGHT than all of the three run possibilities are working fine. What is the the Problem with running from jar in HEAVYWEIGHT mod?

My system: Windows10-64, Java11, SpringBoot 2.1.0.RELEASE, JXBrowser 6.21, OpenJFX 11

Main.class

@Slf4j
@SpringBootApplication
public class Main extends Application
{

private ConfigurableApplicationContext springContext;



public static void main(final String[] args)
{
    Application.launch(args);
}



@Override
public void init()
{
    springContext = SpringApplication.run(Main.class);
    springContext.getAutowireCapableBeanFactory().autowireBean(this);
}



@Override
public void start(Stage stage)
{
    final Browser browser = new Browser();
    stage.setScene(new Scene(new BrowserView(browser)));
    stage.show();
    browser.loadURL("http://www.google.de");
}



@Override
public void stop()
{
    springContext.close();
}

}

StartMain.class

public class StartMain
{
public static void main(String[] args)
{
    Main.main(args);
}

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://maven.apache.org/POM/4.0.0"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">

<groupId>de</groupId>
<artifactId>app</artifactId>
<version>1.0.10-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.RELEASE</version>
    <relativePath/>
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>11</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <jxbrowser.version>6.21</jxbrowser.version>
    <javafx.version>11</javafx.version>
</properties>

<repositories>
    <repository>
        <id>com.teamdev</id>
        <url>http://maven.teamdev.com/repository/products</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.teamdev.jxbrowser</groupId>
        <artifactId>jxbrowser-cross-platform</artifactId>
        <type>pom</type>
        <version>${jxbrowser.version}</version>
    </dependency>
    <dependency>
        <groupId>com.teamdev.jxbrowser</groupId>
        <artifactId>jxbrowser-win64</artifactId>
        <version>${jxbrowser.version}</version>
    </dependency>

    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-base</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-swing</artifactId>
        <version>${javafx.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeSystemScope>true</includeSystemScope>
                <mainClass>...StartMain</mainClass>
                <layout>ZIP</layout>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Upvotes: 4

Views: 459

Answers (1)

Jos&#233; Pereda
Jos&#233; Pereda

Reputation: 45476

I've managed to build the project, and getting a trial license I can run it. As you mentioned, running from the IDE, or from command line mvn compile exec:exec (I've also tried with Gradle, ./gradlew run, adding the required --add-exports), works perfectly fine, the browser is displayed and the given URL loaded.

However, as you said, if you create a fat jar and run it, it doesn't display the browser, but JavaFX works, and you can see some activity going on, only no rendering.

I've tried under JDK 8, 9, 10 and 11. Only under 8 I could get the fat jar to display the browser.

Using a fat jar is a bad practice in general, and now even worse as you have to include the JavaFX classes from the JavaFX SDK.

A better way to distribute your application is by using jlink.

Given that com.teamdev.jxbrowser:jxbrowser is not modular, you can't fully use jlink with your project, but you can create a custom runtime image only with the JavaFX modules, and use that to run your app with the only dependency of jxBrowser (for convenience I'm not using SpringBoot).

So if you download the JavaFX jmods from here, unzip them and run:

export PATH_TO_FX_MODS=/path-to/javafx-jmods-11

$JAVA_HOME/bin/jlink --module-path $PATH_TO_FX_MODS \
  --add-modules=java.se,javafx.web,javafx.fxml,javafx.swing \
  --output jre

you will create a JRE that contains JavaFX.

Then you can run your project, including your dependencies in the classpath:

jre/bin/java -cp \
  /Users/<user>/.gradle/caches/modules-2/files-2.1/com.teamdev.jxbrowser/jxbrowser/6.22/c9...6b/jxbrowser-6.22.jar:\
  /Users/<user>/.gradle/caches/modules-2/files-2.1/com.teamdev.jxbrowser/jxbrowser-mac/6.22/fa...d4/jxbrowser-mac-6.22.jar:\
  build/libs/browserApp.jar jxbrowser.BrowserApp 

This works fine as well, the browser is displayed. So we discard that there could be any issue with JavaFX 11.

Now we can still do a small fat jar with the project and jxBrowser dependencies. And then if you run:

jre/bin/java -cp build/libs/browserApp.jar jxbrowser.BrowserApp

as you can imagine, this won't work, the browser won't show up.

So my final conclusion is that adding a fat jar even only with the two jxBrowser dependencies doesn't work.

See for instance this post about possible causes for this:

There can be files with the same path present in multiple JARs and by default the shade plugin includes the first file in the fat JAR and discards the rest.

So I'd suggest you file an issue to the project issue tracker, if exists, and I'd also suggest you find a way to run your app without fat-jars.

Upvotes: 4

Related Questions