2

I am trying to get to the real classes of an instance that I injected via CDI. I only get a designation as a class name, which is composed of the name of the interface, a sequence of numbers and the character string "$Proxy$_$$_Weld$EnterpriseProxy$".

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestProvider {
    String value();
}

public interface TestConnector {

}

@TestProvider("TestConnector1")
@Stateless
public class Test1 implements TestConnector {

}

@Default
@TestProvider("TestConnector2")
@Stateless
public class Test12 implements TestConnector {

}

@Stateless
public class TestFactory {
    
    @Inject
    @Any
    private Instance<TestConnector> testConnectors;
    
    public TestConnector getConnector(String name) {
        ...
    }
    
    public Set<String> listAllTestConnectorNames(){
        try {
            Set<String> connectors = new HashSet<String>();
            
            this.testConnectors.forEach(con -> {
                System.out.println(con.getClass().getName());
                for(Annotation x : con.getClass().getAnnotations()) {
                    if(x instanceof TestProvider) {
                        String name = ((TestProvider) x).value();
                        System.out.println(name);
                        connectors.add(name);
                    }
                }
                this.testConnectors.destroy(con);
            });
            
            return connectors;
        } catch(Exception e) {
            ...
    }
}

The function listAllTestConnectorNames should go through all the determined instances and return the value of the annotation TestProvider as a list. I would expect the following list.

  • TestConnector1
  • TestConnector2

But the instances that I received are of the type de.test.con1.TestConnector $ 710153185 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $ or de.test.con2.TestConnector $ 219965632 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $

How can I read out the values I am looking for?

Net_Hans
  • 115
  • 12
  • Your problem seems to be a [xy one](https://xyproblem.info). Why would you need such data? Is it to select a given implementation at runtime? Does [this](https://stackoverflow.com/questions/15231255/understanding-the-necessity-of-type-safety-in-cdi/15313148#15313148) solves your real problem? In more elaborate cases, you could use testConnectors.select with a proper AnnotationLiteral to select "dinamically" your ben. Is it your concrete goal? – Paulo Araújo Aug 10 '20 at 11:52
  • I have a real problem behind this. I need to get to the respective value of the TestProvider annotation. The classes, annotations and interfaces are only called "textXYZ" for stackoverflow. In the real application these are of course given reasonable names. – Net_Hans Aug 11 '20 at 11:29
  • 1
    I did not mean to offend you. I know you have a real problem. My point is that maybe your approach to the problem can be exchanged by a more architectural prone, instead of meddling with class hierarchies or, as suggested in the answer by @laid-nelson, weakly linked to a given implementation. Anyway, if you follow the answer, you will be safe (while changes are not made in Weld) for some time. – Paulo Araújo Aug 12 '20 at 11:51

1 Answers1

3

Your TestConnector instances are being proxied by Weld, probably because they are in a normal scope. This is fine and expected.

Your question, therefore, is: "Given a (Weld-defined) proxy class, how do I get the name of the 'real' class it is proxying?"

There is not a way that is guaranteed to work, but this way will work with Weld implementations of CDI:

Weld's proxy classes have the SYNTHETIC flag set on them and in general extend the class they are proxying. I don't think this is guaranteed, but it has been true for many versions and many years now.

So if you do something like:

Class<?> c = proxyClass;
while (c.isSynthetic()) {
  c = c.getSuperclass();
}
// Now c is the "real" class
System.out.println(c.getName()); // shouldn't be a proxy class name anymore

…you should be good.

Laird Nelson
  • 15,321
  • 19
  • 73
  • 127