mercredi 17 juin 2015

@InterceptorBinding / Weld/ EJB 3.2 - problems with injection

My dev environment is: WildFly 8.1, Weld, EJB 3.2, JDK 1.7, Win 7. App is packed as an ear archive (one ejb + one war) because probably it gonna have other web modules in the future.

I'm struggling with a custom @InterceptorBinding type used inside my EJB stateless bean.

@Inherited
@InterceptorBinding
@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
public @interface DetectIntegrityConstraintsViolation {
}

@ManagedBean
@Interceptor
@DetectIntegrityConstraintsViolation
public class ReferentialIntegrityConstraintViolationInterceptor {

    @PersistenceContext
    private EntityManager em;

    @Resource
    private SessionContext sessionContext;

    // ....
 }

beans.xml:

<beans xmlns="http://ift.tt/19L2NlC"
       xmlns:xsi="http://ift.tt/ra1lAU"
       xsi:schemaLocation="http://ift.tt/19L2NlC http://ift.tt/18tV3H8"
       version="1.1" bean-discovery-mode="annotated">

  <interceptors>
    <class>com.xxx.ejb.ReferentialIntegrityConstraintViolationInterceptor</class>
  </interceptors>
</beans>

When I'm calling my EJB method through REST service I'm getting Error injecting resource into CDI managed bean:

java.lang.IllegalStateException: JBAS011048: Failed to construct component instance  Caused by: java.lang.IllegalArgumentException: JBAS016081: Error injecting resource into CDI managed bean.
Can't find a resource named java:comp/env/com.xxx.ejb.ReferentialIntegrityConstraintViolationInterceptor/sessionContext defined on private javax.ejb.SessionContext com.xxx.ejb.ReferentialIntegrityConstraintViolationInterceptor.sessionContext   at org.jboss.as.weld.services.bootstrap.WeldResourceInjectionServices.resolveResource(WeldResourceInjectionServices.java:188) [wildfly-weld-8.1.0.Final.jar:8.1.0.Final]

So walking in the dark, I've moved to the ResourceLookup approach:

@ManagedBean
@Interceptor
@DetectIntegrityConstraintsViolation
public class ReferentialIntegrityConstraintViolationInterceptor {

    @PersistenceContext
    private EntityManager em;

    private SessionContext sessionContext;

    @PostConstruct
    public void init(InvocationContext ctx) {
        try {
            InitialContext ic = new InitialContext();
            this.sessionContext = (SessionContext)ic.lookup("java:comp/EJBContext");
        } catch (NamingException ex) {
            throw new RuntimeException(ex.getMessage());
        }
    }

    // .....
}

Then Injection started to work, but I got a new error:

Caused by: org.jboss.weld.exceptions.DefinitionException: WELD-000619: An interceptor for lifecycle callbacks Interceptor [class com.xxx.ejb.ReferentialIntegrityConstraintViolationInterceptor intercepts @DetectIntegrityConstraintsViolation] declares and interceptor binding interface com.xxx.ejb.DetectIntegrityConstraintsViolation with METHOD as its @Target.

So when removed from the DetectIntegrityConstraintsViolation a METHOD target:

@Inherited
@InterceptorBinding
@Target({ TYPE /*, METHOD*/ }) // CRUCIAL
@Retention(RUNTIME)
@Documented
public @interface DetectIntegrityConstraintsViolation {
}

Then it started to work. But why??
And why I cannot have my annotation placed on the method? Do somebody know?

BTW: what is even more strange, when i'm not using @InterceptorBinding, but plain old:

@Override
// @DetectIntegrityConstraintsViolation
@Interceptors(ReferentialIntegrityConstraintViolationInterceptor.class)
public User updateUser(final User user) {
    // ...
}

Interceptor works flawlessly even on a method level.

I find EJB and Weld so awkward to use...

Aucun commentaire:

Enregistrer un commentaire