package enkan.middleware.jpa;

import enkan.MiddlewareChain;
import enkan.annotation.Middleware;
import enkan.data.Routable;
import enkan.data.jpa.EntityManageable;
import enkan.exception.MisconfigurationException;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.lang.reflect.Method;
import java.util.Optional;

@Middleware(name = "nonJtaTransaction", dependencies = "entityManager")
public class NonJtaTransactionMiddleware<REQ, RES> implements enkan.Middleware<REQ, RES, REQ, RES> {
    private Transactional.TxType getTransactionType(Method m) {
        Transactional transactional = m.getDeclaredAnnotation(Transactional.class);
        return transactional != null ? transactional.value() : null;
    }

    @Override
    public RES handle(REQ req, MiddlewareChain<REQ, RES, ?, ?> chain) {
        EntityManager em = Optional.ofNullable(req)
                .filter(EntityManageable.class::isInstance)
                .map(EntityManageable.class::cast)
                .map(EntityManageable::getEntityManager)
                .orElseThrow(() -> new MisconfigurationException("eclipselink.NOT_ENTITY_MANAGEABLE_REQUEST"));
        if (req instanceof Routable) {
            Routable routable = (Routable) req;
                Method m = routable.getControllerMethod();
                Transactional.TxType type = getTransactionType(m);
                if (type != null) {
                    em.getTransaction().begin();
                    try {
                        RES ret = chain.next(req);
                        em.getTransaction().commit();
                        return ret;
                    } catch (Throwable t) {
                        if (em.getTransaction().isActive()) {
                            em.getTransaction().rollback();
                        }
                        throw t;
                    }
                }
            }
            return chain.next(req);
    }
}

@@ -405,16 +405,17 @@
 ncies = 
+%7B
 %22entityM
@@ -421,16 +421,28 @@
 Manager%22
+, %22routing%22%7D
 )%0Apublic
@@ -536,16 +536,246 @@
  RES%3E %7B%0A
+    private Transactional.TxType getTransactionType(Class%3C?%3E cls) %7B%0A        Transactional transactional = cls.getDeclaredAnnotation(Transactional.class);%0A        return transactional != null ? transactional.value() : null;%0A    %7D%0A%0A
     priv
@@ -1511,126 +1511,265 @@
     
-    Method m = routable.getControllerMethod();%0A                Transactional.TxType type = getTransactionType(m);%0A    
+Transactional.TxType type = getTransactionType(routable.getControllerClass());%0A            Method m = routable.getControllerMethod();%0A            if (m != null) %7B%0A                type = Optional.ofNullable(getTransactionType(m)).orElse(type);%0A            %7D%0A
     
@@ -1804,36 +1804,32 @@
                 
-   
- 
 em.getTransactio
@@ -1857,20 +1857,16 @@
         
-    
 try %7B%0A  
@@ -1883,20 +1883,16 @@
         
-   
- 
 RES ret 
@@ -1910,20 +1910,16 @@
 t(req);%0A
-    
         
@@ -1976,28 +1976,24 @@
             
-  
-  
 return ret;%0A
@@ -1992,20 +1992,16 @@
 rn ret;%0A
-    
         
@@ -2048,28 +2048,24 @@
             
-  
-  
 if (em.getTr
@@ -2106,36 +2106,32 @@
                 
-    
 em.getTransactio
@@ -2162,34 +2162,26 @@
             
- 
-   %7D%0A    
+%7D%0A
             
@@ -2197,38 +2197,16 @@
 hrow t;%0A
-                    %7D%0A
         
@@ -2225,32 +2225,38 @@
           %7D%0A    
+    %7D%0A
         return c

Enable to handle a request whose has no controller method