Search code examples
javacdijboss-weld

Get the real object from CDI Proxy


I looked for a clean CDI solution and not a WELD dependent one but so far nothing...

I need to test if every element of a list of objects that I get with @Inject @Any MyInterface beans is a proxy, and when true I need to get the real object to do introspection and get all the properties of the object.

My WELD implementation:

MyInterface interf = obj;
if (isProxy(interf )) {
        interf = (Config) ((TargetInstanceProxy)interf ).getTargetInstance();
}

where isProxy is so defined (CDI solution?):

public boolean isProxy(Object obj) {
    try{
        return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
    } catch (Exception e) {
        LOGGER.error("Unable to check if object is proxy", e);
    }
    return false;
}

Any suggestions /Indications. In the official documentation I found no mention of introspection (here)

And then I would like to get all the properties of the bean with something like this:

Arrays.stream(interf.getClass().getDeclaredFields()).forEach(
                        field -> extractStuff(...)
                );

We use Wildfly and WELD but don't want to bind us to an implementation of CDI. Thanks in advance!

EDIT: The question is, more precisely: Do you know a clean CDI solution that WELD is already implementing with TargetInstanceProxy? Not if I need to go back to school or if I understand what I'm writing.. Thanks for taking time to help!


Solution

  • CDI is intentionally hiding (or rather not exposing) the internals as they should be unimportant to end user when programming against interface.Furthermore messing with this can cause weird errors as you should always be invoking methods via proxy, not the actual instance.

    So the short answer is - no, there is no pure CDI way to do this. (At least not an intended one.)

    However, seeing that you are using Weld already, there are other ways. Weld comes with pretty much any EE server excepting TomEE, so depending on Weld API should be pretty safe. Now why am I saying this - in Weld 3.x (WildFly 12+), the API was extended to contain WeldConstruct and WeldClientProxy which are interfaces implemented by either Weld sublasses (interceptors/decorators) and/or client proxies - see javadocs of those classes for more information.

    So if you must do this, then you could add a dependency on Weld API as such:

    <dependency>
      <groupId>org.jboss.weld</groupId>
      <artifactId>weld-api</artifactId>
      <version>x.y.z</version>
    </dependency>
    

    And then, in your code, you can check if injected object is a proxy by doing:

    @Inject
    Foo foo;
    
    public void doSomething() {
      if (foo instanceof WeldClientProxy) {
        // foo is a proxy
      } else {
        // not a proxy
      }
    }
    

    If you want to obtain actual instances, WeldClientProxy allows you to obtain Metadata from which you can the retrieve the underlying contextual instance. That's the closest I can get you to what you are after.