docs: @Override
      public synchronized ChainData[] initChainGroup(String groupName) throws ChannelException, ChainException, ChainGroupException {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "initChainGroup: " + groupName);
          }
          if (null == groupName) {
              throw new ChainGroupException("Null chain group");
          }
  
          // Verify the group exists in the framework.
          ChainGroupData groupData = this.chainGroups.get(groupName);
          if (null == groupData) {
              throw new ChainGroupException("Unable to find group: " + groupName);
          }
  
          List<ChainData> changedChains = new ArrayList<ChainData>();
          ChainData[] chainDataArray = groupData.getChains();
          StringBuilder sbErrors = new StringBuilder();
          boolean errorOccurred = false;
  
          String chainName = null;
          Chain chain = null;
          // Loop through all the chain names in the list and init them.
          for (int i = 0; i < chainDataArray.length; i++) {
              chainName = chainDataArray[i].getName();
              if (chainDataArray[i].getType().equals(FlowType.OUTBOUND)) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Chain " + chainName + " is outbound so no action being taken.");
                  }
                  continue;
              }
              try {
                  // See if the chain is already in the runtime.
                  chain = getRunningChain(chainName);
                  if (null == chain) {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "Initialize the chain, " + chainName);
                      }
                      initChainInternal(chainDataArray[i]);
                      changedChains.add(chainDataArray[i]);
                  } else {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "Chain already in initialized state, " + chainName);
                      }
                  }
              } catch (Exception e) {
                  String errorString = "Error initializing chain " + chainName + " in group " + groupName + ", exception=" + e;
                  // No FFDC Needed.
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, errorString);
                  }
                  // Note the error so an exception can be thrown later with a list of
                  // chains that couldn't starte.
                  errorOccurred = true;
                  FFDCFilter.processException(e, getClass().getName() + ".initChainGroup", "3327", this, new Object[] { chainName, groupName });
                  sbErrors.append("\r\n");
                  sbErrors.append(errorString);
                  // Get through as many chains as possible as opposed to fail fast.
                  continue;
              }
          }
  
          // Handle any errors if they occurred.
          if (errorOccurred) {
              throw new ChainGroupException(sbErrors.toString());
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "initChainGroup");
          }
          return changedChains.toArray(new ChainData[changedChains.size()]);
      }