Consistent OSGi import of 3rd party libraries - java

I've been developing OSGi modules but so far I've come across a number of issues when I've had to wrap existing jars. An example of this is the use of the Oracle database driver which, even though I've wrapped the jar as bundle, just refuses to work (cannot find the driver class even though its present). This is just a single example but I've had issues with other 3rd party libraries and was wondering if there's a best practice approach to using 3rd party libraries which works every time?
Jlove

The problem in your case is that jdbc uses a class from the java runtime to find the database driver (DriverManager.getConnection). This can not work as the database driver is not accessible from the system classloader (that loaded the DriverManager class).
A way that works in OSGi is to use a DataSource instead: http://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html . There you simply create the data source using new and this of course works. The problem is that it makes your user bundle depend on the specific DB driver. So the best practice is to create the DataSource centrally and publish it as service.
You can find some more details in my Apache Karaf DB Tutorial (http://www.liquid-reality.de/display/liquid/2012/01/13/Apache+Karaf+Tutorial+Part+6+-+Database+Access).
Btw. In general this kind of factories are tpyically where libraries fail in OSGi. Every lib invents another and different factory system and most of the are incompatible with the restricted classloaders of OSGi. Luckily most libs are made OSGi ready nowadays. Most times this simply means that you can also call the factory with a concrete object that you can retrieve using an OSGi service.

My preferred approach is not to wrap the library, but to unjar it, add a manifest, and re-jar it. Jars-inside-jars tend to cause issues that are hard to debug. Unjar and re-jar can be automated with a simple ant script.
Also, I like to write MANIFEST.MF manually. If the library being wrapped is small, then it's easy enough to do that. Tools like bnd that generate MANIFEST.MF for you do not always give the right results, and if you rely on them too much you don't know what is going on under the hood.

Related

Java creating an addon/mod loader for an application

I have a game written in Java and a whish to write a generic ModLoader/AddonLoader application. A separate application/api that would allow you to create mods/addons for my projects that add extra implementation that I do not want in the main application.
However I am not sure how to go about this, i've done some research and im not too sure how to make the mod/addon interact with a loader which interacts with the main application to add new features/modify old
Many Thanks
Elliott
Since you're looking for some basic guidance I'll suggest the following:
You need a way to pull in classes after the core application is running. That means you will need these classes on the classpath. The simplest way to do that is probably to have your classpath include a folder like "addons" so that all the jars in that folder are automatically on your application's classpath.
Once you have your classpath set up you will need to somehow make use of the appropriate class(es). This part is hard to speak generically about because it depends heavily on how you intend your addons to work. Some tools use annotations to help with this and you can probably look at some open source projects for examples. One that comes to mind is Maven, it makes use of annotations in its plugin system. The general concept is that you need to decide how many different kinds of addons you have and how you will identify them and make use of them.
Typically making use of an addon involves instantiating that addon which is why it can be tricky. Some plugin systems require that addons be written such that they use a specific package name. They do this so that they can make use of reflection to find all classes in a given package and then process them.
Hope that helps to get you started!

Is there any native mechanism whereby we can override classes in an existing deployed Struts2 app?

Specifically, if we have an original .war file deployed in a application server, can one deploy a .war which provides different implementations of classes in the original file without having to modify the base code to support this?
Edit. I've formulated the problem wrongly, it's actually simpler I think. We want to expose actions from two distinct WARs in the same base path, rather than a different path for each WAR. Can it be done at the container configuration level?, or do you recommend employing something like URL rewriting?
Not easily. Generally, a deployed WAR becomes a discrete webapp within a Java EE server, and it gets its own classloader. Your second deployment will get another classloader, and although they will definitely share some ancestry, it won't be possible to reimplement things from the other WAR - your second deployment won't be able to 'see' it, because of the way the classloaders are chained together.
It is possible to rewrite running classes using a Java agent, although this is nontrivial. You can transform (rewrite incoming) classes and you should be able to rewrite live (instantiated) classes, although the problem there is that there may be objects on the heap using the old and new code.
Class rewriting is how Eclipse's Hot Code Replace works, and also how JRebel's fast redployment solution functions.
You might be able to use an AOP system like AspectJ if you really want to pursue this - but it sounds like you're trying to solve a build or deploy problem, rather than a problem where AOP would be a more fitting solution.

What's the purpose: api.jar + impl.jar + bundle.jar?

I see many Java packages have api, impl and bundle jars (name-api.jar, name-impl.jar, name-bundle.jar). Could someone explain what those mean? Are all three needed by the app?
The idea is that you can separate the dependencies of the application; in an attempt to make applications more portable. The idea is that you can make the application dependent on the api.jar when compiling. Then when you want to run the program you can then switch in the appropriate implementation jar (impl.jar) and the appropriate resource bundle jar (bundle.jar).
As an example suppose the library does some database interaction. You write your code so that it references the api.jar. Now suppose you need it to work with a specific type of database e.g. MySQL - you would then add the impl.jar that is specific to MySQL databases to the classpath to get it to work (if you need a different database later - you only need to switch that jar in the classpath).
The bundle.jar is a bit more obscure and not as common. This could be used to supply configuration setting for the library. For example it could be used to supply language specific settings, or some more specific config. In the case of the database library it might be that the implementation is designed for all versions of MySQL, and the resource bundle jar provides config files that allow it to work for a specific MySQL version.
Often :
name-api.jar contains only the interface of the API.
name-impl.jar provides an implementation of all interfaces in the name-api.jar
name-bundle.jar bundles everything with all the needed classes to run a Java application.
api.jar contains API interfaces. These are interfaces as a contract that the implementation of the API should follow.
impl.jar is the implementation of the api.jar. You can't just have the impl.jar without the api.jar.
bundle.jar is the resources (if I'm not mistaken). Those are resources needed for the implementation code necessary to run.
I've never seen such an arrangement.
If the designer packaged the app into three JARs, then I'd say all three are needed.
But you should recognize that it's just a choice made by the designer. It's possible that s/he could have just created a single JAR with everything in it and you'd be none the wiser.
I'm guessing now, but if you were to open those JARs you'd see only interfaces in the API JAR, implementations of those interfaces in the impl JAR, and resource bundles and other .properties files in the bundle JAR. Try it and see. You'll learn something.

Java: Libraries within Libraries and Classpath Issues

We are having a discussion at work and an interesting point came up:
Say you are developing a small library, call it somelib. Say that somelib needs to do some logging, but you don't want to reinvent the wheel, so you decide to use a 3rd party logging library.
Additionally, you want to make integration of somelib as painless as possible, so you distribute a single JAR file (somelib.jar), which has the other logging JAR, call it logger.jar, embedded inside of it. Much like what Maven's jar-with-dependencies assembly does.
Now comes the issue. Since your product is a library, what if your customer is using somelib and also happen to be using a different version of the same logging library on their own. Now we have a classpath problem.
This seems to me like it would be a common problem for people that write libraries, so what is the typical solution?
Do they avoid using JAR bundling methods altogether? Even if we do that, there is still an issue with a user's code expecting version X of the logging library, and somelib's code expecting version Y.
Do they somehow insert a dummy package prefix so that the logger classes in somelib won't conflict?
What about dynamic loading of the logger library? (though this still has versioning problems from 1.)
You may consider to use OSGI or wait for JDK 8 and its Jigsaw project.

Implementing dynamic plugins in Java

I'd like to implement a dynamic plugin feature in a Java application. Ideally:
The application would define an interface Plugin with a method like getCapabilities().
A plugin would be a JAR pluginX.jar containing a class PluginXImpl implementing Plugin (and maybe some others).
The user would put pluginX.jar in a special directory or set a configuration parameter pointing to it. The user should not necessarily have to include pluginX.jar in their classpath.
The application would find PluginXImpl (maybe via the JAR manifest, maybe by reflection) and add it to a registry.
The client could get an instance of PluginXImpl, e.g., by invoking a method like getPluginWithCapabilities("X"). The user should not necessarily have to know the name of the plugin.
I've got a sense I should be able to do this with peaberry, but I can't make any sense of the documentation. I've invested some time in learning Guice, so my preferred answer would not be "use Spring Dynamic Modules."
Can anybody give me a simple idea of how to go about doing this using Guice/peaberry, OSGi, or just plain Java?
This is actually quite easy using plain Java means:
Since you don't want the user to configure the classpath before starting the application, I would first create a URLClassLoader with an array of URLs to the files in your plugin directory. Use File.listFiles to find all plugin jars and then File.toURI().toURL() to get a URL to each file. You should pass the system classloader (ClassLoader.getSystemClassLoader()) as a parent to your URLClassLoader.
If the plugin jars contain a configuration file in META-INF/services as described in the API documentation for java.util.ServiceLoader, you can now use ServiceLoader.load(Plugin.class, myUrlClassLoader) to obatin a service loader for your Plugin interface and call iterator() on it to get instances of all configured Plugin implementations.
You still have to provide your own wrapper around this to filter plugin capabilites, but that shouldn't be too much trouble, I suppose.
OSGI would be fine if you want to replace the plugins during runtime i.g. for bugfixes in a 24/7 environment. I played a while with OSGI but it took too much time, because it wasn't a requirement, and you need a plan b if you remove a bundle.
My humble solution then was, providing a properties files with the class names of plugin descriptor classes and let the server call them to register (including quering their capabilities).
This is obvious suboptimal but I can't wait to read the accepted answer.
Any chance you can leverage the Service Provider Interface?
The best way to implement plug-ins with Guice is with Multibindings. The linked page goes into detail on how to use multibindings to host plugins.
Apologize if you know this, but check out the forName method of Class. It is used at least in JDBC to dynamically load the DBMS-specific driver classes runtime by class name.
Then I guess it would not be difficult to enumerate all class/jar files in a directory, load each of them, and define an interface for a static method getCapabilities() (or any name you choose) that returns their capabilities/description in whatever terms and format that makes sense for your system.

Categories

Resources