code: private void addTriggerFailedAndExitTxn(CodeBuilder b,
                                              String opType,
                                              LocalVariable triggerVar,
                                              LocalVariable txnVar,
                                              LocalVariable stateVar)
      {
          TypeDesc transactionType = TypeDesc.forClass(Transaction.class);
  
          // if (trigger != null) {
          b.loadLocal(triggerVar);
          Label isNull = b.createLabel();
          b.ifNullBranch(isNull, true);
  
          //     try {
          //         trigger.failedXxx(this, state);
          //     } catch (Throwable e) {
          //         uncaught(e);
          //     }
          Label tryStart = b.createLabel().setLocation();
          b.loadLocal(triggerVar);
          b.loadThis();
          b.loadLocal(stateVar);
          b.invokeVirtual(TypeDesc.forClass(Trigger.class), "failed" + opType, null,
                          new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.OBJECT});
          Label tryEnd = b.createLabel().setLocation();
          Label cont = b.createLabel();
          b.branch(cont);
          b.exceptionHandler(tryStart, tryEnd, Throwable.class.getName());
          b.invokeStatic(UNCAUGHT_METHOD_NAME, null,
                         new TypeDesc[] {TypeDesc.forClass(Throwable.class)});
          cont.setLocation();
  
          //     txn.exit();
          b.loadLocal(txnVar);
          b.invokeInterface(transactionType, EXIT_METHOD_NAME, null, null);
  
          isNull.setLocation();
      }
docs: Generates code to call a trigger after the persistence operation has
  failed.
  
  @param opType type of operation, Insert, Update, or Delete
  @param triggerVar required variable of type Trigger for retrieving trigger
  @param txnVar required variable of type Transaction for storing transaction
  @param stateVar required variable of type Object for retrieving state