public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {

    int tenantID = PublisherUtil.getTenantId(messageContext);

    Map<Integer, EventingConfigData> tenantSpecificEventConfig =
        TenantEventConfigData.getTenantSpecificEventingConfigData();
    EventingConfigData eventingConfigData = tenantSpecificEventConfig.get(tenantID);

    if (eventingConfigData != null && eventingConfigData.isMessageTracingEnable()) {

      if (log.isDebugEnabled()) {
        log.debug("Message tracing enabled.");
      }

      AxisService service = messageContext.getAxisService();

      // Temporary fix for track API manager calls
      if (service == null
          || (SystemFilter.isFilteredOutService(service.getAxisServiceGroup())
              && !AgentUtil.allowedServices(service.getName()))
          || service.isClientSide()) {
        return InvocationResponse.CONTINUE;
      } else {

        String activityUUID = HandlerUtils.getUniqueId();
        Object transportHeaders = messageContext.getProperty(MessageContext.TRANSPORT_HEADERS);

        if (transportHeaders != null) {
          String aid = (String) ((Map) transportHeaders).get(MessageTracerConstants.ACTIVITY_ID);
          if (aid != null) {
            if (aid.equals(MessageTracerConstants.EMPTY_STRING)) {
              ((Map) messageContext.getProperty(MessageContext.TRANSPORT_HEADERS))
                  .put(MessageTracerConstants.ACTIVITY_ID, activityUUID);
              if (log.isDebugEnabled()) {
                log.debug("Propagated AID was empty, IN generating new AID");
              }
            } else {
              activityUUID = aid;
              if (log.isDebugEnabled()) {
                log.debug("IN using propagated AID");
              }
            }
          } else {
            ((Map) messageContext.getProperty(MessageContext.TRANSPORT_HEADERS))
                .put(MessageTracerConstants.ACTIVITY_ID, activityUUID);
            if (log.isDebugEnabled()) {
              log.debug("Propagated AID was null, IN generating new AID");
            }
          }
        } else {
          Map<String, String> headers = new TreeMap<String, String>();
          headers.put(MessageTracerConstants.ACTIVITY_ID, activityUUID);
          messageContext.setProperty(MessageContext.TRANSPORT_HEADERS, headers);
          if (log.isDebugEnabled()) {
            log.debug("Transport headers absent, IN generating new AID");
          }
        }

        messageContext.setProperty(MessageTracerConstants.TENANT_ID, tenantID);

        TracingInfo tracingInfo = new TracingInfo();
        tracingInfo.setActivityId(activityUUID);
        tracingInfo.setServer(AgentUtil.getServerName());
        tracingInfo.setMessageDirection(BAMDataPublisherConstants.IN_DIRECTION);
        tracingInfo.setHost(PublisherUtil.getHostAddress());
        tracingInfo.setServiceName(messageContext.getAxisService().getName());
        tracingInfo.setOperationName(messageContext.getAxisOperation().getName().getLocalPart());
        MessageContext inMessageContext =
            messageContext.getOperationContext().getMessageContext(WSDL2Constants.MESSAGE_LABEL_IN);
        if (inMessageContext != null) {
          Object requestProperty =
              inMessageContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
          AgentUtil.extractInfoFromHttpHeaders(tracingInfo, requestProperty);
        }

        try {
          if (eventingConfigData.isDumpBodyEnable()) {
            try {
              Class cls =
                  Class.forName(
                      MessageTracerConstants
                          .ORG_APACHE_SYNAPSE_TRANSPORT_PASSTHRU_UTIL_RELAY_UTILS_CLASS_NAME);
              Class[] paramClasses = new Class[] {MessageContext.class, Boolean.TYPE};
              Method method =
                  cls.getMethod(MessageTracerConstants.BUILD_MESSAGE_METHOD_NAME, paramClasses);
              method.invoke(null, messageContext, false);
            } catch (ClassNotFoundException ignore) {
              // ignore
            } catch (Exception e) {
              throw new AxisFault("Error in building input message: " + e.getMessage(), e);
            }
            SOAPEnvelope soapEnvelope = messageContext.getEnvelope();
            SOAPBody body = soapEnvelope.getBody();
            if (body != null) {
              tracingInfo.setPayload(body.toString());
            }

            SOAPHeader header = soapEnvelope.getHeader();
            if (header != null) {
              tracingInfo.setHeader(header.toString());
            }
          }

          tracingInfo.setTimestamp(System.currentTimeMillis());

          if (MessageContext.IN_FLOW == messageContext.getFLOW()) {
            tracingInfo.setStatus(MessageTracerConstants.STATUS_SUCCESS);
          } else if (MessageContext.IN_FAULT_FLOW == messageContext.getFLOW()) {
            tracingInfo.setStatus(MessageTracerConstants.STATUS_FAULT);
          }

          publisher.publish(tenantID, tracingInfo);
        } catch (OMException e) {
          log.error("Unable to get SOAP details " + e.getMessage(), e);
        }
      }
    }
    return InvocationResponse.CONTINUE;
  }
  public void execute(ConfigurationContext configContext) throws ClusteringFault {
    AxisConfiguration axisConfig = configContext.getAxisConfiguration();

    // Run this code only if this node is not already initialized
    if (configContext.getPropertyNonReplicable(ClusteringConstants.RECD_CONFIG_INIT_MSG) == null) {
      log.info("Received configuration initialization message");
      configContext.setNonReplicableProperty(ClusteringConstants.RECD_CONFIG_INIT_MSG, "true");
      if (serviceGroups != null) {

        // Load all the service groups that are sent by the neighbour
        for (int i = 0; i < serviceGroups.length; i++) {
          String serviceGroup = serviceGroups[i];
          if (axisConfig.getServiceGroup(serviceGroup) == null) {
            // Load the service group
            try {
              ClusteringUtils.loadServiceGroup(
                  serviceGroup,
                  configContext,
                  System.getProperty(
                      "axis2.work.dir")); // TODO: Introduce a constant. work dir is a temp dir.
            } catch (FileNotFoundException ignored) {
            } catch (Exception e) {
              throw new ClusteringFault(e);
            }
          }
        }

        // TODO: We support only AAR files for now

        // Unload all service groups which were not sent by the neighbour,
        // but have been currently loaded
        for (Iterator iter = axisConfig.getServiceGroups(); iter.hasNext(); ) {
          AxisServiceGroup serviceGroup = (AxisServiceGroup) iter.next();
          boolean foundServiceGroup = false;
          for (int i = 0; i < serviceGroups.length; i++) {
            String serviceGroupName = serviceGroups[i];
            if (serviceGroup.getServiceGroupName().equals(serviceGroupName)) {
              foundServiceGroup = true;
              break;
            }
          }
          if (!foundServiceGroup) {
            boolean mustUnloadServiceGroup = true;
            // Verify that this service was not loaded from within a module
            // If so, we must not unload such a service
            for (Iterator serviceIter = serviceGroup.getServices(); serviceIter.hasNext(); ) {
              AxisService service = (AxisService) serviceIter.next();
              if (service.isClientSide()
                  || service.getParameter(AxisModule.MODULE_SERVICE)
                      != null) { // Do not unload service groups containing client side services or
                                 // ones deployed from within modules
                mustUnloadServiceGroup = false;
                break;
              }
            }
            if (mustUnloadServiceGroup) {
              try {
                axisConfig.removeServiceGroup(serviceGroup.getServiceGroupName());
              } catch (Exception e) {
                throw new ClusteringFault(e);
              }
            }
          }
        }
      }
    }
  }
  @Override
  public Handler.InvocationResponse invoke(MessageContext messageContext) throws AxisFault {

    SystemStatisticsUtil systemStatisticsUtil;
    SystemStatistics systemStatistics;

    try {
      int tenantID = PublisherUtil.getTenantId(messageContext);
      Map<Integer, EventConfigNStreamDef> tenantSpecificEventConfig =
          TenantEventConfigData.getTenantSpecificEventingConfigData();
      EventConfigNStreamDef eventingConfigData = tenantSpecificEventConfig.get(tenantID);

      // Check service stats enable -- if true -- go
      if (eventingConfigData != null && eventingConfigData.isServiceStatsEnable()) {

        systemStatisticsUtil = StatisticsServiceComponent.getSystemStatisticsUtil();
        systemStatistics = systemStatisticsUtil.getSystemStatistics(messageContext);
        AxisOperation axisOperation = messageContext.getAxisOperation();

        AxisService axisService = messageContext.getAxisService();
        if (axisService == null
            || SystemFilter.isFilteredOutService(axisService.getAxisServiceGroup())
            || axisService.isClientSide()) {
          return Handler.InvocationResponse.CONTINUE;
        }

        MessageContext inMessageContext = MessageContext.getCurrentMessageContext();

        // If already set in the activity handlers get it or create new publish data
        /*
                        PublishData publishData = (PublishData) messageContext.getProperty(
                                BAMDataPublisherConstants.PUBLISH_DATA);

                        EventData eventData;
                        if (publishData != null) {
                            eventData = publishData.getEventData();
                        } else {
                            publishData = new PublishData();
                            eventData = new EventData();
                            Date date = new Date();
                            Timestamp timestamp = new Timestamp(date.getTime());
                            eventData.setTimestamp(timestamp);
                            if (axisOperation != null) {
                                eventData.setOperationName(axisOperation.getName().getLocalPart());
                            } else {
                                eventData.setOperationName(null);
                            }

                            if (axisService != null) {
                                eventData.setServiceName(messageContext.getAxisService().getName());
                            } else {
                                eventData.setServiceName(null);
                            }

                            //This is a hack for setting message id when sending request to a non-existing operation.
                            if (eventingConfigData.isMsgDumpingEnable() && axisService != null &&
                                axisOperation == null) {
                                eventData.setOutMessageId(new ActivityOutHandler().getUniqueId());
                            }

                        }
        */

        PublishData publishData = new PublishData();
        EventData eventData = new EventData();
        /*                Date date = new Date();
        Timestamp timestamp = new Timestamp(date.getTime());
        eventData.setTimestamp(timestamp);*/
        if (axisOperation != null) {
          eventData.setOperationName(axisOperation.getName().getLocalPart());
        } else {
          eventData.setOperationName(null);
        }

        if (axisService != null) {
          eventData.setServiceName(messageContext.getAxisService().getName());
        } else {
          eventData.setServiceName(null);
        }

        // This is a hack for setting message id when sending request to a non-existing operation.
        /*                if (eventingConfigData.isMsgDumpingEnable() && axisService != null &&
            axisOperation == null) {
            eventData.setOutMessageId(new ActivityOutHandler().getUniqueId());
        }*/

        // Skip resetting same info if already set by activity in/out handlers
        /*                if (!eventingConfigData.isMsgDumpingEnable()) {

            Timestamp timestamp = null;
            if (inMessageContext != null) {
                timestamp = new Timestamp(Long.parseLong(inMessageContext.getProperty(
                        StatisticsConstants.REQUEST_RECEIVED_TIME).toString()));
                Object requestProperty = inMessageContext.getProperty(
                        HTTPConstants.MC_HTTP_SERVLETREQUEST);
                ServiceAgentUtil.extractInfoFromHttpHeaders(eventData, requestProperty);
            } else {
                Date date = new Date();
                timestamp = new Timestamp(date.getTime());
            }

            eventData.setTimestamp(timestamp);

        }*/

        Timestamp timestamp = null;
        if (inMessageContext != null) {
          timestamp =
              new Timestamp(
                  Long.parseLong(
                      inMessageContext
                          .getProperty(StatisticsConstants.REQUEST_RECEIVED_TIME)
                          .toString()));
          Object requestProperty =
              inMessageContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
          ServiceAgentUtil.extractInfoFromHttpHeaders(eventData, requestProperty);
        } else {
          Date date = new Date();
          timestamp = new Timestamp(date.getTime());
        }

        eventData.setTimestamp(timestamp);

        eventData.setSystemStatistics(systemStatistics);

        publishData.setEventData(eventData);

        // Skip if bam server info already set at activity handlers
        if (!eventingConfigData.isMsgDumpingEnable()) {
          BAMServerInfo bamServerInfo = ServiceAgentUtil.addBAMServerInfo(eventingConfigData);
          publishData.setBamServerInfo(bamServerInfo);
        }

        Event event = ServiceAgentUtil.makeEventList(publishData, eventingConfigData);
        EventPublisher publisher = new EventPublisher();
        publisher.publish(event, eventingConfigData);
      }
    } catch (Throwable ignore) {
      log.error(
          "Error at SystemStatisticsOutHandler. "
              + "But continuing message processing for message id: "
              + messageContext.getMessageID(),
          ignore);
    }

    return Handler.InvocationResponse.CONTINUE;
  }