Hi, I'm trying to repackage JOGL as an OSGi bundle.
Currently, I repack all the gluegen and JOGL code jars into a single jar. Then, I deploy that jar as an OSGi bundle after wrapping it with the bnd tool to add the Export-Package metadata. However, I'm not sure where the jars containing the native libraries should go. I could create a jar containing all the .dll, .so, and .jnilib files and make it an OSGi fragment and add Bundle-NativeCode metadata. But that didn't seem to work. What are some working ways that you have used to turn JOGL into OSGi bundles? Thanks, Programmer |
Administrator
|
Hi
I make a separate bundle for GlueGen and JOGL Java classes and I put native libraries into separate bundles (JOGLLib.linux64, JOGLLib.win32, JOGLLib.win64, etc...). Maybe Wade can help you. I don't have any working copy of my bundles at home :s
Julien Gouesse | Personal blog | Website
|
Administrator
|
In reply to this post by Jar
In my tutorial at http://wadeawalker.wordpress.com/2010/10/09/tutorial-a-cross-platform-workbench-program-using-java-opengl-and-eclipse/, I show how to put JOGL into a form that can be deployed as an Eclipse RCP project, which I assume is similar to how it would work in a raw OSGi project. The trick I use is creating a project/bundle for JOGL that contains the gluegen and JOGL JARs, then creating fragment projects/bundles for each of the native platforms. At runtime, OSGi loads the correct fragment for the platform.
I believe that new development builds of JOGL have all the native libraries for all platforms available in one big JAR -- if so, you could just make one single JOGL bundle with all the JARs in it, without using native fragments. But I haven't tried it this way yet. |
I am using jogl with Apache Karaf. However, I cannot make Karaf to recognize libgluegen-rt.jnilib. I've spent last two days trying several approaches without success.
One of the approaches I tried was to deploy jogl-all-main, gluegen-rt-main and all of their dependants in the hot deploy directory. The errors are here: http://pastie.org/pastes/7814616 I was suggested to make a gigantic bundle with all the native jars and java-only jars. I tried that too, but then karaf complains doesn't start the bundle and when I try to start it, I get an error message that it cannot find native libraries. I tried to bundle the jars with native libraries (on Mac OS X, they are distributed as jnilib files): $ cat propNative.bnd -classpath: gluegen-rt-2.0-rc11-natives-macosx-universal.jar, jogl-all-2.0-rc11-natives-macosx-universal.jar Bundle-SymbolicName: jogl-gluegen-macosx ver: 2.0-rc11 -output: ${bsn}-${ver}.jar Bundle-Version: ${ver} Export-Package: *;version=${ver} Bundle-NativeCode: libgluegen-rt.jnilib ; libnativewindow_macosx.jnilib ; libjogl_desktop.jnilib ; libjogl_mobile.jnilib ; libnativewindow_awt.jnilib ; libnewt.jnilib ; osname=MacOS ; processor=x86-64 , * # Uncomment next line to customise imports. The last entry MUST be "*" # Import-Package: * ### By the way, mybnd is just an alias for java -jar /path/to/bnd.jar; bndlib.jar is in my classpath oscars-imac:macosxBundle oscarvarto$ mybnd propNative.bnd ----------------- Warnings 000: propNative.bnd: The JAR is empty: The instructions for the JAR named jogl-gluegen-macosx did not cause any content to be included, this is likely wrong So maybe my problem is that I don't know how to embed jnilibs in an osgi bundle??? I see your comment: The trick I use is creating a project/bundle for JOGL that contains the gluegen and JOGL JARs, then creating fragment projects/bundles for each of the native platforms. At runtime, OSGi loads the correct fragment for the platform. but I guess I don't know how to what you suggest (little experience with osgi). Please I need help! I've been trying for a lot of time without success. |
Administrator
|
Hi
JOGL 2 tries to extract the native libraries somewhere but it seems not to be allowed in your case, then you get a IOException.
Julien Gouesse | Personal blog | Website
|
Administrator
|
In reply to this post by Oscar Vargas Torres
Recently, I successfully used JOGL's native library JARs in an Eclipse RCP project, with the help of a new fix to JarUtil. I'm not sure if it will work in Karaf the same way, but it might.
First, you add the JOGL native library JAR files (e.g. gluegen-rt-natives-linux-amd64.jar and jogl-all-natives-linux-amd64.jar if you're in 64-bit Linux) into an OSGi bundle somehow. In an Eclipse project, this means adding them to a plugin, but in Karaf it may work differently. You can add the JARs for all 5 platforms if you want, or just for the platform you're running on. Then you add this code to your project so it runs before JOGL is invoked: JarUtil.setResolver( new JarUtil.Resolver() { public URL resolve( URL url ) { try { System.out.print( "before resolution: " + url.toString() ); return( FileLocator.resolve( url ) ); } catch( IOException ioexception ) { return( url ); } } } ); FileLocator is an Eclipse class from org.eclipse.core.runtime, there may be something similar in Karaf. It converts OSGi "bundleresource:" URLs into "file:" URLs that JOGL can use internally to unpack its .so/.dll/.jnilib files (more details at https://jogamp.org/bugzilla/show_bug.cgi?id=687). To debug this, you can just return the unresolved URL above and look at what's printed -- if they are bundleresource: or some other type of URL than file:, they need to be resolved somehow or JOGL can't find them. |
Administrator
|
Thank you Wade, this is the typical kind of tip that should be added into our Wiki or into the user's guide.
Julien Gouesse | Personal blog | Website
|
In reply to this post by Wade Walker
I have been trying to follow your advice but need additional help.
you add the JOGL native library JAR files (e.g. gluegen-rt-natives-linux-amd64.jar and jogl-all-natives-linux-amd64.jar if you're in 64-bit Linux) into an OSGi bundle ***somehow*** I have been trying to do that with bnd and the terminal, using a properties.bnd file. Then bnd warns that an empty output file is generated (maybe because there are no classes there, only jnilib files). I added a Include-Resource header to force bnd to include the jnilib files. I tried to do that with Eclipse bndtools and Eclipse RCP but I keep getting the same old error: no gluegen-rt library in java.library.path. I tried to add the java code you posted but I cannot get this to compile: new JarUtil.Resolver() I am using the files here http://search.maven.org/#artifactdetails|org.jogamp.gluegen|gluegen-rt|2.0-rc11|jar Maybe I am supposed to use a newer version of jogamp-all-platforms.7z ... Could you please, give me more detailed help? I have been trying another day and this is driving me nutts! |
In reply to this post by Wade Walker
I found your own Tutorial at http://wadeawalker.wordpress.com/2010/10/09/tutorial-a-cross-platform-workbench-program-using-java-opengl-and-eclipse/
I could successfully follow your instructions there (with eclipse 3.8). I am reeeeeaaaaaaallllly thankful for that tutorial. I am developing my application mostly in Scala, so maybe I'll come back again... |
Administrator
|
Glad you found the tutorial helpful! The JarUtil.setResolver() shows up in nightly builds of JOGL, I don't think it's made it into an official release yet, so you'd need to use a version from http://jogamp.org/deployment/autobuilds/master/.
My tutorial does things the "old fashioned" way, with a fragment bundle for each platform. If you use JarUtil.setResolver(), you can put all 5 platforms of native JARs into the com.jogamp.jogl project, and remove all 5 fragment projects. I've got an example in GitHub at https://github.com/WadeWalker/com.jogamp.jogl. I usually put the JarUtil.setResolver() call in createPartControl() of the editor. If you use it, you also need to make sure you're not calling GLProfile.initSingleton() in a static block anywhere, since it would be run before the resolver is set. |
Wade - would you be able to give an example of an implementation of the interface Resolver?
I am not sure how to set the protocol for use with RCP in the URL return value? Thanks for any help you can give! |
Administrator
|
The resolver I use in Eclipse RCP apps looks like this:
JarUtil.setResolver( new JarUtil.Resolver() { public URL resolve( URL url ) { try { return( FileLocator.resolve( url ) ); } catch( IOException ioexception ) { return( url ); } } } ); where org.eclipse.core.runtime.FileLocator is a part of Eclipse's framework code. FileLocator.resolve(url) converts the URL from an Eclipse/OSGi "bundleresource:" URL protocol (which is how Eclipse locates JARs/libraries that have been packaged into OSGi bundles) to a normal "file:" URL protocol that JOGL and other non-Eclipse code can use. The purpose of the Resolver interface is to allow dependency injection, so JOGL can indirectly call this Eclipse/OSGi FileLocator.resolve() method without directly depending on an outside framework's code. In any given situation where your framework uses non-standard URL protocols, just wrap a Resolver around your framework's URL resolver and JOGL's auto-JAR-unpack feature should work correctly. |
Thanks, Wade!, this got me farther down the path, but now I am getting a runtime exception on starting my Editor because of: Caused by: java.lang.ClassNotFoundException: com.jogamp.common.util.JarUtil$Resolver at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412) at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) ... 112 more I have the gluegen-rt.jar and the jogl-all.jar in my com.jogamp.jogl bundle, along with the appropriate native code jars, I have all the packages in these two jars in the export list, and my application *builds* successfully against it. Anything else I should look at? Thanks for the response and anything else you can think of... |
Administrator
|
Hmm, that is strange that it's a runtime exception and not found at compilation time. There are a couple of things to check:
- Make sure your com.jogamp.jogl bundle is in your plugin.xml dependencies - Make sure your com.jogamp.jogl bundle is also in your <project>.product dependencies (if your plugin.xml was correct, it should have been put there automatically when you created the <project>.product file) - Double-check that you're using a version of JOGL that actually contains JarUtil$Resolver (it's pretty recent, so it might still only be in a nightly build, though it shouldn't compile if that wasn't right) The first two are the most likely -- Eclipse may check dependencies differently for compilation than OSGi does at runtime. Also, just as a reference: I'm setting up the resolver in my editor's createPartControl(), before any JOGL code is called, and I'm not using a static code block anywhere to call GLProfile.initSingleton(). |
Thanks again, Wade - yes, it was the first one. I think everything is working right now on the jogl plugin and its native code. Unfortunately, I am now seeing: !ENTRY org.eclipse.e4.ui.workbench 4 0 2013-05-29 16:33:05.518 !MESSAGE Unable to create class 'org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor' from bundle '428' !STACK 0 org.eclipse.e4.core.di.InjectionException: java.lang.NoSuchMethodError: javax.media.opengl.GLContext.setSynchronized(Z)V at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:63) at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:861) at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:841) ... which I believe I have tracked down to an incompatibility in the version of jogl I am using to utilize the JarUtils.setResolver() and native code mechanism and the version of jogl I apparently need to use with the third party code that is part of my application. It is actually the third party code that actually utilizes jogl, and they ship a specific version - the jars are dated 12/19/2012, which is their release date, and I suspect that the jogl code that is included is from the 11/2012 release that seems to still be the current official release on the website. I found the javax.media.opengl.GLContext.setSynchronized() in their jogl jar and not in the one I have been using from 3/2013. I will keep looking into it - it may be that there is a simple interface change I can make an adapter for, but I suspect that I am going to have to go back to the fragment method. (which I haven't gotten working yet either, but I should be able to with your tutorial :-)) |
I got the fragment bundle method working.
One thing that I did want to point out is that, because of https://jogamp.org/bugzilla/show_bug.cgi?id=537 , I had to set jogamp.gluegen.UseTempJarCache to false to get this to work - otherwise jogl does not handle falling back from attempting the "new" method correctly |
Administrator
|
Thank you for the feedback and you should not use several versions of JOGL 2 at the same time. I already wasted several days because of that. For example, if some constants are modified between 2 versions (which occurred several times in NEWT), you'll have some troubles. Maybe we should reopen the bug report 537.
Julien Gouesse | Personal blog | Website
|
"Maybe we should reopen the bug report 537."
Actually, I believe this is fixed, just in a later version than the one I need to use with the third party libraries. |
Administrator
|
In reply to this post by Gene Lege
I had mentioned this in a reply to a comment on my tutorial, but I've moved that up into the main text now to make it more visible. Thanks for reminding me! This is supposed to be fixed, but I may need to revisit bug 537. |
Administrator
|
In reply to this post by Gene Lege
Ok but I encourage you to use a single version of JOGL 2 at a time, maybe you can recompile these libraries or ask their maintainers to use a more recent version. Using several versions of JOGL 2 at the same time in a program only leads to troubles and you don't benefit of the latest fixes.
Julien Gouesse | Personal blog | Website
|
Free forum by Nabble | Edit this page |