I have a problem with creating object via reflection with Weld context.
I'm loading classes and their configuration from external files.
Simplify my code looks like:
final Class<?> moduleClass = Class.forName(properties.getProperty("className"));
then I'm creating instance of this class
final Constructor<?> constructor = moduleClass.getDeclaredConstructor();
module = (Module) constructor.newInstance();
Module class:
#ModuleImpl
public class ExampleModule extends AbstractModule (implements Module interface) {
#Inject
private Test test;
Module is created sucessfully, but it hasn't weld context to inject Test class. And I cannot find the correct way. I tried to make own producer but I'm not much familiar with Weld and CDI in Java SE yet.
My broken producer (I think that its totaly bad)
public class InjectionProvider {
#Produces
public Module getInsrance(Class<?> clazz) throws ReflectiveOperationException {
final Constructor<?> constructor = clazz.getDeclaredConstructor();
return (Module) constructor.newInstance();
}
}
I cannot find something about this problem, so if anyone can help me I will be glad. I really need this way of creating classes because I don't want to change my code everytime when I need change some property in Module classes.
EDITED:
I cannot make it with producers. But I found a workaround. I'm not sure if is it good solution but it works for now.
I created a singleton class with Weld context.
public class TheMightyWeld {
private static Weld weld;
private static WeldContainer weldContainer;
public static WeldContainer getThePowerOfCreation() {
if (weldContainer == null) {
weld = new Weld();
weldContainer = weld.initialize();
}
return weldContainer;
}
public static void shutdown() {
if (weld != null) {
weld.shutdown();
}
}
}
And then I can initialize my app with
TheMightyWeld.getPowerOfCreation().instance().select(FXApplicationStarter.class).get().startApplication(primaryStage, getParameters());
And later in code I can reuse it for reflection
module = (Module) TheMightyWeld.getPowerOfCreation().instance().select(moduleClass).get();
EDITED 2:
I found better a solution. I can inject weld Instance
#Inject
private Instance<Object> creator;
then I can do only this
creator.select(moduleClass).get();
I think that this is a good solution.
I don't know if I understand your question right,
specifically the part related to the class loading
vs. the code used in the producer.
I am wondering if you expect inject to work for
a object that you instanciate for yourself through
Class.forName. As the decoration of objects
through frameworks usually is done
using a modified classloader and returning
the modified or decorated object, I guess your
approach disables this decoration (dependency injection).
You not using a call to new leaving the instanciating
to the classloader rather you are using a instantiation
through reflection.
See edited post. If someone have a better solution I will be glad for it.
Related
I started to use constructor injection in my projects since Spring declared field injection to be deprecated. Actually, the code feels prettier and more strict, I'm ok with that.
But I encountered a pattern which seems a bit...weird and verbose to me:
I have an abstract service bean class (with #Service annotation), which has, say 2 dependencies, injected directly in the constructor:
#Autowired
public AbstractService(DependencyA depA, DependencyB depB) {
this.depA = depA;
this.depB = depB;
}
Then I have multiple services bean classes (still with #Serviceannotation) extending the abstract one.
And I don't know if there is another way but this is where I find a bit verbose and repetitive having to inject the dependencies for the parent, in each sub-class constructor:
#Service
public class ServiceA extends AbstractService {
private final DepC depC;
#Autowired
public ServiceA(DepA depA, DepB depB, DepC depC) {
super(depA, depB);
this.depC = depC;
}
}
I just wanted to know if this is the right way, and what you think about this ?
The #Autowired on AbstractService doesn't do anything. Change it to:
#Service
public class ServiceA extends AbstractService {
private final DepC depC;
#Autowired
public ServiceA(DepA depA, DepB depB, DepC depC) {
super(depA, depB);
this.depC = depC;
}
}
...
public AbstractService(DependencyA depA, DependencyB depB) {
this.depA = depA;
this.depB = depB;
}
I'm ok with this setup.
For me, the main benefits of using constructor injection is to inform the developer what are the external dependencies. I find it useful when writing unit test. When writing mocks, you just know what needs to be mocked.
An other benefit is to highlight when a Class has too many dependencies, it gives a hint that refactoring may be in order.
The alternative would be using setter injection (while keeping the informational aspect), but I've grown to enjoy constructor injection.
My answer is focusing about the "verbose and repetitive" part in your question; I let others decide how "correct" your usage of annotations is.
Even with Spring and its DI framework, in the end we are still talking about Java source code!
And in Java, if your base class only offers a constructor that takes some A and B; then of course your subclass has to make a call super(A a, B b); and of course, those values a and b have to come from somewhere!
So, what you call "verbose and repetitive" is a direct consequence of using Java.
In other words: there is no way to avoid that part!
I'm having a project based on Dagger 2 which consists of two modules. The core module includes some interfaces and some classes that have member injections declared for these interfaces.
The actual implementations of these interfaces are included in the second module which is an Android project. So, naturally the provide methods for these are included in the Android project.
Dagger will complain during compilation about not knowing how to inject these in the core module.
Any thoughts on how to achieve this without using constructor injections?
In short, I just tried this, and it works. Be sure to check the exact error messages and make sure you are providing these interfaces and #Inject annotations are present.
There is probably just some wrong named interface or a missing annotation. Following up is a full sample using your described architecture that is compiling just fine. The issue you are currently experiencing is probably the one described in the last part of this post. If possible, you should go with the first solution though and just add those annotations.
The library
For reproducability this sample has minimalist models. First, the interface needed by my class in the library module:
public interface MyInterface {
}
Here is my class that needs that interface. Make sure to declare it in the constructor and provide the #Inject annotation!
#MyScope // be sure to add scopes in your class if you use constructor injection!
public class MyClassUsingMyInterface {
private MyInterface mMyInterface;
#Inject
public MyClassUsingMyInterface(MyInterface myInterface) {
mMyInterface = myInterface;
}
}
The idea is that the interface will be implemented by the app using MyClassUsingMyInterface and provided by dagger. The code is nicely decoupled, and my awesome library with not so many features is complete.
The application
Here need to supply the actual coupling. This means to get MyClassUsingMyInterface we have to make sure we can supply MyInterface. Let's start with the module supplying that:
#Module
public class MyModule {
#Provides
MyInterface providesMyInterface() {
return new MyInterface() {
// my super awesome implementation. MIT license applies.
};
}
}
And to actually use this, we provide a component that can inject into MyTestInjectedClass that is going to need MyClassUsingMyInterface.
#Component(modules = MyModule.class)
public interface MyComponent {
void inject(MyTestInjectedClass testClass);
}
Now we have a way to provide the requested interface. We declared that interface needed by the library class in a constructor marked with #Inject. Now I want a class that requires my awesome library class to use. And I want to inject it with dagger.
public class MyTestInjectedClass {
#Inject
MyClassUsingMyInterface mMyClassUsingMyInterface;
void onStart() {
DaggerMyComponent.create().inject(this);
}
}
Now we hit compile...and dagger will create all the factories needed.
Inject Libraries you can not modify
To just provide the full scale of dagger, this sample could also have been without actual access to the source code of the library. If there is no #Inject annotation dagger will have a hard time creating the object. Notice the missing annotation:
public class MyClassUsingMyInterface {
private MyInterface mMyInterface;
public MyClassUsingMyInterface(MyInterface myInterface) {
mMyInterface = myInterface;
}
}
In that case we have to manually provide the class. The module would be needed to be modified like the following:
#Module
public class MyModule {
#Provides
MyInterface providesMyInterface() {
return new MyInterface() {
};
}
#Provides
MyClassUsingMyInterface providesMyClass(MyInterface myInterface) {
return new MyClassUsingMyInterface(myInterface);
}
}
This introduces more code for us to write, but will make those classes available that you can not modify.
Here's how we are using Guice in a new application:
public class ObjectFactory {
private static final ObjectFactory instance = new ObjectFactory();
private final Injector injector;
private ObjectFactory() throws RuntimeException {
this.injector = Guice.createInjector(new Module1());
}
public static final ObjectFactory getInstance() {
return instance;
}
public TaskExecutor getTaskExecutor() {
return injector.getInstance(TaskExecutor.class);
}
}
Module1 defines how the TaskExecutor needs to be constructed.
In the code we use ObjectFactory.getInstance().getTaskExecutor() to obtain and the instance of TaskExecutor.
In unit tests we want to be able to replace this with a FakeTaskExecutor essentially we want to get an instance of FakeTaskExecutor when ObjectFactory.getInstance().getTaskExecutor() is called.
I was thinking of implementing a FakeModule which would be used by the injector instead of the Module1.
In Spring, we would just use the #Autowired annotation and then define separate beans for Test and Production code and run our tests with the Spring4JunitRunner; we're trying to do something similar with Guice.
Okay, first things first: You don't appear to be using Guice the way it is intended. Generally speaking, you want to use Guice.createInjector() to start up your entire application, and let it create all the constructor arguments for you without ever calling new.
A typical use case might be something like this:
public class Foo {
private final TaskExecutor executor;
#Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
This works because the instances of Foo are themselves injected, all the way up the Object Graph. See: Getting started
With dependency injection, objects accept dependencies in their constructors. To construct an object, you first build its dependencies. But to build each dependency, you need its dependencies, and so on. So when you build an object, you really need to build an object graph.
Building object graphs by hand is labour intensive, error prone, and makes testing difficult. Instead, Guice can build the object graph for you. But first, Guice needs to be configured to build the graph exactly as you want it.
So, typically, you don't create a Singleton pattern and put the injector into it, because you should rarely call Guice.createInstance outside of your main class; let the injector do all the work for you.
All that being said, to solve the problem you're actually asking about, you want to use Jukito.
The combined power of JUnit, Guice and Mockito. Plus it sounds like a cool martial art.
Let's go back to the use case I've described above. In Jukito, you would write FooTest like this:
#RunWith(JukitoRunner.class)
public class FooTest {
public static class Module extends JukitoModule {
#Override
protected void configureTest() {
bindMock(TaskExecutor.class).in(TestSingleton.class);
}
}
#Test
public void testSomething(Foo foo, TaskExecutor executor) {
foo.doSomething();
verify(executor, times(2)).someMethod(eq("Hello World"));
}
}
This will verify that your Mock object, generated by Mockito via Jukito has had the method someMethod called on it exactly two times with the String "Hello World" both times.
This is why you don't want to be generating objects with ObjectFactory in the way you describe; Jukito creates the Injector for you in its unit tests, and it would be very difficult to inject a Mock instead and you'd have to write a lot of boilerplate.
I'm creating a library that will be included as a jar, so it won't contain a main method. I'm wondering what is the best practice for bootstrapping Guice in this case. I have one top level singleton.
public class TestManager
{
private TestManager()
{
}
public static TestManager getInstance()
{
// construct and return singleton
}
public void createSomeObjects()
{
}
}
Where should I bootstrap Guice? I was thinking that in the constructor that I could call Guice.createInjector(new Module()); but it wouldn't inject any of the objects created in createSomeObjects().
Is there a common way to do this when you don't have a main method()?
Cheers.
Much like logging configurations, if this is a true library then your options are pretty much this:
Tell the library user that they are responsible for bootstrapping Guice themselves.
Provide a library initialization method that takes care of bootstrapping Guice if they want to use your library
Trying to make the library super-smart to do self-configuration often ends up with somewhat inflexible, hard to test class hierarchies.
If you're just using Guice in the scope of your library and not for the whole application then you could use a static block in the TestManager class.
This strategy assumes that the application is going to call TestManager.getInstance() at some point and that it is the only entry point into your API.
#Singleton
class TestManager {
private static final TestManager INSTANCE;
static {
INSTANCE = Guice.createInjector(new Module()).getInstance(TestManager.class);
}
private TestManager() {
}
public static TestManager getInstance() {
return INSTANCE;
}
#Inject
public void createSomeObjects(YourDependencies ...) {
// Do something with dependencies
}
}
This is not what you should do, but what you could do:
Let key classes in your library extend or otherwise reference a class that initializes everything in a static block. This is a very dirty hack, but if you make sure your api can't be accessed without the classloader loading your initializer class you should be on the safe side.
You could make it a bit cleaner if you used AspectJ and injected a private Member of the initializer type into all classes in your library (without touching the java code), but it would still be a hack.
I see many Java examples using dependency injection with private fields without a public setter like this:
public SomeClass {
#Inject
private SomeResource resource;
}
But that is a bad idea when the injection should be performed manually for example in unit tests.
There are several possibilities to solve this:
add a public setter: setSomeResource(SomeResource r)
make the field public
make the field package protected
I'd like to avoid the setter, since nothing really happens in it. So I'd prefer public or package protected. What do you recommend?
One way to avoid creating a setter for the field is using constructor injection. This even allows you to declare the field as final.
It goes like this:
public class SomeClass {
private final SomeResource resource;
#Inject
public SomeClass(SomeResource resource) {
this.resource = resource;
}
}
Adding setters is not an optimal solution, since you are adding production code which is not needed.
An alternative is to use Spring's ReflectionTestUtils class to inject your test dependencies using reflection, see http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html
EDIT (2017): However, reflection is an even worse solution than adding setters. The cause of this mess is the fact that Spring makes it possible to inject values without setters or constructors. My current stance is to stick to using either of those and avoid using black magic injection practices.
I prefer the setter
it is easier to debug (put a breakpoint in a setter rather than on field access / modification)
easier to log
easier to add some validation (although this is not always the best place)
easier to support bidirectional maintainance (though IOC container can take care of that)
any other "manual AOP" purpose
But that's just my opinion
I recommend using setter. In this question are the benefits of using getters and setters.
With the help of the answer to my (related to this one) question:
How do app servers inject into private fields?
I coded this simple example on how to inject without setters.
Perhaps it helps
//......................................................
import java.lang.annotation.*;
import java.lang.reflect.*;
//......................................................
#Target(value = {ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#interface Inject {
}
//......................................................
class MyClass {
#Inject
private int theValue = 0;
public int getTheValue() {
return theValue;
}
} // class
//......................................................
public class Example {
//......................................................
private static void doTheInjection(MyClass u, int value) throws IllegalAccessException {
Field[] camps = u.getClass().getDeclaredFields();
System.out.println("------- fields : --------");
for (Field f : camps) {
System.out.println(" -> " + f.toString());
Annotation an = f.getAnnotation(Inject.class);
if (an != null) {
System.out.println(" found annotation: " + an.toString());
System.out.println(" injecting !");
f.setAccessible(true);
f.set(u, value);
f.setAccessible(false);
}
}
} // ()
//......................................................
public static void main(String[] args) throws Exception {
MyClass u = new MyClass();
doTheInjection(u, 23);
System.out.println(u.getTheValue());
} // main ()
} // class
Run output:
------- fields : --------
-> private int MyClass.theValue
found annotation: #Inject()
injecting !
23
With field based injection, you run into the issue you describe with testing. Also with setter based injection, an instance of a class can be created in an incomplete state when running tests if you forget to set some of the dependencies. I have been practicing constructor injection most recently due to the fact that it forces you to set all dependencies whenever you create an instance of a class during testing. The answer above by Andre Rodrigues explains how this would be accomplished.
Possible solutions to this:
Use a CDI-aware testing framework like JGlue CDI-Unit. This way you need no setter. You only define the dependency inside your tests - usually using a Mockito mock object. IMHO this is the best solution, since it doesn't require you to do anything extra for testing.
Inject into Constructor or setter. That's right, you can inject into setters! More details here.
Use a protected setter. Simple and works in every case. Since it's protected, you can access it from your test class (which should have the same package definition as your tested class), and no other packages can access it.
Use a getter and override it when testing. In your test class, create a new inner class that extends the tested class and override the getter. This, however, has a big disadvantage: your test class has to use the getter internally instead of the field. Lots of potentially bugged boilerplate...