tx-lcn icon indicating copy to clipboard operation
tx-lcn copied to clipboard

LCN debug time out, occur NullPointException and lock db record.

Open West-Z-Y-Wu opened this issue 6 years ago • 0 comments

Although others also meet the similar situation, the exception seems not same.

1. Bug Description

When I debug in LCN model, it throw the "dtx timeout" LCNBusinessException. And when it catch the exception and handle, NullPointException is thrown in the handler logic. What's more, it also lock the table dbs. If I really run in timeout situation, I think NullPointException will be thrown as well.

2. Environment:

  • JDK version: 1.8
  • OS: window 10
  • TX-LCN version: 5.0.0.RELEASE
  • Others:

3. Exception Stacktrace

java.lang.NullPointerException: null
	at com.codingapi.txlcn.tc.core.checking.DefaultDTXExceptionHandler.handleNotifyGroupBusinessException(DefaultDTXExceptionHandler.java:97)
	at com.codingapi.txlcn.tc.core.template.TransactionControlTemplate.notifyGroup(TransactionControlTemplate.java:159)
	at com.codingapi.txlcn.tc.core.transaction.lcn.control.LcnStartingTransaction.postBusinessCode(LcnStartingTransaction.java:65)
	at com.codingapi.txlcn.tc.core.DTXServiceExecutor.transactionRunning(DTXServiceExecutor.java:109)
	at com.codingapi.txlcn.tc.aspect.weave.DTXLogicWeaver.runTransaction(DTXLogicWeaver.java:95)
	at com.codingapi.txlcn.tc.aspect.TransactionAspect.runWithLcnTransaction(TransactionAspect.java:93)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)

4. Code

TransactionControlTemplate.java

public void notifyGroup(String groupId, String unitId, String transactionType, int state) {
    try {
      this.txLogger.transactionInfo(groupId, unitId, "notify group > {} > groupId: {xid}, unitId: {uid}, state: {}.", new Object[]{transactionType, state});
      if (this.globalContext.isDTXTimeout()) {
        throw new LcnBusinessException("dtx timeout.");
      }

      this.reliableMessenger.notifyGroup(groupId, state);
      this.transactionCleanTemplate.clean(groupId, unitId, transactionType, state);
      log.debug("{} > close transaction group.", transactionType);
    } catch (TransactionClearException var6) {
      log.error("clear exception", var6);
      this.txLogger.trace(groupId, unitId, "Transaction Error", "clean transaction fail.", new Object[0]);
    } catch (RpcException var7) {
      this.dtxExceptionHandler.handleNotifyGroupMessageException(Arrays.asList(groupId, state, unitId, transactionType), var7);
    } catch (LcnBusinessException var8) {
      this.dtxExceptionHandler.handleNotifyGroupBusinessException(Arrays.asList(groupId, state, unitId, transactionType), var8.getCause());
    }

    this.txLogger.transactionInfo(groupId, unitId, "notify group exception state %d.", new Object[]{state});
  }

DefaultDTXExceptionHandler.java

public void handleNotifyGroupBusinessException(Object params, Throwable ex) {
    List paramList = (List)params;
    String groupId = (String)paramList.get(0);
    int state = (Integer)paramList.get(1);
    String unitId = (String)paramList.get(2);
    String transactionType = (String)paramList.get(3);
   
    /*
     * need to validate the ex whether is null 
     */

    if (ex instanceof UserRollbackException) {
      state = 0;
    }

    if (ex.getCause() != null && ex.getCause() instanceof UserRollbackException) {
      state = 0;
    }

    try {
      this.transactionCleanTemplate.clean(groupId, unitId, transactionType, state);
    } catch (TransactionClearException var9) {
      log.error("{} > clean transaction error.", transactionType);
    }
  }

5. Tour Idea

Do a validation in DefaultDTXExceptionHandler.handleNotifyGroupBusinessException, validate whether the ex is null at first. Also need the validation in the similar code.

West-Z-Y-Wu avatar Nov 18 '19 12:11 West-Z-Y-Wu