I'm using 2 common packages, Immutables and
Guice. The very first thing that happens at runtime is I load setting from environment and other sources into settings into a singleton, non-Immutable config class, let's call it MyConfig, that for example, exposes a public getSettingX() method.
MyConfig myConfig = MyConfig.intialize().create();
String settingX = myConfig.getSettingX();
I have one abstract Immutable class, call it AbstractImmutable. that at instantiation needs to set a field based on the myConfig.getSettingX().
#Value.Immutable
abstract class AbstractImmutable {
abstract String getSettingX(); // Ideally set
}
Now, typically I inject MyConfig into classes using Guice, and would liket to figure a way to do this for implementations of the AbstractImmutable class (to avoid manually having to inject the MyConfig class every time I build an object--whole reason using juice to begin with, to manage my DI). However, since the concrete Immutables classes are generated at compile, it doesn't to work with the usual Guice injection annotations.
There's indication on the Immutables site of using the builder package to annotate a static factory method, but I can't seem to figure how to add this to the abstract immutable class.
Anyone have any suggestions?
To my knowledge, there is no way to do this on the generated Immutables class itself (though there may be some funny stuff you could do with #InjectAnnotation), so you may be out of luck there.
Even though you are asking under the guise of Guice, what you are asking for reminds me of the pattern that AutoFactory uses, and should be similarly applicable. In essence, take advantage of the Factory Pattern by injecting into the factory and then the factory will create the Immutable object.
For example, specifically referring to your case,
#Value.Immutable
abstract class ValueObject {
MyConfig getMyConfig();
#Value.Derived
String getSettingX() {
getMyConfig().getSettingX();
}
String getAnotherProperty();
class ValueObjectFactory {
#Inject MyConfig myConfig;
ValueObject create(String anotherProperty) {
return ImmutableValueObject.builder()
.setMyConfig(this.myConfig)
.setAnotherProperty(anotherProperty)
.build();
}
}
}
Then, in the application code, you would inject the ValueObjectFactory directly and call create on it as
class SomeApplicationClass {
#Inject ValueObjectFactory factory;
void someMethod() {
ValueObject = factory.create("myString");
// ... do something with the ValueObject
}
}
Similarly, you could define your factory as a builder, but that will be a decision you will have to make based on the number of parameters you have.
Related
Suppose I'm building a car and I have several Brake beans with different implementations
class Car {
#Inject
Car(#BrakeType(value="abs")Brake frontBrake, #BrakeType(value="nonabs")Brake rearBrake) { }
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
public #interface BrakeType {
String value();
}
interface Brake {}
#BrakeType(value="abs")
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
#BrakeType(value="nonabs")
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
why does my CarModule have to define #Provides for the specific Brake types? Shouldn't the custom annotation type #BrakeType be enough to determine which impl to inject? Or would that require using reflection, which dagger2 does not use?
#Module
public class CarModule {
#Provides #BrakeType("abs")
public Brake absBrake() {
return new AbsBrakeImpl();
}
#Provides #BrakeType("nonabs")
public Brake nonabsBrake() {
return new BrakeImpl();
}
}
Dagger doesn't look at qualifier annotations on classes, only on #Provides or #Binds methods. So the #BrakeType(value="abs") annotations on your classes don't have any effect.
A more canonical way of writing your code is:
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
#Module
abstract class CarModule {
#Binds #BrakeType("abs")
abstract Brake absBrake(AbsBrakeImpl impl);
#Binds #BrakeType("nonabs")
abstract Brake nonabsBrake(BrakeImpl impl);
}
Note that since you have #Inject on the constructors of your implementations, you can simply use Dagger's #Bind to bind the implementations directly to the appropriately qualified interface.
Reflection is probably not a big issue here because it would happen at compile time.
I did not look through the source code, but dagger is but an annotation processor—it registers to be called whenever a set of given annotations is used. While the qualifier alone would probably be enough to find out what you intended, I can think of the following reasons why this could not be the best solution.
javax.inject.Qualifier is part of a bigger API, and might also be used by other libraries in different context. So you might not want dagger to generate code for a method, just because it is annotated with a qualifier.
Another reason could be that since there is the possibility to create custom qualifiers, dagger would have to check every annotation on every method in every module and then in turn determine whether that annotation itself is annotated with #Qualifier to see if the method is of some interest to it. This is rather an unnecessary overhead.
There might be more reasons, but those 2 listed here seem enough to just make users of dagger use some sort of contract: #Provides.
Annotations don't affect the performance of the code, and having an addtional annotation won't do any harm, so there is more to gain than to lose by handling it the way they do.
For the record, you can use your own qualifier annotations (as BrakeType), or just use #Named from Dagger.
Using this last one, your code will look something like:
#Inject #Named("abs") Brake frontBrake;
#Inject #Named("nonabs") Brake rearBrake;
And on your module:
#Provides #Named("abs") static Brake provideAbsBrake() {
return new AbsBrakeImpl();
}
#Provides #Named("nonabs") static Brake provideNonAbsBrake() {
return new BrakeImpl();
}
Remember to use Dagger name conventions (like provide prefix) to get most of it. And on your modules try to use all #Provides methods static, doing so the resultant implementation does not need to instantiate it.
In short, Provides and Qualifiers work together so you need both.
Source: Dagger users guide.
#Inject constructor means provide a type that class itself, in your case, which mean you provide the AbsBrakeImpl type and BrakeImpl type, so when you try to inject with Brake, dagger can not found the provider.
Qualifier in #Inject constructor is not work, because class type is unique, we don't need to add a qualifier to.
So, in your case, or you have to use CarModule to tell Dagger explicitly, or change your constructor with
class Car {
#Inject
Car(AbsBrakeImpl frontBrake, BrakeImpl rearBrake) { }
}
I have a situation where when I initialize some of my classes, some of the fields I need to be injected (e.g. references to factories etc) whereas some others are dynamic and created at runtime (e.g. usernames etc). How do I construct such objects using the GUICE framework?
Simply annotating the fields I need injected as #Inject doesn't work as they seem to not be set up when creating an object using the constructor. For instance:
class C {
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
public C(ConfigurationField passedIn) {
this.passedIn = passedIn;
}
}
If my understanding is correct (and I could be wrong), the fact that I'm creating a new instance of C via new and not through Guice means that no injection will take place. I do need to pass these parameters in the constructor, but also want some fields injected -- so how do I solve this problem?
A feature specifically matching "mixing injection and parameters passed" would be Assisted Injection.
class C {
// Guice will automatically create an implementation of this interface.
// This can be defined anywhere, but I like putting it in the class itself.
interface Factory {
C create(ConfigurationField passedIn);
}
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
private SomeOtherDepIfYoudLike otherDep;
#Inject public C(#Assisted ConfigurationField passedIn,
SomeOtherDepIfYoudLike otherDep) {
this.passedIn = passedIn;
this.otherDep = otherDep;
}
}
Now in your module:
#Override public void configure() {
install(new FactoryModuleBuilder().build(C.Factory.class));
}
Now when someone wants to create a C, they can avoid calling the constructor directly; instead, they inject a C.Factory into which they pass a ConfigurationField instance of their choice and receive a fully-constructed, fully-injected C instance. (Like with most well-designed DI objects, they can call the constructor directly.)
Note that this design is especially useful in a few ways:
You can use constructor injection, treat all your fields as final, and treat the object as immutable.
If you stick with constructor injection entirely, your object will never be in a partially-initialized state, and your API stays simple (call the constructor and your object is ready).
For testing, you can write any implementation of C.Factory and have it return any instance you want. This can include test doubles of C or its factory: Fakes, mocks, or spies that you create manually or by using Mockito, EasyMock, JMock, or any other mocking framework.
What you are looking for is "On Demand" Injections:
public static void main(String[] args)
{
Injector injector = Guice.createInjector(...);
CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor();
injector.injectMembers(creditCardProcessor);
}
or for static things
#Override public void configure() {
requestStaticInjection(ProcessorFactory.class);
...
}
All explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection.
Note:
Both of these things are code smells and should only really be used
for migrating old code over to Guice. New code should not use these
approaches.
In the project I'm working on (not my project, just working on it), there are many structures like this:
project.priv.logic.MyServiceImpl.java
project.priv.service.MyServiceFactoryImpl.java
project.pub.logic.MyServiceIF.java
project.pub.service.MyServiceFactoryIF.java
project.pub.service.MyServiceFactorySupplier.java
And the Service is called like this:
MyServiceFactorySupplier.getMyServiceFactory().getMyService()
I understand that a factory is used to hide the implementation of MyServiceImpl if the location or content of MyServiceImpl changes. But why is there another factory for my factory (the supplier)? I think the probability of my Factory and my FactorySupplier to change is roughly equal. Additionally I have not found one case, where the created factory is created dynamically (I think this would be the case in the Abstract Factory Pattern) but only returns MyServiceFactoryImpl.getInstance(). Is it common practice to implement a FactorySupplier? What are the benefits?
I can think of a couple of examples (some of the quite contrived) where this pattern may be useful. Generally, you have two or more implementations for your Services e.g.
one for production use / one for testing
one implementation for services accessing a database, another one for accessing a file base storage
different implementations for different locales (translations, formatting of dates and numbers etc)
one implementation for each type of database you want to access
In each of these examples, an initialization for your FactorySupplier is needed at startup of the application, e.g. the FactorySupplier is parametrized with the locale or the database type and produces the respective factories based in these parameters.
If I understand you correctly, you don't have any kind of this code in your application, and the FactorySupplier always returns the same kind of factory.
Maybe this was done to program for extensibility that was not needed yet, but IMHO this looks rather like guessing what the application might need at some time in the future than like a conscious architecture choice.
Suppose you have a hierarchy of classes implementing MyServiceIF.
Suppose you have a matching hierarchy of factory classes to create each of the instances in the original hierarchy.
In that case, MyServiceFactorySupplier could have a registry of available factories, and you might have a call to getMyServiceFactory(parameter), where the parameter determines which factory will be instantiated (and therefore an instance of which class would be created by the factory).
I don't know if that's the use case in your project, but it's a valid use case.
Here's a code sample of what I mean :
public class MyServiceImpl implements MyServiceIF
{
....
}
public class MyServiceImpl2 implements MyServiceIF
{
....
}
public class MyServiceFactoryImpl implements MyServiceFactoryIF
{
....
public MyServiceIF getMyService ()
{
return new MyServiceImpl ();
}
....
}
public class MyServiceFactoryImpl2 implements MyServiceFactoryIF
{
....
public MyServiceIF getMyService ()
{
return new MyServiceImpl2 ();
}
....
}
public class MyServiceFactorySupplier
{
....
public static MyServiceFactoryIF getMyServiceFactory()
{
return new MyServiceFactoryImpl (); // default factory
}
public static MyServiceFactoryIF getMyServiceFactory(String type)
{
Class serviceClass = _registry.get(type);
if (serviceClass != null) {
return serviceClass.newInstance ();
} else {
return getMyServiceFactory(); // default factory
}
}
....
}
I have a related hierarchy of classes that are instantiated by a hierarchy of factories. While I don't have a FactorySupplier class, I have in the base class of the factories hierarchy a static method BaseFactory.getInstance(parameter), which returns a factory instance that depends on the passed parameter.
I have previously used Spring DI, and one of the benefits I perceive is that I can test my Spring bean classes without involving Spring (imports omitted for brevity):
public class Foo {
private String field;
public void setField(String field) { this.field = field; }
public String getField() { return field; }
}
public class TestFoo {
#Test
public void test_field_is_set() {
Foo foo = new Foo();
foo.setField("Bar");
assertEquals("Bar", foo.getField());
}
}
Now I am experimenting with JSR-330, which means not explicitly writing setters.
I'm using Hk2 so far, purely because of some anecdotal stuff about Jersey being tied to Hk2, and making it difficult to co-habit with other JSR-330 implementations.
public class Foo {
#Inject
private String field;
}
I half expected some magic to happen, whereby the #Inject annotation caused a setter to become available, but this is not the case:
Foo foo = new Foo();
foo.setField("Bar"); // method setField(String) is undefined for the type Foo
How can I (conveniently) test this kind of annotated class without invoking a framework?
Failing that, how can I invoke a framework in a portable way (i.e. without tightly coupling my test code to Hk2, Guice, etc.)
Failing that, what's a typical, clean way to test classes annotated in this way?
Simplest is to make the fields package-private (instead of private), then in the test, set them directly. (That works if the test is in the same package)
public class Foo {
#Inject
String field;
}
Foo foo = new Foo();
foo.field = "bar";
This has the advantage of avoiding reflection so it's safe for refactoring.
The field injection approach you mentioned is actually the typical Spring style; many programmers don't write setters for private injected fields at all. Spring (with #Autowired or #Inject) and JSR-330 containers usually inject fields using direct field reflection rather than setters.
Because of this, if you don't want to use any DI framework, you could write the necessary reflection code into your unit tests yourself, but this seems like overkill just to avoid a test dependency; after all, the point of using #Inject is that you're coding to an interface, and you don't avoid using the JVM to avoid coupling to it.
The usual approach for testing this sort of class is to set up a test context for whatever container you prefer and run the unit tests in that context. If you're using Spring, you'd put an applicationContext-test.xml file or TestConfig class in your src/test/ directory (or equivalent), and if you're using Guice, you'd write a module to wire up mocks or test datasets.
It turns out that frameworks relying on private/protected field access are not so uncommon. Hibernate, JPA, several JSR-330 implementations, including Spring itself, all do it.
Spring's spring-test package provides a ReflectionTestUtils class containing static methods for accessing these fields.
Using this one can test the class in the question thus:
import static org.springframework.test.util.ReflectionTestUtils.*;
...
#Test
public void testUsingSpringReflectionTestUtils() {
Foo foo = new Foo();
setField(foo, "field", "Bar");
assertEquals("Bar", foo.getField());
}
You need spring-test and spring-core in your test classpath for this to work, but it doesn't add a dependency on Spring for your production code.
(Comments welcome about alternative implementations of the same principle welcome. I don't think it's worth rolling one's own, however simple it would be, given that Spring has a good implementation.)
Give "needle" a try: http://needle.spree.de/overview
needle is an DI-test-framework that only simulates the container behavior, making unit tests real simple.
Suppose you have one interface
public interface A {
public void doSomething();
}
and two implementation classes
#Component(value="aImpl1")
public class AImpl1 implements A {
}
#Component(value="aImpl2")
public class AImpl2 implements A{
}
And finally a class that will use an "A" implementation:
#Component
public class MyClass {
#Autowire
A a;
}
Now if I want to inject AImpl1 I add the #Qualifier("aImpl1") while if I want to inject AImpl2 I add #Qualifier("aImpl2")
The question is: Is it possible to instruct spring somehow to look up all implementations of "A" in this case AImpl1 and AImpl2 and use some application specific conventions to choose the most appropriate implementation? for example in this case my convention could be use the implementation with the greatest suffix (i.e. AImpl2)?
EDIT: the class MyClass should not be aware at all about the implementation lookup logic, it should just find its property "a" set with an object of AImpl2.
You can inject all implentations as List:
#Autowired
List<A> as;
or as Map with bean name as key:
#Autowired
Map<String, A> as;
and then choose proper implementation manually (perhaps, in a setter method):
#Autowired
public void setAs(Map<String, A> as) {
this.a = ...;
}
Assuming you already have hundreds of interfaces and implementations (as you said in a comment), and you do not want to refactor all the code... then is a tricky problem... and this is a tricky solution:
You could create a custom BeanDefinitionRegistryPostProcessor and implement either the method postProcessBeanDefinitionRegistry or postProcessBeanFactory.
This way you have access to all bean definitions before they are instantiated and injected. Do your logic to find which is the preferred implementation for each one of your interfaces, and then, set that one as primary.
#Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a #Configuration class will not be avalable here.
}
#Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by #configuration, #component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let's say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
The hard part is to find the bean name, it depends of the specifics of your application. I guess that having a consistent naming convention will help.
Update:
It seems that both methods in the interface BeanDefinitionRegistryPostProcessor can be used for this purpose. Having in mind that in the postProcessBeanDefinitionRegistry phase, beans configured through #configuration classes are not yet available, as noted in the comments below.
On the other hand they are indeed available in postProcessBeanFactory.
If you have a Configuration class you could use a method in that to make the decision of which implementation of A to return. Then the autowired will inject the appropriate instance for that class.
#Configuration
public class ApplicationConfiguration {
#Bean
A getA() {
// instantiate the implementation of A that you would like to have injected
// or you could use reflection to find the correct class from the classpath.
// return the instance
}
}
This assumes you always want to use the same instance everywhere you are injecting A. If not, then you could have different #Bean annotated methods with names to get different versions.
You can try to use Spring Profiles.