use of org.openremote.model.notification.NotificationSendResult in project openremote by openremote.
the class NotificationService method configure.
@Override
public void configure() throws Exception {
from(NOTIFICATION_QUEUE).routeId("NotificationQueueProcessor").doTry().process(exchange -> {
Notification notification = exchange.getIn().getBody(Notification.class);
if (notification == null) {
throw new NotificationProcessingException(MISSING_NOTIFICATION, "Notification must be set");
}
LOG.finest("Processing: " + notification.getName());
if (notification.getMessage() == null) {
throw new NotificationProcessingException(MISSING_MESSAGE, "Notification message must be set");
}
Notification.Source source = exchange.getIn().getHeader(HEADER_SOURCE, () -> null, Notification.Source.class);
if (source == null) {
throw new NotificationProcessingException(MISSING_SOURCE);
}
// Validate handler and message
NotificationHandler handler = notificationHandlerMap.get(notification.getMessage().getType());
if (handler == null) {
throw new NotificationProcessingException(UNSUPPORTED_MESSAGE_TYPE, "No handler for message type: " + notification.getMessage().getType());
}
if (!handler.isValid()) {
throw new NotificationProcessingException(NOTIFICATION_HANDLER_CONFIG_ERROR, "Handler is not valid: " + handler.getTypeName());
}
if (!handler.isMessageValid(notification.getMessage())) {
throw new NotificationProcessingException(INVALID_MESSAGE);
}
// Validate access and map targets to handler compatible targets
String realm = null;
String userId = null;
String assetId = null;
AtomicReference<String> sourceId = new AtomicReference<>("");
boolean isSuperUser = false;
boolean isRestrictedUser = false;
switch(source) {
case INTERNAL:
isSuperUser = true;
break;
case CLIENT:
AuthContext authContext = exchange.getIn().getHeader(Constants.AUTH_CONTEXT, AuthContext.class);
if (authContext == null) {
// Anonymous clients cannot send notifications
throw new NotificationProcessingException(INSUFFICIENT_ACCESS);
}
realm = authContext.getAuthenticatedRealm();
userId = authContext.getUserId();
sourceId.set(userId);
isSuperUser = authContext.isSuperUser();
isRestrictedUser = identityService.getIdentityProvider().isRestrictedUser(authContext);
break;
case GLOBAL_RULESET:
isSuperUser = true;
break;
case TENANT_RULESET:
realm = exchange.getIn().getHeader(Notification.HEADER_SOURCE_ID, String.class);
sourceId.set(realm);
break;
case ASSET_RULESET:
assetId = exchange.getIn().getHeader(Notification.HEADER_SOURCE_ID, String.class);
sourceId.set(assetId);
Asset<?> asset = assetStorageService.find(assetId, false);
realm = asset.getRealm();
break;
}
LOG.info("Sending " + notification.getMessage().getType() + " notification '" + notification.getName() + "': '" + source + ":" + sourceId.get() + "' -> " + notification.getTargets());
// Check access permissions
checkAccess(source, sourceId.get(), notification.getTargets(), realm, userId, isSuperUser, isRestrictedUser, assetId);
// Get the list of notification targets
List<Notification.Target> mappedTargetsList = handler.getTargets(source, sourceId.get(), notification.getTargets(), notification.getMessage());
if (mappedTargetsList == null || mappedTargetsList.isEmpty()) {
throw new NotificationProcessingException(MISSING_TARGETS, "Notification targets must be set");
}
// Filter targets based on repeat frequency
if (!TextUtil.isNullOrEmpty(notification.getName()) && (!TextUtil.isNullOrEmpty(notification.getRepeatInterval()) || notification.getRepeatFrequency() != null)) {
mappedTargetsList = mappedTargetsList.stream().filter(target -> okToSendNotification(source, sourceId.get(), target, notification)).collect(Collectors.toList());
}
// Send message to each applicable target
AtomicBoolean success = new AtomicBoolean(true);
mappedTargetsList.forEach(target -> {
boolean targetSuccess = persistenceService.doReturningTransaction(em -> {
// commit the notification first to get the ID
SentNotification sentNotification = new SentNotification().setName(notification.getName()).setType(notification.getMessage().getType()).setSource(source).setSourceId(sourceId.get()).setTarget(target.getType()).setTargetId(target.getId()).setMessage(notification.getMessage()).setSentOn(Date.from(timerService.getNow()));
sentNotification = em.merge(sentNotification);
long id = sentNotification.getId();
try {
NotificationSendResult result = handler.sendMessage(id, source, sourceId.get(), target, notification.getMessage());
if (result.isSuccess()) {
LOG.info("Notification sent '" + id + "': " + target);
} else {
LOG.warning("Notification failed '" + id + "': " + target + ", reason=" + result.getMessage());
sentNotification.setError(TextUtil.isNullOrEmpty(result.getMessage()) ? "Unknown error" : result.getMessage());
}
// Merge the sent notification again with the message included just in case the handler modified the message
sentNotification.setMessage(notification.getMessage());
em.merge(sentNotification);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Notification handler threw an exception whilst sending notification '" + id + "'", e);
sentNotification.setError(TextUtil.isNullOrEmpty(e.getMessage()) ? "Unknown error" : e.getMessage());
em.merge(sentNotification);
}
return sentNotification.getError() == null;
});
if (!targetSuccess) {
success.set(false);
}
});
exchange.getOut().setBody(success.get());
}).endDoTry().doCatch(NotificationProcessingException.class).process(handleNotificationProcessingException(LOG));
}
Aggregations