Search in sources :

Example 1 with NotificationValidationContext

use of org.apache.nifi.bootstrap.notification.NotificationValidationContext in project nifi by apache.

the class NotificationServiceManager method notify.

public void notify(final NotificationType type, final String subject, final String message) {
    final List<ConfiguredNotificationService> configs = servicesByNotificationType.get(type);
    if (configs == null || configs.isEmpty()) {
        return;
    }
    for (final ConfiguredNotificationService config : configs) {
        final NotificationService service = config.getService();
        final AtomicInteger attemptCount = new AtomicInteger(0);
        notificationExecutor.submit(new Runnable() {

            @Override
            public void run() {
                // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications
                final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config), variableRegistry);
                final Collection<ValidationResult> validationResults = service.validate(validationContext);
                final List<String> invalidReasons = new ArrayList<>();
                for (final ValidationResult result : validationResults) {
                    if (!result.isValid()) {
                        invalidReasons.add(result.toString());
                    }
                }
                // If the service is valid, attempt to send the notification
                boolean failure = false;
                if (invalidReasons.isEmpty()) {
                    final NotificationContext context = buildNotificationContext(config);
                    try {
                        service.notify(context, type, subject, message);
                        logger.info("Successfully sent notification of type {} to {}", type, service);
                    } catch (final Throwable t) {
                        // keep running even if a Throwable is caught because we need to ensure that we are able to restart NiFi
                        logger.error("Failed to send notification of type {} to {} with Subject {} due to {}. Will ", type, service == null ? "Unknown Notification Service" : service.toString(), subject, t.toString());
                        logger.error("", t);
                        failure = true;
                    }
                } else {
                    logger.warn("Notification Service {} is not valid for the following reasons: {}", service, invalidReasons);
                    failure = true;
                }
                final int attempts = attemptCount.incrementAndGet();
                if (failure) {
                    if (attempts < maxAttempts) {
                        logger.info("After failing to send notification to {} {} times, will attempt again in 1 minute", service, attempts);
                        notificationExecutor.schedule(this, 1, TimeUnit.MINUTES);
                    } else {
                        logger.info("After failing to send notification of type {} to {} {} times, will no longer attempt to send notification", type, service, attempts);
                    }
                }
            }
        });
        if (NotificationType.NIFI_STOPPED.equals(type)) {
            // we don't want to return before the notifier has had a chance to perform its task.
            while (attemptCount.get() == 0) {
                try {
                    Thread.sleep(1000L);
                } catch (final InterruptedException ie) {
                }
            }
        }
    }
}
Also used : NotificationValidationContext(org.apache.nifi.bootstrap.notification.NotificationValidationContext) NotificationService(org.apache.nifi.bootstrap.notification.NotificationService) ValidationResult(org.apache.nifi.components.ValidationResult) NotificationValidationContext(org.apache.nifi.bootstrap.notification.NotificationValidationContext) ValidationContext(org.apache.nifi.components.ValidationContext) NotificationContext(org.apache.nifi.bootstrap.notification.NotificationContext) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Collection(java.util.Collection) ArrayList(java.util.ArrayList) NodeList(org.w3c.dom.NodeList) List(java.util.List)

Example 2 with NotificationValidationContext

use of org.apache.nifi.bootstrap.notification.NotificationValidationContext in project nifi by apache.

the class NotificationServiceManager method loadNotificationServices.

/**
 * Loads the Notification Services from the given XML configuration file.
 *
 * File is expected to have the following format:
 *
 * <pre>
 * &lt;services&gt;
 *   &lt;service&gt;
 *     &lt;id&gt;service-identifier&lt;/id&gt;
 *     &lt;class&gt;org.apache.nifi.MyNotificationService&lt;/class&gt;
 *     &lt;property name="My First Property"&gt;Property Value&lt;/property&gt;
 *   &lt;/service&gt;
 *   &lt;service&gt;
 *     &lt;id&gt;other-service&lt;/id&gt;
 *     &lt;class&gt;org.apache.nifi.MyOtherNotificationService&lt;/class&gt;
 *     &lt;property name="Another Property"&gt;Property Value 2&lt;/property&gt;
 *   &lt;/service&gt;
 *   ...
 *   &lt;service&gt;
 *     &lt;id&gt;service-identifier-2&lt;/id&gt;
 *     &lt;class&gt;org.apache.nifi.FinalNotificationService&lt;/class&gt;
 *     &lt;property name="Yet Another Property"&gt;3rd Prop Value&lt;/property&gt;
 *   &lt;/service&gt;
 * &lt;/services&gt;
 * </pre>
 *
 * Note that as long as the file can be interpreted properly, a misconfigured service will result in a warning
 * or error being logged and the service will be unavailable but will not prevent the rest of the services from loading.
 *
 * @param servicesFile the XML file to load services from.
 * @throws IOException if unable to read from the given file
 * @throws ParserConfigurationException if unable to parse the given file as XML properly
 * @throws SAXException if unable to parse the given file properly
 */
