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 :-)
Related
How do you keep an overview over which objects get injected where? I have a rather small project where i use guice, not so much because i really need it (given the project is still small), but rather because i want to get to know it a little better.
I am already starting to loose the overview with only ~10 classes; are there tools that analyze the code to show something like a dependency graph?
That would make it easier to see quickly where i forgot something or where i need singleton scoped injection. Also with guice a lot of things happen implicitly, being able to see these things explicitly would help debugging in the future.
I have a couple of principles which help to manage dependencies using Guice.
Keep all bindings inside modules only. Do not use just-in-time bindings stuff. I mean, do not use #Singleton or #ImplementedBy or #ProvidedBy, i.e. all that is described here. Try also always call binder.requireExplicitBindings() at the top of your modules - it will force you to always bind your dependencies explicitly. When you keep all dependencies to the modules, you can easily find which interface fulfilled by which implementation. This simplifies navigation around bindings a lot.
Try to keep your modules as small as possible, and then combine them when creating an injector (directly via createInjector() call or using a central module which does nothing but install()s other modules). Each module should be responsible for its own part of the application and should be named accordingly. Also your modules should not contain complex initialization and dynamic binding code. This way you will be able to find a module which is responsible for some part of your application quite easily.
These principles are really simple but they make dependency management very easy.
Also, you can visualize dependency graph using special Guice extension. It has it bugs though, and it has been a while since I have used it, so I can't give you exact links on how to avoid these bugs, but googling for it won't take long.
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'm having trouble getting a shared library working in a Java EE environment.
In particular, the library contains some helpers for common JMS activities. However, as soon as the code enters a library function that requires anything from javax.jms it's triggering a ClassNotFound exception (claiming it can't find javax.jms.Message, for instance.)
How do I get around this? I'm placing the shared lib under $AS_HOME\lib\endorsed -- does it belong elsewhere? I have tried also packaging all the dependencies inside the jar; this doesn't seem to make much of a difference.
I am really hoping this is much more straightforward than it is seeming right now. In order just to get it working, I've refactored the helper into a helper-per-module within each component that requires the functionality. Note that this is working, so I'm thinking the issue at this point is just classpath problems? Thanks for any advice!
The best practice is to put the jms.jar in:
$AS_HOME/domains/<your domain>/lib
but you could always just place them in:
$AS_HOME/lib/
If you are not familiar with domains, take a quick glance at Concept of a GlassFish Domain
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).
I have a rather large (several MLOC) application at hand that I'd like to split up into more maintainable separate parts. Currently the product is comprised of about 40 Eclipse projects, many of them having inter-dependencies. This alone makes a continuous build system unfeasible, because it would have to rebuild very much with each checkin.
Is there a "best practice" way of how to
identify parts that can immediately be separated
document inter-dependencies visually
untangle the existing code
handle "patches" we need to apply to libraries (currently handled by putting them in the classpath before the actual library)
If there are (free/open) tools to support this, I'd appreciate pointers.
Even though I do not have any experience with Maven it seems like it forces a very modular design. I wonder now whether this is something that can be retrofitted iteratively or if a project that was to use it would have to be layouted with modularity in mind right from the start.
Edit 2009-07-10
We are in the process of splitting out some core modules using Apache Ant/Ivy. Really helpful and well designed tool, not imposing as much on you as maven does.
I wrote down some more general details and personal opinion about why we are doing that on my blog - too long to post here and maybe not interesting to everyone, so follow at your own discretion: www.danielschneller.com
Using OSGi could be a good fit for you. It would allow to create modules out of the application. You can also organize dependencies in a better way. If you define your interfaces between the different modules correctly, then you can use continuous integration as you only have to rebuild the module that you affected on check-in.
The mechanisms provided by OSGi will help you untangle the existing code. Because of the way the classloading works, it also helps you handle the patches in an easier way.
Some concepts of OSGi that seem to be a good match for you, as shown from wikipedia:
The framework is conceptually divided into the following areas:
Bundles - Bundles are normal jar components with extra manifest headers.
Services - The services layer connects bundles in a dynamic way by offering a publish-find-bind model for plain old Java objects(POJO).
Services Registry - The API for management services (ServiceRegistration, ServiceTracker and ServiceReference).
Life-Cycle - The API for life cycle management (install, start, stop, update, and uninstall bundles).
Modules - The layer that defines encapsulation and declaration of dependencies (how a bundle can import and export code).
Security - The layer that handles the security aspects by limiting bundle functionality to pre-defined capabilities.
First: good luck & good coffee. You'll need both.
I once had a similiar problem. Legacy code with awful circular dependencies, even between classes from different packages like org.example.pkg1.A depends on org.example.pk2.B and vice versa.
I started with maven2 and fresh eclipse projects. First I tried to identify the most common functionalities (logging layer, common interfaces, common services) and created maven projects. Each time I was happy with a part, I deployed the library to the central nexus repository so that it was almost immediately available for other projects.
So I slowly worked up through the layers. maven2 handled the dependencies and the m2eclipse plugin provided a helpful dependency view. BTW - it's usually not too difficult to convert an eclipse project into a maven project. m2eclipse can do it for you and you just have to create a few new folders (like src/main/java) and adjust the build path for source folders. Takes just a minute or two. But expect more difficulties, if your project is an eclipse plugin or rcp application and you want maven not only to manage artifacts but also to build and deploy the application.
To opinion, eclipse, maven and nexus (or any other maven repository manager) are a good basis to start. You're lucky, if you have a good documentation of the system architecture and this architecture is really implemented ;)
I had a similar experience in a small code base (40 kloc). There are no °rules":
compiled with and without a "module" in order to see it's usage
I started from "leaf modules", modules without other dependencies
I handled cyclic dependencies (this is a very error-prone task)
with maven there is a great deal with documentation (reports) that can be deployed
in your CI process
with maven you can always see what uses what both in the site both in netbeans (with a
very nice directed graph)
with maven you can import library code in your codebase, apply source patches and
compile with your products (sometimes this is very easy sometimes it is very
difficult)
Check also Dependency Analyzer:
(source: javalobby.org)
Netbeans:
(source: zimmer428.net)
Maven is painful to migrate to for an existing system. However it can cope with 100+ module projects without much difficulty.
The first thing you need to decide is what infra-structure you will move to. Should it be a lot of independently maintained modules (which translates to individual Eclipse projects) or will you consider it a single chunk of code which is versioned and deployed as a whole. The first is well suited for migrating to a Maven like build environment - the latter for having all the source code in at once.
In any case you WILL need a continuous integration system running. Your first task is to make the code base build automatically, so you can let your CI system watch over your source repository and rebuild it whenyou change things. I decided for a non-Maven approach here, and we focus on having an easy Eclipse environment so I created a build enviornment using ant4eclipse and Team ProjectSet files (which we use anyway).
The next step would be getting rid of the circular dependencies - this will make your build simpler, get rid of Eclipse warnings, and eventually allow you to get to the "checkout, compile once, run" stage. This might take a while :-( When you migrate methods and classes, do not MOVE them, but extract or delegate them and leave their old name lying around and mark them deprecated. This will separate your untangeling with your refactoring, and allow code "outside" your project to still work with the code inside your project.
You WILL benefit from a source repository which allows for moving files, and keeping history. CVS is very weak in this regard.
I wouldn't recommend Maven for a legacy source code base. It could give you many headaches just trying to adapt everything to work with it.
I suppose what you need is to do an architectural layout of your project. A tool might help, but the most important part is to organize a logical view of the modules.
It's not free but Structure101 will give you as good as you will get in terms of tool support for hitting all your bullet points. But for the record I'm biased, so you might want to check out SonarJ and Lattix too. ;-)