docs: private void unregisterClient(ActionBean action) throws ActionException {
          if (!securityContext.hasPermission(PermissionType.clientAdmin, action.getOrganizationId()))
              throw ExceptionFactory.notAuthorizedException();
  
          ClientVersionBean versionBean;
          List<ContractSummaryBean> contractBeans;
          try {
              versionBean = orgs.getClientVersion(action.getOrganizationId(), action.getEntityId(), action.getEntityVersion());
          } catch (ClientVersionNotFoundException e) {
              throw ExceptionFactory.actionException(Messages.i18n.format("ClientNotFound")); //$NON-NLS-1$
          }
          try {
              contractBeans = query.getClientContracts(action.getOrganizationId(), action.getEntityId(), action.getEntityVersion());
          } catch (StorageException e) {
              throw ExceptionFactory.actionException(Messages.i18n.format("ClientNotFound"), e); //$NON-NLS-1$
          }
  
          // Validate that it's ok to perform this action - client must be Ready.
          if (versionBean.getStatus() != ClientStatus.Registered) {
              throw ExceptionFactory.actionException(Messages.i18n.format("InvalidClientStatus")); //$NON-NLS-1$
          }
  
          Client client = new Client();
          client.setOrganizationId(versionBean.getClient().getOrganization().getId());
          client.setClientId(versionBean.getClient().getId());
          client.setVersion(versionBean.getVersion());
  
          // Next, unregister the client from *all* relevant gateways.  This is done by
          // looking up all referenced APIs and getting the gateway information for them.
          // Each of those gateways must be told about the client.
          try {
              storage.beginTx();
              Map<String, IGatewayLink> links = new HashMap<>();
              for (ContractSummaryBean contractBean : contractBeans) {
                  ApiVersionBean svb = storage.getApiVersion(contractBean.getApiOrganizationId(),
                          contractBean.getApiId(), contractBean.getApiVersion());
                  Set<ApiGatewayBean> gateways = svb.getGateways();
                  if (gateways == null) {
                      throw new PublishingException("No gateways specified for API: " + svb.getApi().getName()); //$NON-NLS-1$
                  }
                  for (ApiGatewayBean apiGatewayBean : gateways) {
                      if (!links.containsKey(apiGatewayBean.getGatewayId())) {
                          IGatewayLink gatewayLink = createGatewayLink(apiGatewayBean.getGatewayId());
                          links.put(apiGatewayBean.getGatewayId(), gatewayLink);
                      }
                  }
              }
              storage.commitTx();
              for (IGatewayLink gatewayLink : links.values()) {
                  gatewayLink.unregisterClient(client);
                  gatewayLink.close();
              }
          } catch (Exception e) {
              storage.rollbackTx();
              throw ExceptionFactory.actionException(Messages.i18n.format("UnregisterError"), e); //$NON-NLS-1$
          }
  
          versionBean.setStatus(ClientStatus.Retired);
          versionBean.setRetiredOn(new Date());
  
          try {
              storage.beginTx();
              storage.updateClientVersion(versionBean);
              storage.createAuditEntry(AuditUtils.clientUnregistered(versionBean, securityContext));
              storage.commitTx();
          } catch (Exception e) {
              storage.rollbackTx();
              throw ExceptionFactory.actionException(Messages.i18n.format("UnregisterError"), e); //$NON-NLS-1$
          }
  
          log.debug(String.format("Successfully registered Client %s on specified gateways: %s", //$NON-NLS-1$
                  versionBean.getClient().getName(), versionBean.getClient()));
      }