@Override
  public void leave(DelegateExecution execution) {

    if (log.isDebugEnabled()) {
      log.debug("Leaving exclusive gateway '{}'", execution.getCurrentActivityId());
    }

    ExclusiveGateway exclusiveGateway = (ExclusiveGateway) execution.getCurrentFlowElement();
    
    if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
      Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
          ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_COMPLETED, exclusiveGateway.getId(), exclusiveGateway.getName(), execution.getId(),
              execution.getProcessInstanceId(), execution.getProcessDefinitionId(), exclusiveGateway));
    }

    SequenceFlow outgoingSequenceFlow = null;
    SequenceFlow defaultSequenceFlow = null;
    String defaultSequenceFlowId = exclusiveGateway.getDefaultFlow();

    // Determine sequence flow to take
    Iterator<SequenceFlow> sequenceFlowIterator = exclusiveGateway.getOutgoingFlows().iterator();
    while (outgoingSequenceFlow == null && sequenceFlowIterator.hasNext()) {
      SequenceFlow sequenceFlow = sequenceFlowIterator.next();
      
      String skipExpressionString = sequenceFlow.getSkipExpression();
      if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpressionString)) {
        boolean conditionEvaluatesToTrue = ConditionUtil.hasTrueCondition(sequenceFlow, execution);
        if (conditionEvaluatesToTrue && (defaultSequenceFlowId == null || !defaultSequenceFlowId.equals(sequenceFlow.getId()))) {
          if (log.isDebugEnabled()) {
            log.debug("Sequence flow '{}'selected as outgoing sequence flow.", sequenceFlow.getId());
          }
          outgoingSequenceFlow = sequenceFlow;
        }
      } else if (SkipExpressionUtil.shouldSkipFlowElement(Context.getCommandContext(), execution, skipExpressionString)) {
        outgoingSequenceFlow = sequenceFlow;
      }

      // Already store it, if we would need it later. Saves one for loop.
      if (defaultSequenceFlowId != null && defaultSequenceFlowId.equals(sequenceFlow.getId())) {
        defaultSequenceFlow = sequenceFlow;
      }
      
    }
    
    // We have to record the end here, or else we're already past it
    Context.getCommandContext().getHistoryManager().recordActivityEnd((ExecutionEntity) execution, null);

    // Leave the gateway
    if (outgoingSequenceFlow != null) {
      execution.setCurrentFlowElement(outgoingSequenceFlow);
    } else {
      if (defaultSequenceFlow != null) {
        execution.setCurrentFlowElement(defaultSequenceFlow);
      } else {

        // No sequence flow could be found, not even a default one
        throw new ActivitiException("No outgoing sequence flow of the exclusive gateway '" + exclusiveGateway.getId() + "' could be selected for continuing the process");
      }
    }

    super.leave(execution);
  }
@ Override public void leave ( DelegateExecution execution ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "Leaving exclusive gateway '{}'" , execution . getCurrentActivityId ( ) ) ; } ExclusiveGateway exclusiveGateway = ( ExclusiveGateway ) execution . getCurrentFlowElement ( ) ; if ( Context . getProcessEngineConfiguration ( ) != null && Context . getProcessEngineConfiguration ( ) . getEventDispatcher ( ) . isEnabled ( ) ) { Context . getProcessEngineConfiguration ( ) . getEventDispatcher ( ) . dispatchEvent ( ActivitiEventBuilder . createActivityEvent ( ActivitiEventType . ACTIVITY_COMPLETED , exclusiveGateway . getId ( ) , exclusiveGateway . getName ( ) , execution . getId ( ) , execution . getProcessInstanceId ( ) , execution . getProcessDefinitionId ( ) , exclusiveGateway ) ) ; } SequenceFlow outgoingSequenceFlow = null ; SequenceFlow defaultSequenceFlow = null ; String defaultSequenceFlowId = exclusiveGateway . getDefaultFlow ( ) ; Iterator < SequenceFlow > sequenceFlowIterator = exclusiveGateway . getOutgoingFlows ( ) . iterator ( ) ; while ( outgoingSequenceFlow == null && sequenceFlowIterator . hasNext ( ) ) { SequenceFlow sequenceFlow = sequenceFlowIterator . next ( ) ; String skipExpressionString = sequenceFlow . getSkipExpression ( ) ; if ( ! SkipExpressionUtil . isSkipExpressionEnabled ( execution , skipExpressionString ) ) { boolean conditionEvaluatesToTrue = ConditionUtil . hasTrueCondition ( sequenceFlow , execution ) ; if ( conditionEvaluatesToTrue && ( defaultSequenceFlowId == null || ! defaultSequenceFlowId . equals ( sequenceFlow . getId ( ) ) ) ) { if ( log . isDebugEnabled ( ) ) { log . debug ( "Sequence flow '{}'selected as outgoing sequence flow." , sequenceFlow . getId ( ) ) ; } outgoingSequenceFlow = sequenceFlow ; } } else if ( SkipExpressionUtil . shouldSkipFlowElement ( Context . getCommandContext ( ) , execution , skipExpressionString ) ) { outgoingSequenceFlow = sequenceFlow ; } if ( defaultSequenceFlowId != null && defaultSequenceFlowId . equals ( sequenceFlow . getId ( ) ) ) { defaultSequenceFlow = sequenceFlow ; } } Context . getCommandContext ( ) . getHistoryManager ( ) . recordActivityEnd ( ( ExecutionEntity ) execution , null ) ; if ( outgoingSequenceFlow != null ) { execution . setCurrentFlowElement ( outgoingSequenceFlow ) ; } else { if ( defaultSequenceFlow != null ) { execution . setCurrentFlowElement ( defaultSequenceFlow ) ; } else { throw new ActivitiException ( "No outgoing sequence flow of the exclusive gateway '" + exclusiveGateway . getId ( ) + "' could be selected for continuing the process" ) ; } } super . leave ( execution ) ; }
The default behaviour of BPMN, taking every outgoing sequence flow (where the condition evaluates to true), is not valid for an exclusive gateway.

Hence, this behaviour is overridden and replaced by the correct behavior: selecting the first sequence flow which condition evaluates to true (or which hasn't got a condition) and leaving the
activity through that sequence flow.

If no sequence flow is selected (ie all conditions evaluate to false), then the default sequence flow is taken (if defined).