简体   繁体   English

如何启动JavaFx OSGi捆绑包

[英]How to start a JavaFx OSGi bundle

I'm trying to run a JavaFx OSGi module, but I keep getting the error: 我正在尝试运行JavaFx OSGi模块,但我不断收到错误消息:

org.osgi.framework.BundleException: Unable to resolve OSGiDmHelloWorldProvider [7](R 7.0): missing requirement [OSGiDmHelloWorldProvider [7](R 7.0)] osgi.wiring.package; (osgi.wiring.package=javafx.application) Unresolved requirements: [[OSGiDmHelloWorldProvider [7](R 7.0)] osgi.wiring.package; (osgi.wiring.package=javafx.application)]
    at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4112)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:2118)
    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
    at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)

This is how I load and start the modules: 这是我加载和启动模块的方式:

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;

import java.io.File;
import java.util.*;


public class Launcher {

    private static String[] libs = null;

    private BundleContext context;

    private Launcher() {

        FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();

        Map<String, String> config = new HashMap<String, String>();
        config.put("osgi.console", "");
        config.put("osgi.clean", "true");
        config.put("osgi.noShutdown", "true");
        config.put("eclipse.ignoreApp", "true");
        config.put("osgi.bundles.defaultStartLevel", "4");
        config.put("osgi.configuration.area", "./configuration");

        // automated bundles deployment
        config.put("felix.fileinstall.dir", "./dropins");
        config.put("felix.fileinstall.noInitialDelay", "true");
        config.put("felix.fileinstall.start.level", "4");

        config.put(Constants.FRAMEWORK_BOOTDELEGATION, "javafx.*,com.sun.javafx.*");
        config.put(Constants.FRAMEWORK_BUNDLE_PARENT, Constants.FRAMEWORK_BUNDLE_PARENT_APP);

        Framework framework = frameworkFactory.newFramework(config);

        try {
            framework.init();
            framework.start();
        } catch (BundleException e) {
            e.printStackTrace();
        }

        context = framework.getBundleContext();

        Bundle OSGiDmHelloWorldProvider = install("OSGiDmHelloWorldProvider");
        try {

            OSGiDmHelloWorldProvider.start();

        } catch (BundleException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Launcher();
    }

    private String[] getLibs() {
        if (libs == null) {
            List<String> jarsList = new ArrayList<String>();
            File pluginsDir = new File("libs");

            System.out.println("PATHS : " + pluginsDir.getAbsolutePath());

            for (String jar : pluginsDir.list()) {
                jarsList.add(jar);
            }
            libs = jarsList.toArray(new String[jarsList.size()]);
        }
        return libs;
    }

    protected Bundle install(String name) {
        String found = null;

        for (String jar : getLibs()) {
            if (jar.startsWith(name)) {
                found = String.format("file:libs/%s", jar);
                System.out.println(found);
                break;
            }
        }
        if (found == null) {
            throw new RuntimeException(String.format("JAR for %s not found", name));
        }
        try {
            return context.installBundle(found);
        } catch (BundleException e) {
            e.printStackTrace();
        }
        return null;
    }
}

The OSGiDmHelloWorldProvider Activator class: OSGiDmHelloWorldProvider Activator类:

import com.bw.osgi.provider.able.HelloWorldService;
import com.bw.osgi.provider.impl.HelloWorldServiceImpl;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProviderActivator implements BundleActivator {

    Logger logger = LoggerFactory.getLogger(ProviderActivator.class);

    Stage stage;

    private ServiceRegistration registration;
    BundleContext bundleContext;

    @Override
    public void start(BundleContext bundleContext) throws Exception {
        registration = bundleContext.registerService(
                HelloWorldService.class.getName(),
                new HelloWorldServiceImpl(),
                null);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                stage = new Stage();
                BorderPane pane = new BorderPane();
                Scene scene = new Scene(pane, 400, 200);
                pane.setCenter(new Label("This is a JavaFX Scene in a Stage"));
                stage.setScene(scene);
                stage.show();
            }
        });

        System.out.println("STAGE CALLED !!!");
    }

    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        registration.unregister();

        logger.info("Set4Jfx Bundle: stop()");
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                stage.close();
            }
        });
    }
}

How can I load a module that uses JavaFx in a Maven OSGi application? 如何在Maven OSGi应用程序中加载使用JavaFx的模块?

Thank you all in advance. 谢谢大家。

The error message means that your bundle imports package javafx.application , and no bundle exports that package. 该错误消息表示您的捆绑软件导入了软件包javafx.application ,而没有捆绑软件导出了该软件包。 Therefore the import cannot be resolved. 因此,导入无法解决。

I note that in your launcher code you try to set bootdelegation to javafx.* . 我注意到在启动器代码中,您尝试将bootdelegation设置为javafx.* That might allow the class to be loaded from the boot classpath if your bundle ever got as far as running, however it cannot get that far because of the unresolved import. 如果您的捆绑软件可以运行,那么这可能允许从引导类路径中加载类,但是由于无法解析的导入,它无法做到这一点。

If you intend for the JavaFX classes to be loaded from the boot classloader then you should remove the package import from your own bundle. 如果打算从引导类加载器中加载JavaFX类,则应从自己的包中删除软件包导入。 You would also have to arrange for the JavaFX classes to actually be provided by the boot classloader, since AFAIK they are normally only visible from the extension classloader. 您还需要安排JavaFX类由引导类加载器实际提供,因为AFAIK通常仅在扩展类加载器中可见。

However a better solution would be leave the import alone, and arrange for the javafx.application package to be exported from a bundle. 但是,更好的解决方案是将导入保留javafx.application ,并安排从捆绑包中导出javafx.application包。 That could be done from the system bundle using Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA . 可以使用Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA从系统捆绑包中完成。

Update 更新资料

You should probably look at the Drombler FX tool/framework from @Puce, since it sounds like he has already done a lot of these setup tasks. 您可能应该看看@Puce的Drombler FX工具/框架,因为听起来他已经完成了许多设置任务。 However I felt that his answer didn't directly address your question about why your code was failing. 但是,我感到他的回答并没有直接解决您的有关代码为何失败的问题。

I've released some first versions of Drombler FX - the modular application framework for JavaFX based on OSGi and Maven (POM first). 我已经发布了Drombler FX的一些第一个版本-基于OSGi和Maven的JavaFX模块化应用程序框架(首先是POM)。

It takes care of initializing JavaFX and OSGi. 它负责初始化JavaFX和OSGi。

Maybe you find it useful. 也许您觉得它有用。 The application framework is Open Source and the code is available on GitHub . 该应用程序框架是开放源代码,其代码可在GitHub上获得

There is also a tutorial with a Getting Started trail. 还有一个带有入门指南教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM