Validating guice module configuration - how to use the SPI? - java

I'm writing a framework that uses Guice to bootstrap a server, and so I've extended Guice's AbstractModule to create a Module that provides some convenience methods for users to configure their code. However, I want to to check that the configuration is sane before launching the code. So it has to go somewhere in here:
// here, before the injector is created?
Injector injector = Guice.createInjector(someModule);
// here, after configure() is called?
Object something = injector.getInstance(SomeServer.class);
// start the server
It seems that there's not much I can check before the injector is created because the modules are not configure()ed yet. There is some mention of using the Guice SPI to validate module configuration, but the documentation is not too clear. Can someone, who uses Guice, give a short description on the best practices for validating modules before injectors are used?

I haven't experienced much of this first-hand, but it seems to me that you have three choices:
Refactor to MyConvenienceMethodModule.myConfigure() and MyConvenienceMethodModule.validate() if your convenience methods are expressive enough to provide useful information without ever running configure(). In theory you could call Module.configure(Binder) with a mock, but with Guice's EDSL that's far too complex; use ElementVisitor (below) instead.
Call Elements.getElements() on a particular Module to check on the binding status. Because the elements might be of a variety of types, you'd probably want to create an ElementVisitor instead (probably by creating a subclass of DefaultElementVisitor to insulate you from future Elements yet to be created). This way you get a good view of all bindings, even bindings in Guice's EDSL, while still in the context of the Module. I think this is your best bet.
Create your Injector as usual and call getAllBindings() to investigate it. This is probably your best option if your configuration's sanity depends on how multiple modules interact, rather than how individual modules are structured. If you only check at this point, you won't really be able to tell one Module from another.

Related

Is it possible to use Spring Framework DI without a container?

I want to create an java API to connect to a Restful API.
To deal with dependencies, I want to use Spring.
However, all examples I see over the internet talks about a DI container, and the whole system is running like a service.
What I need is:
Provide some classes to user be able to connect to such Restful API, but the inner dependencies of these classes being resolved by Spring. Needless to say that this framework won't start any application server. It will just provide some useful classes and interfaces to contact the RestAPI.
Is that possible?
Thanks in advance!
The Situation
Let's suppose I've wrote an API which provides a class called Car. User can use this Car class in their project. But Car class depends on two other classes: Wheel and Engine. What I want is the last two classes to be injected automatically, without the user needing to instantiate this.
The short answer to the situation is: no.
The reason for this is somebody must start Spring.
You have some options.
Solution 1
You can create some kind of initialization class that starts Spring for you.
The API user would need to do this:
Call the initialization stuff. Possibly something as simple as myAPI.initialize();.
Then use your stuff.
A giant (imho) drawback of this is that every class in your API would need to check to see if initialization happened.
Solution 2
Expose your classes via a factory. In this case, the API user would do something like this: MyFactory.createCar(...parameters...);
With this technique, the Spring initialization would be hidden from the user because you could load Spring in a static initialization block in the MyFactory class.
Solution 3
Instead of a factory patter,
use a builder pattern to instantiate your classes.
This is, effectively, a variation of the factory solution,
except that each Builder would call a static initialization method of some hidden (perhaps package access) class that starts Spring once.
Option other
If you only want DI,
Spring may not be a good fit for you (it might be overkill).
Google guice is a "just" DI tool that might be a good fit.
Even with guice,
somebody will still need to start it,
so solutions 1-3 will apply.

Dynamic class loading in OSGi

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.

How to keep an overview over the dependency injection stuff?

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.

How to inject SLF4J bindings with Guice?

