I have a large OSGI package that I want to package and release as a single jar file. I'm trying to figure out what the best approach is for packaging multiple jars into a single large jar.
So far the best option I've seen appears to be one-jar project. However, the framework we are using pulls in jar files from a 'plugins' directory and one-jar appears to want/require all jar files to be stored only in the lib directory. There may be an easy way around this, I haven't looked fully into the architecture enough to know as I'm still trying to decide what approach is best.
any suggestions for other approaches to package the multiple OSGI bundles into one jar and/or how I would go about making it work in one-jar is appreciated.
Thanks
An alternative solution could be to run your bundles using PojoSR instead of running them in an OSGi framework. PojoSR in a nutshell implements the service layer of OSGi without the module layer. One of the side effects of that is that you can easily package your application as an executable JAR file. When you run that JAR it also does not need to create a bundle cache on disk.
For more information on PojoSR, go to:
http://code.google.com/p/pojosr/
http://luminis-technologies.com/?p=358
http://www.infoq.com/news/2011/10/pojosr
Using the Apache Felix Maven Bundle Plugin, I believe the option might accomplish what you are looking for. http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html
Apache Sling's maven-launchpad-plugin generates a runnable jar (and optionally a war file and a Karaf descriptor) from a list of bundles, see http://sling.apache.org/site/maven-launchpad-plugin.html
The Sling installer can be used to load additional bundles from the filesystem or other sources, see http://sling.apache.org/site/jcr-installer-jcrjcrinstall-and-osgiinstaller.html
Related
Did a lot of research but could not find a proper answer. My question is simple - I am building an executable jar file which has few external dependencies like spring etc. Now I want to deploy my executable jar file to server machine. Is there a easy and safe way of achieving it? Few options I am aware of:
Build an uber jar with all the dependencies bundled along with application code and deploy it
Deploy the source code executable jar and then manually add all the dependency jar files to the class path
Is there any other better way? Any tools which can help here? How are dependency jar upgrades handled? - Are they manually replaced on server machine?
If you 'just' have an executable jar and some other jar files as dependencies (this is the most common case actually), you can follow best practice standards and create a zip file containing them all. Check how various open source projects offer their stuff for download.
If you use some framework that might also guide you about deployment. As an example, the servlet specification tells you how to create that zip file in chapter 10.
If you want another way more compliant to the OS package manager, you could take a look at JPackage. It also bundles a Java Runtime so you have tight control not just about the jar dependencies but also the runtime.
I created an Eclipse 4 application and I needed a jar offering a functionality as part of my application (this could be anything e.g. log4j to make it trivial).
I added the jar as part of my project's classpath (Right Click->Configure Build Path) but on runtime my service failed with a ClassNotFound error (from OSGI I guess?).
Anyway searching this it turned out, at least as I have understand it, that I should add the jar as part of another Plugin and create a dependency from my application/service to this new plugin.
I.e. I created a Plugin Project from Existing JAR archives.
This time the setup worked.
So if I understand this, when developing for Eclipse/OSGi we should not add jars in the classpaths directly but add them via plugins (why?).
Question: If I am correct so far, what is the standard practice to include jars when developing a project?
Define/Create one Plugin Project from existing JAR archives and add all the required third party libraries needed there, or have a different plugin project per needed jar or something else perhaps???
Sorry if my terminology is not accurate. I am new in OSGi and Eclipse programming
Note: When talking about jars I am not refering to other OSGi services. I am refering to the norm of using ready, reliable third party libraries that would be needed by many parts of an application. E.g. log4j or an xml parsing library or apache commons etc
For the runtime it is always the Manifest and the headers there that control what is in your bundle classpath. There are three ways to get access to a jar:
Import-Package header. This is the recommended way. You define one import per package you need. You jar you want to access has to be deployed in the runtime as a bundle. It also needs to export all needed packages.
Require-Bundle . This is another way to access bundles. You define the id of the bundle you need and see all packages it exports. As Require-Bundle binds you more closely to the other bundle the Import-Package way should be preferred.
Bundle-Classpath . This allows to add jars to your classpath that you embed into your own bundle. This should only be a last resort when the other way do not work. You can have nasty classloading issues when mixing this with the other methods.
You can find many pre built bundles in maven central. Many jars today already contain an OSGi manifest. For the cases where this is not true many jars are repackaged as bundles by servicemix. See groupId: org.apache.servicemix.bundles. There is also the spring bundle repository where you find some more.
Below I listed some resources you might want to read:
http://www.aqute.biz/Blog/2007-02-19
http://wiki.osgi.org/wiki/Import-Package
http://wiki.osgi.org/wiki/Require-Bundle
http://www.vogella.com/blog/2009/03/27/required-bundle-import-package/
The examples you have mentioned are available as OSGi bundles, so you don't need to make them bundles yourself. You don't typically use direct jar dependencies in OSGi, you typically use package or bundle dependencies. In the log4j example you are referring to, you should use import package as there can be multiple bundle providers (newer log4j jar, springsource bundled version of older log4j, slf4j implementation...). This will disconnect your code dependencies from the actual provider.
These dependencies are maintained via you manifest, not your project classpath. In an eclipse plugin project, the projects build classpath is derived from the entries in the manifest.
Even though you are not using services, all code dependencies are still maintained via the manifest.
Extactaly same problem we faced in our project.
we have some legacy jar which are not OSGi compatible, we create lib folder parallel to BundleContent and added it into the classpath section of manifest.
Bundle-ClassPath: .,
/lib/<legacy jar>.jar
There is no need to exporting and importing of packages unnecessarily if only one bundle is going to consume it,
I've already a java project (non-plugin) for customized logging feature which is internally using log4j. I want to use this customized logger with eclipse plugin-project so I've specified logger project in the build path of the plugin-project. It doesn't give any compilation problem when I try to run the plugin application it gives ClassNotFoundException.
Can anyone tell me the proper way of using non-plugin project with plugin project?
Any suggestion would be appreciated.
Thanks & Regards.
Eclipse is OSGi based, and all plugins are OSGi bundles. The trick is, bundles can usually only see other bundles. You have a couple of options:
turn your other jar into a bundle. You just need to add an OSGi MANIFEST.MF to it. This is the recommended way, as that jar knows what it should and shouldn't do
include that jar in your bundle, and add it to your Bundle-ClassPath. You have to take care on what packages you export and at what version level, because you don't want to ever collide with another bundle.
You can convert your jar into OSGi bundle as Paul Webster has suggested. You may have a look at my answer to this question How to convert jar to OSGi bundle which some people found useful.
Is it possible to save my OSGi project (which comprises of few bundles) to a single executable file, something like an .exe file , so I can copy and run it to any PC that has a JVM.
I know that the normal method is to open a command prompt and install the required bundles/ jar files one by one. But since my project contains quite a few bundles that method seems tedious.
Thanx in Advance.
You can definitely do better than installing bundles one by one, even if you don't get as far as a single 'natively executable' archive like a .exe. There are lots of commercial and open source OSGi applications which ship as zip archives; the user unzips the archive and then either calls java -jar some.osgi.jar or runs a shell script.
There are a few ways the OSGi runtime can work out what bundles to install. Some are specific to an OSGi framework (such as Equinox or Felix) and others are more generic. If you're using Equinox, you can create a config.ini file and put it in a folder called configuration as the same level as your OSGi jar. List any bundles you want to start in the osgi.bundles property. The config.ini file can list all the bundles to start, and also any other configuration properties you might need.
Eclipse also allows you to define a minimal set of bundles in config.ini and use the configurator to start everything in the plugins folder. Similarly, if you're using Felix, any bundles in the auto-deploy directory will be automatically started. You could also look at Felix File Install, which allows you to drop bundles into a monitored folder to install them (once FileInstall itself is installed). Despite the name, FileInstall works on both Equinox and Felix.
This is similar to creating a complete OSGi application with Felix & Maven - the Sling Launchpad Plugin can be used to create an executable jar or war file that contains a specific set of bundles. If you're not using Maven yet it's not as simple as "saving your project to an executable file" but you could probably adapt the jar file generation mechanisms to your environment.
Eclipse has the notion of products. You could create a product from your existing bundles, and then your product can be exported as an executable. For details about the product see the Eclipse RCP tutorial from http://www.vogella.com/articles/EclipseRCP/article.html
The tutorial introduces the Eclipse RCP applications, but you do not need everything from there - it is possible to create a product without creating an entire Eclipse application.
This limits your choices as you are more or less bound to Eclipse Equinox as your OSGi runtime, but for creating an executable product from it might be a workable tradeoff.
Thanx.
Following the answers above I came across Chapter 9 in this book.
http://my.safaribooksonline.com/9780321561510/ch09#ch09
It had a walk through tutorial in exporting the project through the product configuration.
Its exactly what I needed. :)
If you use bnd(tools) then you can export a project to an executable jar either from the bndtools GUI or via the bnd commandline (bnd package xyz.bndrun; java -jar xyz.jar). The resulting jar file contains all the bundles, the launcher, and the framework.
I am having four different project, and i am using Weblogic to deploy my projects. There are several libraries ( jar files ) which are common for all projects. Currently each of my project are having lib directory and have almost same set of libraries. Now, is it possible to have this lib directory outside WAR files and access them.
Resist the temptation of putting the jar files in the "shared" folder of your container. It is better to keep the jar files where they are now. It may sound a good idea to use a shared folder now, but in the future you may need to deploy an application that requires a shared library, but a different version.
That being said, I have no experience with WebLogic. In Tomcat there is a shared folder with libraries common for all deployed applications. It is not a good idea to use this. If WebLogic can be configured to use a shared folder per a set of applications (and not for all deployed applications) you could go for it.
Do you want to do this ? Unless you're stuck for deployment space, I would (perhaps) advise against it.
Why ? At the moment you have 4 solutions running off these libs. If you have to upgrade one of the libs (say, if you discover a bug, or if you require a new feature), then you're going to have to test compatibility and functionality for all 4 solutions. If each solution has its own set of libs, then they're sandboxed and you don't have to move all 4 in step.
Note that all this hinges on how easy it is to regression-test your solutions. You may find it easy, in which case using the same set of libs is feasible.
Don't do that.
The whole idea of WAR files is that they are self-contained units. This makes deployment so much easier.
In addition to the possible version conflicts that others have pointed out, putting jar files in /shared can have very nested consequences for class visibility. They will be on a separate classloader, and be unable to see the classes in the WAR file. If you use libraries that rely on Class.forName() to work (and there are plenty), this could get very painful.
If you really, really cannot afford the extra disk space and memory look at OSGi or Spring DM. They have solved this problem, but at the price of increased complexity.
Put all the shared jar files under common\lib folder of weblogic. common\lib is accessible by all the deployed apps.
Well first of all you can put your libs all on the same place and have your build process import the ones needed.
Has for on deploy the new Weblogic 10 has a lib folder in each domain where you can put shared libs. i dont think that is possible before Weblogic 10
You can put the jars in their own ear file and deploy it as a shared library.
You can also put the wars in an ear and add the shared jars to APP-INF/lib. This is a Weblogic extension of J2EE, so it won't work on other servers.
I'm currently using another approach.
Create a central repository folder and put all common libraries in there.
In each project you can create a reference to all needed libraries. In Subversion it works with externals
Everytime, the local working copy is updated, the externals are updated to, so you just need to commit to the central folder and it's automatically distributed to all projects.