public void storeWorkflowDefinition(
      AbstractWorkflowDefinition<? extends WorkflowState> definition) {
    StoredWorkflowDefinition storedDefinition = convert(definition);
    MapSqlParameterSource params = new MapSqlParameterSource();
    params.addValue("type", definition.getType());
    String serializedDefinition = serializeDefinition(storedDefinition);
    params.addValue("definition_sha1", sha1(serializedDefinition));
    params.addValue("definition", serializedDefinition, sqlVariants.longTextType());
    params.addValue("modified_by", executorInfo.getExecutorId());
    params.addValue("executor_group", executorInfo.getExecutorGroup());

    String sql =
        "update nflow_workflow_definition "
            + "set definition = :definition, modified_by = :modified_by, definition_sha1 = :definition_sha1 "
            + "where type = :type and executor_group = :executor_group and definition_sha1 <> :definition_sha1";
    int updatedRows = namedJdbc.update(sql, params);
    if (updatedRows == 0) {
      sql =
          "insert into nflow_workflow_definition(type, definition_sha1, definition, modified_by, executor_group) "
              + "values (:type, :definition_sha1, :definition, :modified_by, :executor_group)";
      try {
        namedJdbc.update(sql, params);
      } catch (DataIntegrityViolationException dex) {
        logger.debug("Another executor already stored the definition.", dex);
      }
    }
  }
 StoredWorkflowDefinition convert(AbstractWorkflowDefinition<? extends WorkflowState> definition) {
   StoredWorkflowDefinition resp = new StoredWorkflowDefinition();
   resp.type = definition.getType();
   resp.description = definition.getDescription();
   resp.onError = definition.getErrorState().name();
   Map<String, StoredWorkflowDefinition.State> states = new HashMap<>();
   for (WorkflowState state : definition.getStates()) {
     states.put(
         state.name(),
         new StoredWorkflowDefinition.State(
             state.name(), state.getType().name(), state.getDescription()));
   }
   for (Entry<String, List<String>> entry : definition.getAllowedTransitions().entrySet()) {
     StoredWorkflowDefinition.State state = states.get(entry.getKey());
     for (String targetState : entry.getValue()) {
       state.transitions.add(targetState);
     }
     sort(state.transitions);
   }
   for (Entry<String, WorkflowState> entry : definition.getFailureTransitions().entrySet()) {
     StoredWorkflowDefinition.State state = states.get(entry.getKey());
     state.onFailure = entry.getValue().name();
   }
   resp.states = new ArrayList<>(states.values());
   sort(resp.states);
   return resp;
 }