Dependency injection and custom annotation

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 

About dnikiforov

I'm writing here about everything what is in my interest - mathematics, physics, Java, Oracle, C++ and other things. These are just remarks about things I'm working with, and if this helps you, guys, in your work - this makes me happy. ;)
This entry was posted in Java and tagged . Bookmark the permalink.

Leave a comment