[ 
https://issues.apache.org/jira/browse/TOMEE-2043?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16032853#comment-16032853
 ] 

Svetlin Zarev edited comment on TOMEE-2043 at 6/1/17 11:53 AM:
---------------------------------------------------------------

Your test case passes because the transaction is started in the TxRequired 
policy. While my sample app fails, because the transaction is ".begin()"ed 
manually in the servlet:

{code}
 transaction.begin();
 transactionalBean.withDontRollbackOn();
 transaction.commit();
{code}

ThRequired policy: 
{code}
    public void commit() throws ApplicationException, SystemException {
        // only commit if we started the transaction
        if (clientTx == null) {
            completeTransaction(currentTx);
        } else {
            fireNonTransactionalCompletion();
        }
    }
{code}

So in the junit test case, the execution goes to the "clientTx == null" branch, 
while in my case it goes to  " fireNonTransactionalCompletion();" IMO that's 
fine in all cases except for if this is the outermost interceptor, because in 
that case there is no one to complete the transaction.

What do you think ?


was (Author: svetlinzarev):
Your test case passes because the transaction is started in the TxRequired 
policy. While may sample app fails, because the transaction is ".begin()"ed 
manually in the servlet:

{code}
 transaction.begin();
 transactionalBean.withDontRollbackOn();
 transaction.commit();
{code}

ThRequired policy: 
{code}
    public void commit() throws ApplicationException, SystemException {
        // only commit if we started the transaction
        if (clientTx == null) {
            completeTransaction(currentTx);
        } else {
            fireNonTransactionalCompletion();
        }
    }
{code}

So in the junit test case, the execution goes to the "clientTx == null" branch, 
while in my case it goes to  " fireNonTransactionalCompletion();" IMO that's 
fine in all cases except for if this is the outermost interceptor, because in 
that case there is no one to complete the transaction.

> Thread local transactions are left open across requests
> -------------------------------------------------------
>
>                 Key: TOMEE-2043
>                 URL: https://issues.apache.org/jira/browse/TOMEE-2043
>             Project: TomEE
>          Issue Type: Bug
>          Components: TomEE Core Server
>    Affects Versions: 7.0.3
>            Reporter: Svetlin Zarev
>         Attachments: sample.zip
>
>
> @Transactional CDI bean methods annotated with     
> @Transactional(dontRollbackOn = SomeException.class) do not commit the 
> transaction at the end of the request/response cycle when the SomeException 
> exception is thrown. As a result the thread local transaction object is 
> preserved across requests which makes unrelated requests to fail with "Nested 
> transactions are not supported".
> Sample application that reproduces the issue is attached to the ticket. Just 
> request the application several times and observe how the output is changing.
> Sample valve that can be used to demonstrate the issue: 
> {code}
> public final class LeakedTransactionDetectionValve extends ValveBase {
>     private static final Logger logger = 
> Logger.getLogger(LeakedTransactionDetectionValve.class.getName());
>     @Override
>     public void invoke(Request request, Response response) throws 
> IOException, ServletException {
>         boolean hasActiveTransaction = false;
>         try {
>             final Collection<Transaction> transactionsBeforeRequest = 
> getTransactions();
>             for (Transaction transaction : transactionsBeforeRequest) {
>                 if (transaction.getStatus() == Status.STATUS_ACTIVE) {
>                     hasActiveTransaction = true;
>                     break;
>                 }
>             }
>         } catch (Exception ex) {
>             //no-op
>         }
>         getNext().invoke(request, response);
>         if (!hasActiveTransaction) {
>             try {
>                 final Collection<Transaction> transactionsAfterRequest = 
> getTransactions();
>                 for (Transaction transaction : transactionsAfterRequest) {
>                     if (transaction.getStatus() == Status.STATUS_ACTIVE) {
>                         logger.log(Level.SEVERE, "Found active transaction: "
>                                 + request.getRequestURI()
>                                 + "?"
>                                 + request.getQueryString()
>                         );
>                     }
>                 }
>             } catch (Exception ex) {
>                 logger.log(Level.SEVERE, "Failed to determine thread local 
> transaction status.", ex);
>             }
>         }
>     }
>     Collection<Transaction> getTransactions() throws NoSuchFieldException, 
> IllegalAccessException {
>         final Field threadLocalsField = 
> Thread.class.getDeclaredField("threadLocals");
>         threadLocalsField.setAccessible(true);
>         final Object threadLocals = 
> threadLocalsField.get(Thread.currentThread());
>         final Field tableField = 
> threadLocals.getClass().getDeclaredField("table");
>         tableField.setAccessible(true);
>         final Object table = tableField.get(threadLocals);
>         final Collection<Transaction> transactions = new LinkedList<>();
>         for (int i = 0; i < Array.getLength(table); i++) {
>             final Object entry = Array.get(table, i);
>             if (null != entry) {
>                 final Field valueField = 
> entry.getClass().getDeclaredField("value");
>                 valueField.setAccessible(true);
>                 final Object value = valueField.get(entry);
>                 if (value instanceof Transaction) {
>                     transactions.add((Transaction) value);
>                 }
>             }
>         }
>         return transactions;
>     }
> {code}
> PS: in addition to the issue above, the 
> org.apache.openejb.cdi.transactional.InterceptorBase must not wrap the 
> exception specified in the "donotRollbackOn" attribute inside 
> TransactionalException



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to