I've used Spring before (and like it), but thought I'd take a look at Guice.
Is there a way to initialize something like maps or lists into beans using Guice?
For instance, I've done the following before in Spring to inject a list of items I want to process into some bean.
<property name="FilesToProcess">
<list>
<value>file1.xml</value>
<value>file2.xml</value>
</list>
</property>
How can I do this in Guice?
Guice2 has MultiBindings and MapBindings, which should work for you.
https://github.com/google/guice/wiki/Multibindings
Updated:
After looking at this again, it seems that you may be asking how you can inject runtime values into Guice, perhaps as arbitrary objects.
Guice is very focused around doing everything as typesafe code, so it doesn't lend itself
naturally to this. What I've done to provide input to Guice is to create an XML schema and use jaxb to suck this in and inject the resulting objects.
There is a Names.bindProperties method for binding regular old properties into Guice
constants.
There is also some level of integration with Spring, so you may want to look at this as
well.
Guice lets you inject type literals. The syntax is a little strange. There is a blog entry that explains why.
The binding would look something like this:
public class SampleModule extends AbstractModule {
protected void configure() {
bind(new TypeLiteral<List<String>>() {}).
annotatedWith(Names.named("FilesToProcess")).
toInstance(Arrays.asList("file1.xml", "file2.xml"));
}
}
And then your application code could inject the list by name like this:
public class SampleClass {
private final List<String> files;
#Inject
public SampleClass(#Named("FilesToProcess") List<String> files) {
this.files = files;
}
}
I agree with Dave Stenglein for runtime values.
There are frameworks like Obix that are specialized in the configuration. I like Guice for code injection, but they are better for that configuration injection.
Related
In a simple Spring boot application I have my component like this:
#Data
#Component
public class GenericHandler {
private String path;
private HandlerType type;
}
And my properties might look like this:
my.handlers[0].path='/vol1/abc'
my.handlers[0].type='Single'
my.handlers[1].path='/vol1/dora'
my.handlers[1].type='MultiSequence'
I tried decorating with the GenericHandler-class with #ConfigurationProperties(prefix="my.handlers") and getting a list of all component instances in a service using
#Autowired
private List<GenericHandler> handlers;
But that created just one component, ignoring the property values at all.
How can I get one component instance per my.handlers property-entry?
You need a wrapper class
#Component
#ConfigurationProperties(prefix="my.handlers")
#Data
public class GenericHandlerWrapper {
private List<GenericHandler> handlers;
...
}
Then you can autowire the GenericHandlerWrapper
Update
As #zoolway pointed out in the comments, for the properties in the question to work as it is, #ConfigurationProperties(prefix="my.handlers") should be changed to #ConfigurationProperties(prefix="my")
That's not possible. What can be done is this:
#Data
#Component
public class GenericHandler {
private List<String> path;
private List<HandlerType> type;
}
I dealt with a similar issue in a different manner. I created a factory and an interface. The factory would hold different implementations of that interface In your case, GenericHandler would be your interface. Then you write any number of implementations of your interface and each implementation is declared as a Component. So, Spring will instantiate it as bean upon a startup (you might use #Lazy(false) to force the instantiation at startup) using some infrastructure that I wrote each bean of that interface will self-insert itself into its factory. Then at any part of your code in any bean, you can use the factory to access concrete implementation (base on your property "type" for example). The beauty is that you don't need to inject all the implementations in your bean at the time of writing but access needed implementation dynamically at run-time. I found this to be a useful pattern and created an infrastructure that does most of the work for you and published it as an Open Source library called MgntUtils. The detailed description of the idea (including reference to the library) could be found here. Also detailed explanation with examples of how to use it can be found in library Javadoc here. The library is available (with source code and Javadoc) as Maven artifacts and on the Github. Also a general article about the MgntUtils library could be found here
Suppose I have a class that looks like this:
public class MyClass {
#Inject
public MyClass(#Foo("whatever") Bar dependency) {
// ...
}
}
And I wanted to have some custom logic that can see we're injecting an object of type Bar with an annotation of type #Foo("whatever") and construct a corresponding Bar object...something like a Guice Provider, but that gets more context information about the injection site. Does Guice let me do something like that?
What you're describing isn't possible through normal Guice: Providers are intended to be zero-argument pure functions and there's no way to plumb the injection site information into them as you would a flexible callback function.
You can approximate what you want, though, two different ways:
If you know every single possible value of #Foo's parameter, you can make your #Foo a binding annotation and bind it by providing a Annotation-compatible equals and hashCode. This provides the most intuitive experience: You can do anything with your #Foo you can do with any other type, such as using #Foo in constructors or injecting #Foo("value") Provider<Bar> barProvider.
#Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
If you want #Foo to work for arbitrary parameters, you'll need to extend Guice with custom injections. This won't work for constructor injection or alongside any other #Inject annotations, but it will allow you to inspect types after Guice injection is finished to augment them as you see fit (e.g. detecting and reacting to #Foo annotations on fields).
See the example in the Guice docs for more information there.
Internally, Guice's core is effectively a Map<Key, Provider>, where a Key represents a pair of a possibly-parameterized type and an optional binding annotation. The former binding annotation trick works because Guice can map your injection request to a Provider all on its own, where the latter skips Guice's map so you can inspect/construct/inject instances all on your own.
If you're willing to skip the annotation part of your solution, you could inject a BarProvider or BarFactory that exposes a forFoo(String) method, which would give you consistent injection without knowing all your String values ahead of time. This would allow you to use assisted injection or AutoFactory to generate your factory (if you want to generate one instance per call), or let you write a straightforward factory yourself for added flexibility.
public class MyClass {
private final Bar dependency;
#Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}
Let's say we have the following code:
#Inject
private Collection<SomeKind> myCollection;
What I want is that the dependencies after they were solved (I mean, all the classes that are of SomeKind type), could also being added to the collection. I know I can inject the ServiceLocator, and programmatically search for the instances on the registry, and then add them to the collection by myself, I just was wondering if there is a common mechanism for this scenario.
I think what you want is an IterableProvider<SomeKind>. See the Documentation.
It's an Iterable, so you can use it in a for each loop
for (SomeKind someKind: someKinds) {
...
}
You could look them up by name
#Inject
IterableProvider<SomeKind> someKinds;
...
SomeKind someKind = someKinds.named("someName").get();
Here's a complete example using Jersey
I have created a OSGI service with declarative services to inject an object that implements an interface. If I inject the object in a class that is attached to the application model (handler,part,....) it is working fine. If I inject it in a class that is not attached to the application model it is always returning null.
Is it possible to use DI in classes that are not attached to the application model? I looked in the vogella tutorials but somehow I don't find a solution.
I know of three ways of how Eclipse 4 can inject objects in your classes:
During start-up the Eclipse runtime looks for relevant annotations in the classes it instantiates.
Objects injected in 1. are tracked and will be re-injected if changed.
Manually triggering injection using the ContextInjectionFactory and IEclipseContext.
What you want may be possible with the third option. Here is a code example:
ManipulateModelhandler man = new ManipulateModelhandler();
//inject the context into an object
//IEclipseContext iEclipseContext was injected into this class
ContextInjectionFactory.inject(man,iEclipseContext);
man.execute();
The problem is, however; that the IEclipseContext already needs to be injected into a class that can access the object that needs injection. Depending on the number of necessary injections, it might be more useful to use delegation instead (testability would be one argument).
#Inject
public void setFoo(Foo foo) {
//Bar is not attached to the e4 Application Model
bar.setFoo(foo);
}
Therefore, a better solution is probably using the #Creatable annotation.
Simply annotate your class, and give it a no-argument constructor.
#Creatable
public class Foo {
public Foo () {}
}
Using #Inject on that type as in the method above, will let Eclipse instantiate and inject it.
The disadvantage is that you cannot control the object creation anymore, as you would with ContextInjectionFactory.inject(..).
I refactored out some part of e(fx)clipse in order to achieve that. Have a look at this. Sorry for the shameless plug...
I'd like an injected instance of an object to know the name of the class that is requesting its injection. I'm aware that this kind of violates the entire concept of dependency injection, but it seems like a valid use case for supporting useful logging. Is this possible with Guice?
Example:
class InjectorAware {
#Inject
public InjectorAware(Class injectorClass){
System.out.println("I was injected into a "+injectorClass.getCanonicalName());
}
}
class NeedsInjectorAwareField {
#Inject InjectorAware injectorAware;
}
When NeedsInjectorAwareField gets injected, the console would print "I was injected into a somepackage.NeedsInjectorAwareField"
Guice actually already injects a java.util.logging.Logger for you that already is customized with the name of the class it's injected into. Not sure how it's done, but you might be able to borrow the technique used from the Guice source...or just use the Logger directly.
UPDATE: this appears to be the point of the Guice source responsible for this behavior. You might be able to borrow the technique somehow, I'm not sure.
It is not possible using only Guice and they wont allow it.
http://code.google.com/p/google-guice/issues/detail?id=27
Not sure if you could do it only with Guice, but it wouldn't be too hard to make it work through the injected constructors.
public interface InjectorAware {
void setInjector(Object injectingInstance);
}
public class Foo {
#Injected
public Foo(InjectorAware injectorAware){
injectorAware.setInjector(this);
}
}
That said. Not sure it's a good idea.
I know it's an old thread, but for those folks who are still trying to solve this problem, have a look at https://github.com/raner/loginject