@Override protected boolean isDeleteAllowed(ServiceContext context, Entity entity) { Notification notification = (Notification) entity; Notification.State state = notification.getState(); return !(state.equals(Notification.State.CREATED) || state.equals(Notification.State.STARTED) || state.equals(Notification.State.SCHEDULED)); }
@Override public ServiceResults postCollection(ServiceContext context) throws Exception { logger.info("NotificationService: start request."); Timer.Context timer = postTimer.time(); postMeter.mark(); try { validate(null, context.getPayload()); Notification.PathTokens pathTokens = getPathTokens(context.getRequest().getOriginalParameters()); context.getProperties().put("state", Notification.State.CREATED); context.getProperties().put("pathQuery", pathTokens); context.setOwner(sm.getApplication()); ServiceResults results = super.postCollection(context); Notification notification = (Notification) results.getEntity(); // update Notification properties if (notification.getStarted() == null || notification.getStarted() == 0) { long now = System.currentTimeMillis(); notification.setStarted(System.currentTimeMillis()); Map<String, Object> properties = new HashMap<String, Object>(2); properties.put("started", notification.getStarted()); properties.put("state", notification.getState()); notification.addProperties(properties); logger.info( "ApplicationQueueMessage: notification {} properties updated in duration {} ms", notification.getUuid(), System.currentTimeMillis() - now); } long now = System.currentTimeMillis(); notificationQueueManager.queueNotification(notification, null); logger.info( "NotificationService: notification {} post queue duration {} ms ", notification.getUuid(), System.currentTimeMillis() - now); // future: somehow return 202? return results; } catch (Exception e) { logger.error("serialization failed", e); throw e; } finally { timer.stop(); } }
@Override public Entity updateEntity(ServiceRequest request, EntityRef ref, ServicePayload payload) throws Exception { validate(ref, payload); Notification notification = em.get(ref, Notification.class); if ("restart".equals(payload.getProperty("restart"))) { // for emergency // use only payload.getProperties().clear(); payload.setProperty("restart", ""); payload.setProperty("errorMessage", ""); payload.setProperty("deliver", System.currentTimeMillis() + gracePeriod); // once finished, immutable } else if (notification.getFinished() != null) { throw new ForbiddenServiceOperationException(request, "Notification immutable once sent."); // once started, only cancel is allowed } else if (notification.getStarted() != null) { if (payload.getProperty("canceled") != Boolean.TRUE) { throw new ForbiddenServiceOperationException( request, "Notification has started. You may only set canceled."); } payload.getProperties().clear(); payload.setProperty("canceled", Boolean.TRUE); } Entity response = super.updateEntity(request, ref, payload); Long deliver = (Long) payload.getProperty("deliver"); if (deliver != null) { if (!deliver.equals(notification.getDeliver())) { notificationQueueManager.queueNotification((Notification) response, null); } } return response; }
@Override public void sendNotification( String providerId, Object payload, Notification notification, TaskTracker tracker) throws Exception { try { List<TranslatedNotification> translatedNotifications = (List<TranslatedNotification>) payload; for (TranslatedNotification translatedNotification : translatedNotifications) { // set the optional TTL value used when pushing notifications WnsNotificationRequestOptional opt = new WnsNotificationRequestOptional(); opt.ttl = String.valueOf(notification.getExpireTTLSeconds()); switch (translatedNotification.getType()) { case "toast": WnsToast toast = new WnsToastBuilder() .bindingTemplateToastText01(translatedNotification.getMessage().toString()) .build(); service.pushToast(providerId, opt, toast); break; case "badge": WnsBadge badge; if (translatedNotification.getMessage() instanceof Integer) { badge = new WnsBadgeBuilder() .value((Integer) translatedNotification.getMessage()) .build(); } else { badge = new WnsBadgeBuilder() .value(translatedNotification.getMessage().toString()) .build(); } service.pushBadge(providerId, opt, badge); break; case "raw": Object message = translatedNotification.getMessage(); if (message instanceof String) { WnsRaw raw = new WnsRawBuilder().stream(((String) message).getBytes()).build(); // set additional optional parameter for raw notifications opt.cachePolicy = "cache"; opt.requestForStatus = "true"; WnsNotificationResponse response = service.pushRaw(providerId, opt, raw); if (!response.notificationStatus.equals( "received")) { // https://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx#pncodes_x_wns_notification throw new Exception( String.format( "Notification failed status:%s, devicesStatus:%s, description:%s, debug flag:%s", response.notificationStatus, response.deviceConnectionStatus, response.errorDescription, response.debugTrace)); } } else { throw new IllegalArgumentException( "You must send a string in the raw body. instead got this: " + message.getClass().getName()); } break; default: throw new IllegalArgumentException( translatedNotification.getType() + " does not match a valid notification type (toast,badge)."); } } tracker.completed(); } catch (Exception e) { tracker.failed(0, e.toString()); LOG.error("Failed to send notification", e); } }