tags:

views:

209

answers:

1

Hi,

I am using Seam to inject beans to my controller using @In annotation. The injected class has a custom annotation, when calling injectedClass.getClass().getAnnotation(annotationClass) it returns null.

When debug I found that Seam passes a proxy instance so getClass() returns InjectedClass_$$_javassist_seam_5 which doesn't have my custom annotation.

How I can get my custom annotation from the proxy class?

Here's how my classes look like:

@CustomAnnotation(value="myvalue")
@Name("myAnnotatedClass")
public class MyAnnotatedClass extends SuperClass {...}

@Scope(ScopeType.SESSION)
@Name("myController")
public class MyController {
     @In("#{myAnnotatedClass}")
     private MyAnnotatedClass myAnnotatedClass;

     public void actionMethod(){
         //call another class which call myAnnotatedClass.getClass().getAnnotation(CustomAnnotation.class)
         //then do some reflection for MyAnnotatedClass fields 
     }
}
+1  A: 

Hi Noura,

Good question.

When you call a method by using Seam, it is intercepted by a proxy. And this one enables @In or @Out-jection. But There is an exception to this rule: it does not work when you call an internal method

So try this code

@Name
public class Service {

    @In
    private MyAnnotatedClass myAnnotatedClass;


    public void myInterceptedMethod() {
        // internal method bypass interceptor
        // So @In or @Out-jection is not enabled
        internalMethod();
    }

    private void internalMethod() {
        System.out.println(myAnnotatedClass.getClass().getAnnotation(annotationClass));
    }

}

Added to original answer

You want to retrieve an annotation from your bean. But, because of method interceptor, myAnnotatedClass.getClass() returns a proxy object, not the bean class itself.

For each bean class, Seam creates a Component definition, in which is stored in the application context. The name of the attribute follows this pattern: component name plus .component. So if you have a bean like this one

@Name("myBean")
public class MyBean {

}

Its Componet definition is stored in the attribute myBean.component

So inside your method, you can use

Component myBeanComponentDefinition = (Component) Context.getApplicationContext().get("myBean.component");

Now you can call

myBeanComponentDefinition.getBeanClass().getAnnotation(CustomAnnotation.class);

regards,

Arthur Ronald F D Garcia
Thanks for your reply, but it doesn't work.I used a wrapper for MyAnnotatedClass, the wrapper has @Name annotation instead of MyAnnotatedClass. Now the controller has the wrapper injected and it calls wrapper.getMyAnnotatedClass().getAnnotation(annotationClass) I think it is an ugly solution, but it fixed the problem till we have a better one.
Noura
yes, that gets the annotation. I could also get annotation using myAnnotatedClass.getSuperClass().getAnnotation(CustomAnnotation.class), But I cannot get fields by reflection. I iterate on myAnnotatedClass.getSuperClass().getClass().getDeclaredFields(). Then call field.get(myAnnotatedClass), when pass the proxy object it throws exception.
Noura