Java EE provides a couple of extremely attractive options – DI (dependency injection feature) and custom annotations what allow qualify classes you develop. They bring remarkable flexibility in the job – but if you keep in mind the technique they use.
Couple of days ago I had to resolve some issue in the third-party code. I will simulate the case and keep the main idea of design to demonstrate what was the issue. Let’s create the basic interface and a custom annotation:
public interface SimpleInterface { String msg(); }
@Target({TYPE}) @Retention(RUNTIME) public @interface QualifyerA { }
Also we create simple class and allow DI using @SessionScoped annotation.
@SessionScoped @QualifyerA public class SimpleClass implements SimpleInterface, Serializable { public String msg() { return "Got it"; } }
Finally let’s create managed bean and the simple JSF to check results:
@ManagedBean public class SimpleBean { SimpleInterface si = new SimpleClass(); public String result() { if (si.getClass().isAnnotationPresent(QualifyerA.class)) return si.msg(); else return "Not annotated"; } public String showClass() { return si.getClass().getName(); } }
A piece of JSF code:
Hello, #{simpleBean.result()}
If we start the application on Web application server we get:
Hello, Got it
OK, everything is well so far. Let’s now use the injection instead of explicit instantiation:
public class SimpleBean { @Inject SimpleInterface si; public String result() { if (si.getClass().isAnnotationPresent(QualifyerA.class)) return si.msg(); ...
And we have failed:
Hello, Not annotated
Oops, we lost something, but what ? We can understand what happens if we look as the variable real class (
let’s change JSF code):
Hello, #{simpleBean.showClass()}
We get:
Hello, com.tray.SimpleClass$Proxy$_$$_WeldClientProxy
As you can see, Injection uses proxy class and, hence, we lost annotation information.
What we can do is to apply @Inherited to our custom annotation:
@Target({TYPE}) @Retention(RUNTIME) @Inherited public @interface QualifyerA { }
After forcing the inheritance we gat what we need (don’t forget to restore original JSF code)
Hello, Got it