public void addGeneratedSAMLTokenToExchange(Exchange exchange) throws Exception {
    Element assertion =
        samlAssertionBuilder.createSamlAssertionElement(
            issuerString,
            inResponseTo,
            recipient,
            audienceRestriction,
            authenticationMethod,
            defaultCanonicalizationAlgorithm,
            defaultRSASignatureAlgorithm,
            customAttributes);

    // Set the token header so that CXF can retrieve this on the outbound call
    String tokenID = exchange.getExchangeId();
    exchange.getIn().setHeader("tokenID", tokenID);

    ojbSamlMap.putToken(exchange.getExchangeId(), assertion);
  }
  @Override
  public String invokeIncidentSearchRequest(
      IncidentSearchRequest incidentSearchRequest, String federatedQueryID, Element samlToken)
      throws Exception {

    if (allowQueriesWithoutSAMLToken) {
      if (samlToken == null) {
        // Add SAML token to request call
        samlToken =
            SAMLTokenUtils.createStaticAssertionAsElement(
                "https://idp.ojbc-local.org:9443/idp/shibboleth",
                SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS,
                SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1,
                true,
                true,
                null);
      }
    }

    if (samlToken == null) {
      throw new Exception("No SAML token provided. Unable to perform query.");
    }

    // POJO to XML Request
    // When multiple operations are supported, we will call the appropriate POJO to XML Method
    Document incidentRequestPayload =
        RequestMessageBuilderUtilities.createIncidentSearchRequest(
            incidentSearchRequest, cityTownCodelistNamespace, cityTownCodelistElementName);

    incidentRequestPayload.normalizeDocument();

    log.debug(OJBUtils.getStringFromDocument(incidentRequestPayload));

    // Create exchange
    Exchange senderExchange = new DefaultExchange(camelContext, ExchangePattern.InOnly);

    // Set exchange body to XML Request message
    senderExchange.getIn().setBody(incidentRequestPayload);

    // Set reply to and WS-Addressing message ID
    senderExchange.getIn().setHeader("federatedQueryRequestGUID", federatedQueryID);
    senderExchange.getIn().setHeader("WSAddressingReplyTo", this.getReplyToAddress());

    // Set the token header so that CXF can retrieve this on the outbound call
    String tokenID = senderExchange.getExchangeId();
    senderExchange.getIn().setHeader("tokenID", tokenID);
    OJBSamlMap.putToken(tokenID, samlToken);

    incidentSearchMessageProcessor.sendResponseMessage(camelContext, senderExchange);

    // Put message ID and "noResponse" place holder.
    putRequestInMap(federatedQueryID);

    String response = pollMap(federatedQueryID);

    if (response.length() > 500) {
      log.debug("Here is the response (truncated): " + response.substring(0, 500));
    } else {
      log.debug("Here is the response: " + response);
    }

    // This is a defensive check in case the polling completes and the service has not yet returned
    // a response
    // In this case we send back an empty search result
    if (response.equals(NO_RESPONSE)) {
      log.debug("Endpoints timed out and no response recieved at web app, create error response");
      response = MergeNotificationErrorProcessor.returnMergeNotificationErrorMessage();
    }

    // return response here
    return response;
  }