public void loadNotificationServices(final File servicesFile) throws IOException, ParserConfigurationException, SAXException {
    final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    docBuilderFactory.setNamespaceAware(false);
    final DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    final Map<String, ConfiguredNotificationService> serviceMap = new HashMap<>();
    try (final InputStream fis = new FileInputStream(servicesFile);
        final InputStream in = new BufferedInputStream(fis)) {
        final Document doc = docBuilder.parse(new InputSource(in));
        final List<Element> serviceElements = getChildElementsByTagName(doc.getDocumentElement(), "service");
        logger.debug("Found {} service elements", serviceElements.size());
        for (final Element serviceElement : serviceElements) {
            final ConfiguredNotificationService config = createService(serviceElement);
            final NotificationService service = config.getService();
            if (service == null) {
                // reason will have already been logged, so just move on.
                continue;
            }
            final String id = service.getIdentifier();
            if (serviceMap.containsKey(id)) {
                logger.error("Found two different Notification Services configured with the same ID: '{}'. Loaded the first service.", id);
                continue;
            }
            // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications
            final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config), variableRegistry);
            final Collection<ValidationResult> validationResults = service.validate(validationContext);
            final List<String> invalidReasons = new ArrayList<>();
            for (final ValidationResult result : validationResults) {
                if (!result.isValid()) {
                    invalidReasons.add(result.toString());
                }
            }
            if (!invalidReasons.isEmpty()) {
                logger.warn("Configured Notification Service {} is not valid for the following reasons: {}", service, invalidReasons);
            }
            serviceMap.put(id, config);
        }
    }
    logger.info("Successfully loaded the following {} services: {}", serviceMap.size(), serviceMap.keySet());
    servicesById.clear();
    servicesById.putAll(serviceMap);
}
Also used : InputSource(org.xml.sax.InputSource) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) HashMap(java.util.HashMap) NotificationValidationContext(org.apache.nifi.bootstrap.notification.NotificationValidationContext) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) Element(org.w3c.dom.Element) ArrayList(java.util.ArrayList) NotificationService(org.apache.nifi.bootstrap.notification.NotificationService) Document(org.w3c.dom.Document) ValidationResult(org.apache.nifi.components.ValidationResult) FileInputStream(java.io.FileInputStream) NotificationValidationContext(org.apache.nifi.bootstrap.notification.NotificationValidationContext) ValidationContext(org.apache.nifi.components.ValidationContext) DocumentBuilder(javax.xml.parsers.DocumentBuilder) BufferedInputStream(java.io.BufferedInputStream)

Aggregations

ArrayList (java.util.ArrayList)2 NotificationService (org.apache.nifi.bootstrap.notification.NotificationService)2 NotificationValidationContext (org.apache.nifi.bootstrap.notification.NotificationValidationContext)2 ValidationContext (org.apache.nifi.components.ValidationContext)2 ValidationResult (org.apache.nifi.components.ValidationResult)2 BufferedInputStream (java.io.BufferedInputStream)1 FileInputStream (java.io.FileInputStream)1 InputStream (java.io.InputStream)1 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 List (java.util.List)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 DocumentBuilder (javax.xml.parsers.DocumentBuilder)1 DocumentBuilderFactory (javax.xml.parsers.DocumentBuilderFactory)1 NotificationContext (org.apache.nifi.bootstrap.notification.NotificationContext)1 Document (org.w3c.dom.Document)1 Element (org.w3c.dom.Element)1 NodeList (org.w3c.dom.NodeList)1 InputSource (org.xml.sax.InputSource)1