Search code examples
javacdiinterceptorweld

CDI Transactional Interceptor not working


I have a Java SE application with these classes:

main:

public static void main(String args[])
    {
        Weld weld = new Weld(); 
        WeldContainer container = weld.initialize(); 

        ShopCar sc = container.instance().select(ShopCar.class).get(); 
        sc.execute();
        weld.shutdown();
    }

My DAO(not fully implemented):

/**
 *
 * @author vFreitas
 * @param <T> The type T 
 */
public class JpaDAO<T> implements DAO<T>, Serializable
{
    /* The EntityManager of my connection */
    private final EntityManager em;
    /* The class to be persist */
    private final Class<T> classe;

    private ThreadLocal<EntityManager> threadLocal;

    /* Builder */
    /**
    *
    * @author info1
    * @param classe The class to that will represent T
    * @param em A new instance of EntityManager 
    */
    public JpaDAO(Class<T> classe, EntityManager em)
    {
        this.classe = classe;
        this.em = em;
        threadLocal = new ThreadLocal<>();
        threadLocal.set(em);
    }

    @Override
    @Transacional
    public void save(T entity)
    {
        //em.getTransaction().begin();
        em.persist(entity);
        //em.getTransaction().commit();
    }

...

My DAOFactory:

public class DAOFactory<T>
{
    @Inject @MyDatabase private EntityManager em;

    @SuppressWarnings({ "rawtypes", "unchecked" })    
    @Produces
    public JpaDAO<T> createJpaDAO(InjectionPoint injectionPoint) throws 
            ClassNotFoundException 
    {    
        ParameterizedType type = (ParameterizedType) injectionPoint.getType();    
        Class classe = (Class) type.getActualTypeArguments()[0];   
        return new JpaDAO<>(classe,em);    
    }    
}

Interceptor annotation:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@InterceptorBinding
public @interface Transacional 
{

}

and my interceptorImpl:

@Interceptor
@Transacional
public class TransacionalInterceptor 
{

    @Inject @MyDatabase
    private EntityManager manager;

    @Inject private ThreadLocal<EntityManager> threadLocal;

    Logger logger = LoggerFactory.getLogger(TransacionalInterceptor.class);

    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception 
    {
        manager = threadLocal.get();
        //EntityTransaction trx = manager.getTransaction();
        if(!manager.getTransaction().isActive())
        {
            manager.getTransaction().begin();
            System.out.println("Starting transaction");
            Object result = context.proceed();
            manager.getTransaction().commit();
            System.out.println("Committing transaction");
            return result;
        }

beans.xml:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd" >

    <interceptors>
        <class>shopcar.util.TransacionalInterceptor</class>
    </interceptors>
</beans>

When I save a entity it says that I need to open my transaction...so my interceptor is not being invoked. I did a lot of search and don't know what is the problem with my code. I appreciate some help. Thanks!


Solution

  • Ok, I had to re-read your question to see the issue.

    The problem is that in your producer method, you're instantiating a DAO. Because you instantiate it using new you bypass the interceptor bindings.