如何将MigLayout for JavaFX转换为OSGi包,使其在OSGi容器中工作?
我正在尝试制作一个OSGi包,它是一个用JavaFX编写的GUI。我的设置如下:如何将MigLayout for JavaFX转换为OSGi包,使其在OSGi容器中工作?,javafx,osgi,apache-felix,equinox,miglayout,Javafx,Osgi,Apache Felix,Equinox,Miglayout,我正在尝试制作一个OSGi包,它是一个用JavaFX编写的GUI。我的设置如下: OS name: "linux", version: "3.8.0-25-generic", arch: "amd64", family: "unix" Java version: 1.7.0_45, vendor: Oracle Corporation Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 10:22:22
OS name: "linux", version: "3.8.0-25-generic", arch: "amd64", family: "unix"
Java version: 1.7.0_45, vendor: Oracle Corporation
Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 10:22:22-0500)
我按照javafxmaven插件提供的说明进行操作。我使用ApacheFelix作为OSGi容器。所有这些结合在一起效果相当不错。(即:我可以将javafxgui创建为一个OSGi包,它可以工作!)
我遇到的问题是JavaFX的MigLayout库。我正在使用这些依赖项:
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-core</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-javafx</artifactId>
<version>4.2</version>
</dependency>
下面是我尝试加载的示例fxml文件login.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>
<?import org.tbee.javafx.scene.layout.fxml.MigPane?>
<StackPane xmlns:fx="http://javafx.com/fxml" fx:controller="client.view.LoginView" fx:id="pane">
<children>
<Button text="Login" fx:id="loginButton" onAction="#login"/>
</children>
</StackPane>
miglayout-core-4.2.jar MANIFEST.MF:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Bnd-LastModified: 1384015623755
Build-Jdk: 1.6.0_29
Built-By: Mike
Bundle-ManifestVersion: 2
Bundle-Name: miglayout.core
Bundle-SymbolicName: miglayout.core
Bundle-Version: 0
Created-By: 1.7.0_45 (Oracle Corporation)
Export-Package: net.miginfocom.layout
Originally-Created-By: Apache Maven
Tool: Bnd-2.1.0.20130426-122245
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Bnd-LastModified: 1384015600603
Build-Jdk: 1.6.0_29
Built-By: Mike
Bundle-ManifestVersion: 2
Bundle-Name: miglayout.javafx
Bundle-SymbolicName: miglayout.javafx
Bundle-Version: 0
Created-By: 1.7.0_45 (Oracle Corporation)
Export-Package: org.tbee.javafx.scene.layout;uses:="javafx.scene,javafx.
scene.layout,net.miginfocom.layout",org.tbee.javafx.scene.layout.fxml;u
ses:="javafx.beans,javafx.scene,net.miginfocom.layout,org.tbee.javafx.s
cene.layout"
Import-Package: javafx.beans;resolution:=optional,javafx.collections;res
olution:=optional,javafx.geometry;resolution:=optional,javafx.scene;res
olution:=optional,javafx.scene.control;resolution:=optional,javafx.scen
e.layout;resolution:=optional,javafx.scene.paint;resolution:=optional,j
avafx.scene.shape;resolution:=optional,javafx.stage;resolution:=optiona
l,net.miginfocom.layout;resolution:=optional
Originally-Created-By: Apache Maven
Tool: Bnd-2.1.0.20130426-122245
miglayout-javafx-4.2.jar MANIFEST.MF:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Bnd-LastModified: 1384015623755
Build-Jdk: 1.6.0_29
Built-By: Mike
Bundle-ManifestVersion: 2
Bundle-Name: miglayout.core
Bundle-SymbolicName: miglayout.core
Bundle-Version: 0
Created-By: 1.7.0_45 (Oracle Corporation)
Export-Package: net.miginfocom.layout
Originally-Created-By: Apache Maven
Tool: Bnd-2.1.0.20130426-122245
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Bnd-LastModified: 1384015600603
Build-Jdk: 1.6.0_29
Built-By: Mike
Bundle-ManifestVersion: 2
Bundle-Name: miglayout.javafx
Bundle-SymbolicName: miglayout.javafx
Bundle-Version: 0
Created-By: 1.7.0_45 (Oracle Corporation)
Export-Package: org.tbee.javafx.scene.layout;uses:="javafx.scene,javafx.
scene.layout,net.miginfocom.layout",org.tbee.javafx.scene.layout.fxml;u
ses:="javafx.beans,javafx.scene,net.miginfocom.layout,org.tbee.javafx.s
cene.layout"
Import-Package: javafx.beans;resolution:=optional,javafx.collections;res
olution:=optional,javafx.geometry;resolution:=optional,javafx.scene;res
olution:=optional,javafx.scene.control;resolution:=optional,javafx.scen
e.layout;resolution:=optional,javafx.scene.paint;resolution:=optional,j
avafx.scene.shape;resolution:=optional,javafx.stage;resolution:=optiona
l,net.miginfocom.layout;resolution:=optional
Originally-Created-By: Apache Maven
Tool: Bnd-2.1.0.20130426-122245
但是将生成的“bundle”放在OSGi容器中并不能解决问题。我也犯了同样的错误
我不知道还能尝试什么,这样我就可以使用OSGi容器中的MigLayout库了
我需要做什么才能在OSGi容器中使用MigLayout
编辑
下面是加载FXML的代码。它是用Scala编写的
package client
import _root_.javafx.application.Application
import _root_.javafx.stage.Stage
import _root_.javafx.scene.{Parent, Scene}
import _root_.javafx.fxml.FXMLLoader
import client.view.{Login, Screen}
class Gui extends Application {
def start(stage: Stage) {
val initialScreen: Screen = Login
stage.setTitle("GUI")
val loader = new FXMLLoader
loader.setLocation(initialScreen.url)
try {
val root: Parent = loader.load(initialScreen.inputStream).asInstanceOf[Parent]
val scene: Scene = new Scene(root, 800, 600)
scene.getStylesheets.add("/fxml/styles/styles.css")
stage.setScene(scene)
stage.show()
} catch {
case t: Throwable => t.printStackTrace()
}
}
override def stop() {
System.out.println("Stopping JavaFX Application")
Container.shutdown()
}
}
另外,这里是为客户端定义的导入包。这个构建实际上是使用scala和osgi插件与gradle一起完成的
build.gradle的代码片段:
def importPackages =
' akka.actor' +
', akka.actor.dungeon' +
', akka.event' +
', akka.osgi' +
', javafx.application' +
', javafx.beans' +
', javafx.collections' +
', javafx.fxml' +
', javafx.geometry' +
', javafx.scene' +
', javafx.scene.control' +
', javafx.scene.image' +
', javafx.scene.layout' +
', javafx.scene.paint' +
', javafx.scene.shape' +
', javafx.stage' +
', net.miginfocom.layout' +
', org.osgi.framework' +
', org.tbee.javafx.scene.layout' +
', org.tbee.javafx.scene.layout.fxml' +
', scala' +
', scala.collection' +
', scala.reflect' +
', scala.runtime'
jar {
manifest {
name = "client (OSGi bundle)"
instruction 'Bundle-Vendor', 'Company'
instruction 'Bundle-Description', 'Client (OSGi bundle)'
instruction 'Private-Package', 'client'
instruction 'Bundle-Activator', 'client.ClientActivator'
instruction 'Import-Package', importPackages
}
}
def importPackages =
' akka.actor' +
', akka.actor.dungeon' +
', akka.event' +
', akka.osgi' +
', javafx.application' +
', javafx.beans' +
', javafx.collections' +
', javafx.fxml' +
', javafx.geometry' +
', javafx.scene' +
', javafx.scene.control' +
', javafx.scene.image' +
', javafx.scene.layout' +
', javafx.scene.paint' +
', javafx.scene.shape' +
', javafx.stage' +
', net.miginfocom.layout' +
', org.osgi.framework' +
', org.tbee.javafx.scene.layout' +
', org.tbee.javafx.scene.layout.fxml' +
', scala' +
', scala.collection' +
', scala.reflect' +
', scala.runtime'
编辑2
我根据tomsontom的建议修改了加载fxml的代码,以设置类加载器。以下是更新的代码:
build.gradle中的代码段:
def importPackages =
' akka.actor' +
', akka.actor.dungeon' +
', akka.event' +
', akka.osgi' +
', javafx.application' +
', javafx.beans' +
', javafx.collections' +
', javafx.fxml' +
', javafx.geometry' +
', javafx.scene' +
', javafx.scene.control' +
', javafx.scene.image' +
', javafx.scene.layout' +
', javafx.scene.paint' +
', javafx.scene.shape' +
', javafx.stage' +
', net.miginfocom.layout' +
', org.osgi.framework' +
', org.tbee.javafx.scene.layout' +
', org.tbee.javafx.scene.layout.fxml' +
', scala' +
', scala.collection' +
', scala.reflect' +
', scala.runtime'
jar {
manifest {
name = "client (OSGi bundle)"
instruction 'Bundle-Vendor', 'Company'
instruction 'Bundle-Description', 'Client (OSGi bundle)'
instruction 'Private-Package', 'client'
instruction 'Bundle-Activator', 'client.ClientActivator'
instruction 'Import-Package', importPackages
}
}
def importPackages =
' akka.actor' +
', akka.actor.dungeon' +
', akka.event' +
', akka.osgi' +
', javafx.application' +
', javafx.beans' +
', javafx.collections' +
', javafx.fxml' +
', javafx.geometry' +
', javafx.scene' +
', javafx.scene.control' +
', javafx.scene.image' +
', javafx.scene.layout' +
', javafx.scene.paint' +
', javafx.scene.shape' +
', javafx.stage' +
', net.miginfocom.layout' +
', org.osgi.framework' +
', org.tbee.javafx.scene.layout' +
', org.tbee.javafx.scene.layout.fxml' +
', scala' +
', scala.collection' +
', scala.reflect' +
', scala.runtime'
fxml加载代码:
def start(stage: Stage) {
val initialScreen: Screen = Login
stage.setTitle("GUI")
val loader = new FXMLLoader
loader.setClassLoader(getClass.getClassLoader)
loader.setLocation(initialScreen.url)
try {
val root: Parent = loader.load(initialScreen.inputStream).asInstanceOf[Parent]
val scene: Scene = new Scene(root, 800, 600)
scene.getStylesheets.add("/fxml/styles/styles.css")
stage.setScene(scene)
stage.show()
} catch {
case t: Throwable => t.printStackTrace()
}
}
但请注意,现在在OSGi容器中运行应用程序时,我收到了一条类似但不同的错误消息:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>
<!--<?import org.tbee.javafx.scene.layout.fxml.MigPane?>-->
<StackPane xmlns:fx="http://javafx.com/fxml" fx:controller="client.view.LoginView" fx:id="pane">
<children>
<Button text="Login" fx:id="loginButton" onAction="#login"/>
</children>
</StackPane>
javafx.fxml.LoadException: java.lang.ClassNotFoundException: org.tbee.javafx.scene.layout.fxml.MigPane
at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2489)
at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2333)
at javafx.fxml.FXMLLoader.processProcessingInstruction(FXMLLoader.java:2301)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2154)
at client.Gui.start(Gui.scala:23)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:216)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:89)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: org.tbee.javafx.scene.layout.fxml.MigPane
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.apache.felix.framework.ExtensionManager$ExtensionManagerWiring.getClassByDelegation(ExtensionManager.java:873)
at org.apache.felix.framework.BundleWiringImpl.searchImports(BundleWiringImpl.java:1553)
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1484)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at javafx.fxml.FXMLLoader.loadTypeForPackage(FXMLLoader.java:2557)
at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2546)
at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2487)
... 14 more
它仍在生成ClassNotFoundException。但这一次,堆栈跟踪不包括任何与跟踪来自哪个包有关的内容。这是一个微妙的区别,我不知道这意味着什么。有什么想法吗
编辑3
在使用bnd命令行实用程序之后,我修改了OP,以包含为这两个MigLayout依赖项生成的MANIFEST.MF文件
编辑4
client.jar MANIFEST.MF
(请注意,我的包实际上是x.x.client,而不仅仅是client。但是我已经从包名中删除了x.x.,这就是这个MANIFEST.MF文件中行距不一致的原因):
编辑5
我创建了一个,你可以下载看看问题。正如当前签入的一样,如果您按照文件README.txt中的说明进行操作,则在签出该项目后,该项目应立即运行
如果您想查看我在MigLayout库中遇到的问题,请通过取消对MigPane导入的注释来编辑文件
client/src/main/resources/fxml/login.fxml
。重建项目,将新创建的client-1.0.0-SNAPSHOT.jar复制到app/bundle/
目录,使用$rm-rf app/felix cache/
清除felix缓存目录,然后使用命令$java-jar bin/felix.jar
从app
目录中重新启动felix启动器。您还需要在UI包中包含相应的导入包语句。创建这些文件的最简单方法是在UI包的pom中使用
无论您是否使用bundle插件,都要检查生成的清单,以确保所有nevassery Import包语句都存在。我99%确定在fxml中,您的问题是没有设置正确的类加载器。请显示您的fxml加载代码是的,我应该在OP中包含该代码。我在客户端捆绑包中有导入语句。我不明白为什么它不起作用。唯一的另一个想法是,可能midlayout核心没有Import-Package语句,而异常发生在一个miglayout核心类中,当然它使用自己的类加载器。这不会产生不同的错误消息吗,有关无法将捆绑包连接在一起的问题?如果存在导入包语句,但没有捆绑包导出它,则会发生有关解析失败的错误。如果缺少Import-Package语句,但该包仍在使用,则会出现运行时ClassNotFoundException,如您的情况。好的,我看到您已更新,是的,您需要在fxmlloader实例上调用setClassloader。如果您考虑一下,您的代码在OSGi中必须失败,因为FXMLLoader位于extclassloader中,而extclassloader自然不知道OSGi捆绑包中的migpane。我应该将哪个类装入器传递给setClassloader?在OSGi包中它来自哪里?保存加载代码的包必须依赖于migpane,然后传递这个包。如果在java类中实现fxml文件中的内容,您需要考虑如何配置包,因此您还应该导入所有javafx包!您将获得一个类加载器,它是getClass()。getClassloader()谢谢您的帮助。我认为这几乎解决了,但它仍然造成了一个问题。请参阅我再次更新了OP。您没有显示ui包的清单。我建议从纯java/scala开始,然后向其中添加fxml