After a cursory inspection, it seems like SLF4J and Guice (well, any DI framework, really) are sort of conflicting philosophies. SLF4J takes the approach "hey, we won't know until runtime what classes we're going to bind to, and that's OK." Guice, on the other hand, seems to say "hey, we need to know at compile-time exactly what classes we're binding to.".
So I ask: is it possible to use Guice/Spring/whatever DI framework to configure/inject SLF4J bindings?
The kicker is that the Java ClassLoader is what is really "injecting" SLF4J at runtime with the proper Logger/LoggerFactory/etc. objects, so I can't figure out how to inject those ClassLoaders so that they returns the org.slf4j.impl.Logger that I want at runtime:
I ask because I like the benefit of SLF4J and logging against an API, but also like the benefits of DI. Is there a way to make this work? Thanks in advance!
I believe it is not possible (unless you make something extremely cumbersome, like a container that create child classloader for your app... something like that)
The basic idea of SLF4j to have replaceable implementation is by having the binder lib providing the org.slf4j.impl.StaticLoggerBinder and SLF4J API will lookup this class thru classloader. Hence, if there is more than 1 binder in classpath, there is no way to distinguish the org.slf4j.impl.StaticLoggerBinders they are providing. DI framework is not going to help on this, given that Logging framework initialize even before DI happens.
Unless SLF4J is changing its design in the future, there is not much way we can do. And, I doubt it is possible even SLF4J changes its design. As we have no way to tell the DI container that the Logging initialization is something everybody depends on. I believe there are more reasons make it almost impossible to achieve.
However, what I am in doubt is, does this really have to do with DI? Honestly I don't see the problem of controlling which logging binding to use by putting corresponding JAR in classpath. If you want to control it on runtime, kind of programmatically, I think writing a little container to launch your app is the way to go. However, it is still nothing to do with DI.
One rather simple approach to this problem is to inject a ILoggerFactory instance into LoggerFactory via the setILoggerFactory() method. (As of October 2012, the setILoggerFactory() method does not exist.)
The static binding mechanism currently implemented by SLF4J does not do much other than setting the ILoggerFactory. Would such an approach work for you?
For anyone finding this now: Sangria implements a "context-sensitive binder" that works very well for this; see sangria-slf4j and sangria-contextual specifically.
From the author's blog post, you can set up an SLF4J named logger factory as easily as:
public class YourModule extends AbstractModule {
#Override
protected void configure() {
install(new SangriaSlf4jModule());
}
}
...and there are examples of how to use the new providers for your own types as well.

Guice: When to kick off injection/bootstrapping in a headless JAR?

So I'm writing a bunch of components (that will be packaged as JARs), and they are all using Guice for DI. These components are just reusable, "commons"-type JARs that will be used by other downstream projects.
My understanding with Guice is that you implement a concrete Module and use that to bind objects together and, in effect, configure all of your DI. It is also my understanding that you should then have a single "bootstrapping" phase where the Guice injector is created, and then all dependencies the module is configured with are then fetched from that injector with injector.getInstance(SomeClass.class).
That would work great in standalone application, that had some entry point, where you could invoke an init()-style method to then bootstrap Guice with, but in a headless JAR that has no entry point, I'm struggling with trying to determine when/where/how to bootstrap Guice.
These will be JARs living on the classpath and, at any point in time, an external entity could invoke and class and any method inside of them. I thought about using up a "lazy initialization" set up, where a method checks to see if its dependencies have been configured yet, and, if so, kicks off a bootstrap method.
But that's a really terrible solution! Partly, because that would require every class to have its own Module (which is ridiculous), and it would also pollute my entire codebase with DI-related code.
I'm clearly missing some Guice fundamentals here, otherwise I don't see how Guice could be used in anything other than an app where execution from start to finished is known and controlled. Any code samples are a huge plus! Thanks in advance.
If other code wants to configure your classes without using Guice, it should be able to. However, you should provide a Guice module which binds everything in a reasonable way so that other code (perhaps other modules) can install your module, and then inject the dependencies into their own classes.
Of course, you don't need to expose a module yourself at all - you can leave it up to others to perform all the binding. However, you may wish to provide a module to avoid exposing your implementation details - you can expose a public interface and a public module, but then keep the implementation package-private. The module can bind the interface to the implementation without the caller knowing anything about it.
You may also want to investigate private modules, so that you can bind dependencies that your code needs, without exposing them more widely.
Something, somewhere is going to have to create an injector - but if your code is just "library" code, then it almost certainly shouldn't be you. You shouldn't be performing the injection yourself - you should just be making your code amenable to injection.

Categories