Net_Hans
Net_Hans

Reputation: 185

Java EE CDI Instance | How to get real class

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.

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?

Upvotes: 3

Views: 622

Answers (1)

Laird Nelson
Laird Nelson

Reputation: 16196

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.

Upvotes: 3

Related Questions