I have a project that I am trying to convert to OSGi. However, this project has been built with Guice as its dependency injection manager. It's a large project with Guice interwoven all throughout. Guice has been giving me many fits with the conversion process. Specifically, it has been given me a NoClassDefFoundError for com.google.inject.internal.cglib.reflect.FastClass. I have made sure that nothing is package-private and I also downloaded and used the guice-2.0-customloader.jar. Still, to no avail.
Is there any advice from anyone that has gone down this path? It is worth mentioning that I use peaberry to get dynamic services from the OSGi environment (for a plugin-type architecture) that I then use in the program later on.
Thanks a lot,
Steve
Hard to say exactly what the problem is, classloader issues can be very situation specific in OSGi and hard to debug.
If guice really is a core to your application it may make sense to make it a Fragment bundle of the System Bundle. The System Bundle is the root node in the classloader tree for ALL bundles. If classes exist in this bundle, they'll be accessible everywhere. This is a technique I've used successfully to wrap Swing LAF (Substance, Alloy, Jide) as OSGi bundles. They've gotta be at the root level since all of my bundles use Swing (especially the Swing classloader)
You'll want to check the OSGi specs for creating a Fragment bundle and making that fragment bundle a framework extension fragment. I've only been able to do this using Eclipse's Equinox runtime. At the time I wrote most of the supporting classes, Apache Felix did not yet support framework extension fragments. It may have changed now. I have no idea about frameworks (knopplefish, spring-dm)
Just use Peaberry. It has all the support you need for using Guice in OSGi. No need to reinvent everything from scratch!
I'm assuming your comments on package-private are related to this page on Guice and bridging class loaders?
There's a bug report/patch that may be related to your issue: http://code.google.com/p/google-guice/issues/detail?id=343
Have you tried adding Guice and cglib to the standard classpath and doing boot delegation for them? That would prove/disprove your issue is the same one as mentioned on the above bug report.
You could try my latest patch for Issue 343 - just attached a freshly patched build which is the latest Guice trunk plus this one patch, so people can try it and give feedback.
The latest patch avoids a lot of these CGLIB exceptions without forcing you to make classes public, and also provides a better error message in the few remaining places where this is still necessary (basically when you explicitly use method interception).
Related
For an ongoing project, we are looking for a possibility to dynamically download and load jar files into a running application. Apart from downloading the files (which is probably fairly straightforward), I am unaware of any solution that would automatically add the jar's to the classpath, and do discovery of the annotations (like CDI beans).
Given such a system, it would be rather handy if the #Inject annotation would not throw a runtime failure of an implementation of a class is not present (because that module-jar was not loaded).
Is there currently any such system? Does spring or OSGi fit this need?
Any ideas how close project Jigsaw would come in trying to fulfill this on application level?
I think you need OSGI, using an OSGI container like Karaf : https://karaf.apache.org
In standard java provide ServiceLoader https://docs.oracle.com/javase/tutorial/ext/basics/spi.html
I advice you to not follow that path
It should be possible to dynamically load jar files without the usage of OGSI. The keyword are Classloaders especially when used with a proper hierarchy. The following answer should give you an idea: How should I load Jars dynamically at runtime? but keep in mind that this might cause serious security issues
You followed the path at 2. even I advice you not to do it. But now you end up in the scenario that the context of your used framework does not know this classes. You would have this problem with most IOC frameworks. Since they build up the context on startup. There are libraries for this created for development purpose (spring-loaded, spring dev tools, JRebel). If your IOC framework supports it go with it.
Regarding handling not available jars. The best point to do research on this is Spring Boot and its auto configuration mechanism. It checks if certain classes/jars (not sure to be honest) are available and add additional behavior for this cases. But still this is application startup solution and not a runtime IOC solution.
I have a whole bunch of framework modules that work fine on OSGi, all the services and components are finding one another and running just fine.
There is however one framework that does some dynamic stuff regarding classes. Basically at some point you give it a class name and it performs Class.forName() and then reflection magic happens.
This works great when running in a standard jvm and using SPI to wire together the frameworks but it fails in OSGi because of course that random class "test.MyTest" that you are trying to approach via the framework is not visible to said framework.
It will throw a "java.lang.ClassNotFoundException: test.MyTest not found by framework"
So my question: how can I solve this lack of visibility for the framework that needs to see all? Import-Package: *?
UPDATE
Assuming OSGi hasn't changed much since 2010 on this front, the article http://njbartlett.name/2010/08/30/osgi-readiness-loading-classes.html is very interesting. I have currently added support for both actively registering classes and a domain factory to be injected via OSGi.
Apart from that the default resolving uses context classloader anyway so if all else fails that will be used to try and load the class.
UPDATE
I have added support for the suggested DynamicImport-Package as well which is easier for small projects.
You can use DynamicImport-Package:*. This will allow the bundle to see all classes. The problem is that you have no real control over what exactly is exposed. So this is normally a last resort and not the recommended way.
You should first try to use Thread.currentThread().setContextClassLoader() and set it to the classloader of the class you provide to the framework. Sometimes the frameworks also consult this classloader.
The even better way is to find a method in the framework that allows to provide the user classloader.
If you have control over the code then avoid Class.forName(). Instead let the user either give you a class object instead of a class name or let the user give you the combination of a class name and the classloader to use. Both ways work perfectly in and outside OSGi.
I'm trying to make a plugin-based application which means, besides the basic framework, other functionalities should be added with a plugin style.
The majar problem of such system, i think, is how to load new plugins at the runtime. I don't want to recomplie the whole project when a new plugin installed. Just like Eclipse, after new installation of plugin, the user only need to restart it.
So my first idea about that is using java reflection to load the class at the runtime. there might be some plugin configuration files, the system reads them and load the plugin classes with reflection. Maybe i can use the spring framework as well, because its Inversion of Control is just match my request.
Another idea i'm investigating is using the ejb container. when the plugins are ejbs, i can just pack them into jar and deploy them in an ejb container, then i can use jndi to access them. but it only works when the plugin are ejbs.
anyway, i'm a rookie in system design. so i post this topic and want to hear of your opinions.
btw. is there any good book about system design you want to recommand?
thanks alot in advance!
You may first look at OSGI and his implementation (Equinox for Eclipse and Apache Felix) but it would be easier if you give us more information of what you are trying to do.
Plug-in to solve what problem?
Designers of frameworks usually have deep domain knowledge that informs their design choices. Frameworks come about after two or three attempts to solve some problem; the earlier implementations give clues about how to abstract what's important into a framework.
Eclipse solves the problem of an expandable IDE (poorly, in my opinion). EJBs are transactional, distributed components that run in a container.
You've given no indication of what kind of problem you want to solve. Until you do, your ideas won't get very far.
I like OSGi, but the import/export restrictions and the lack of context class loader creates havoc when trying to use 3rd party libraries (e.g., some libraries try to find file.xml in META-INF, expecting for all such files in all jars to be returned, other libraries use ServiceLoader).
I want OSGi's dynamic loading, ability for handling several versions of the same library, and service framework.
So what are my alternatives? I know of JPF, looking for something less xmlish.
I had this problem with having a java mail bundle separate from my java activation bundle. You have the following options to get 1 bundle to see files (ie. not java resources but things like xml files) in META-INF of other bundles.
1) Merge the bundles together. This is often icky to deal with or just not impossible for the project.
2) Have the bundles that need to share resources be bundle fragments of the bundle that needs to read up the resources. Bundle fragments are defined by the OSGi spec and allow separate bundles to share resources as though they were merged together.
Have you tried googling for each library + osgi? A quick glance shows some others experiences and (it would seem) successes.
Sorry for the "just google it answer" but since I don't actively use these libraries in my OSGi app I can only suggest how I've handled this for some of my libraries ... which was google.
This is not really a good answer, but I don't want this buried in comments.
I want OSGi's dynamic loading, ability for handling several versions of the same library, and service framework.
There are other service frameworks, but to get dynamic loading and several versions of the same class there is nothing else by OSGi that I know of.
Also, now that OSGi seems to finally gain some traction, the pressure on libraries to "play nice" is rising. SpringSource for example maintains a growing collection of OSGified libraries. The package you need may already be there.
I often read about dependency injection and I did research on google and I understand in theory what it can do and how it works, but I'd like to see an actual code base using it (Java/guice would be preferred).
Can anyone point me to an open source project, where I can see, how it's really used? I think browsing the code and seeing the whole setup shows me more than the ususal snippets in the introduction articles you find around the web. Thanks in advance!
The Wave Protocol Server is my favourite example app.
I struggled a bit with this exact issue. It's so abstract and simple I was always worried I was "doing it wrong".
I've had been using it in the main project which has dependencies on other projects because the Guice module which sets the bindings was part of the main project.
I finally realized the libraries should be supplying the Modules themselves. At that point you can depend only on an instance of a Module (not a specific one), and the interfaces that are bound by it.
Taking it one step better, you can use the new ServiceLoader mechanism in Java 6 to automatically locate and install all Guice modules available on the classpath. Then you can swap in dependencies just by changing class path (db-real.jar vs. db-mock.jar).
I understand you're in Java-land, but in the .NET space the are several open-source apps written using an inversion of control container. Check out CodeCampServer, in which the UI module doesn't have a reference to the dependency resolution module. There is an HttpModule that does the work. (an HttpModule is just a external library you can plug in that handles events in ASP.NET, in CodeCampServer the UI project loads this DependencyRegistrarModule at run time, without any compile time reference to it.)
I think dependency injection has a way of disappearing from view if used properly, it will be just a way of initializing/wiring your application -- if it looks more fancy than that you are probably looking at extra features of the framework at hand, and not at the bare-bones dependency injection.
Edit: I'd recommend actually starting to use it instead of trying to find examples, and then come back and post questions here if you can't get stuff to work like you'd think it should :-)