0

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.

enkor
  • 167
  • 14

2 Answers2

0

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.

Peter
  • 1,769
  • 1
  • 14
  • 18
  • Yes. Thats the problem I'm not using Weld classloader. My producer is just a bad try, don't look at it. So my question is: How can I use Weld to instantiate my object this or similar way. Because I don't know what class I will instantiate. I only know that they will implements the Module interface and I can have a lot of objects in future so It's impossible to instantiate them some other way. – enkor Sep 03 '14 at 17:14
  • Okay but this seems to be a paradoxes. As cdi is declarative it sort of bites with dynamic types and like I said the decency injection is taking place at a point you can't reach via reflection. Your object isn't know to the cdi provider instantiated that way – Peter Sep 03 '14 at 17:38
  • Maybe you can use your own class loader calling the cdi classloader but as this is a security issue I guess your weld provider (container) will not permitt such an approach and because of the use of reflection it would mean proxying the reflection objects themself which is really heavy stuff – Peter Sep 03 '14 at 17:43
  • Still you can exchange your the implementation of the interface you are using with modularization as you could switch the jar file implementing it. – Peter Sep 03 '14 at 17:46
  • The use of the @New annotation sort of adds dynamic aspects to producers methods but still the types to be produced would have to be known leaving you with a list of produceable implementation of your interface if the implementations are beans themself. – Peter Sep 03 '14 at 18:07
  • So you could switch the module implementation you use based on a properties file if the requested class is known to the producer method (included in the list) – Peter Sep 03 '14 at 18:08
  • (basically this is a dependency injection into your producer method itself and returning just the requested type) – Peter Sep 03 '14 at 18:14
  • Thank you for your comments. I will try the list in producer it seems loggical and it could works. – enkor Sep 03 '14 at 19:09
  • I cannot get it work with producers, so I found a workaround. See my post. But Thank you very much for your help. – enkor Sep 03 '14 at 19:59
  • Interesting approach. – Peter Sep 03 '14 at 21:34
0

See edited post. If someone have a better solution I will be glad for it.

enkor
  • 167
  • 14