Executable jar can't find or load main class a

2019-02-28 07:40发布

问题:

I used the gluon plugin to create a new single view project and changed nothing in its files. If I use the gradle task application > run it works fine. But if I use the taks build > jar it created the jar under SingleViewProject\build\libs and when I run it from the command line i get

Error: Could not find or load main class com.gluonapplication.GluonApplication

This is the untouched build.gradle:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.1.1'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'com.gluonapplication.GluonApplication'

dependencies {
    compile 'com.gluonhq:charm:4.1.0'
}

jfxmobile {
    downConfig {
        version = '3.0.0'
        plugins 'display', 'lifecycle', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

and the "main class":

package com.gluonapplication;

import com.gluonhq.charm.glisten.application.MobileApplication;
import com.gluonhq.charm.glisten.visual.Swatch;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

public class GluonApplication extends MobileApplication {

    public static final String BASIC_VIEW = HOME_VIEW;

    @Override
    public void init() {
        addViewFactory(BASIC_VIEW, () -> new BasicView(BASIC_VIEW));
    }

    @Override
    public void postInit(Scene scene) {
        Swatch.BLUE.assignTo(scene);

        ((Stage) scene.getWindow()).getIcons().add(new Image(GluonApplication.class.getResourceAsStream("/icon.png")));
    }
}

It's true that there is no main method in the class but you shouldn't need one. And it runs fine straight from the IDE. What's the problem?

回答1:

When you execute the jar task on a Gluon project, you will get just a jar with the classes and resources under the main and desktop packages of your project. In your case, something like this:

That jar contains the main class, but it doesn't contain any of the dependencies (Gluon Charm).

If you want to create an executable jar, you need to create a shadowJar or fatJar, that bundles all the dependencies within that jar.

You can add this plugin for it: com.github.johnrengelman.shadow, based on this project.

Once you add the plugin, all you need to do is let it know about your custom configurations, as it doesn't know about the Desktop one.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.1.1'
        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
    }
}

apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'com.github.johnrengelman.shadow'

...

// Add desktop dependencies to the task
shadowJar {
    configurations = [project.configurations.desktopRuntime]
}

Reload your project and execute shadowJar. You can find it under the Tasks menu:

You will find your executable jar under /builds/libs/yourProjectName-all.jar.