/** * Adds a property for the device identifier. * <p> * The property will only be added if the AMQP message contains * a non-{@code null} device identifier. * * @param msg The AMQP message to retrieve the value from. * @return This message for chaining. */ public EventBusMessage setDeviceId(final Message msg) { setDeviceId(MessageHelper.getDeviceId(msg)); return this; }
/** * Adds a property for the device identifier. * <p> * The property will only be added if the AMQP message contains * a non-{@code null} device identifier. * * @param msg The AMQP message to retrieve the value from. * @return This message for chaining. */ public EventBusMessage setDeviceId(final Message msg) { setDeviceId(MessageHelper.getDeviceId(msg)); return this; }
private void printMessage(final String tenantId, final Message msg, final String messageType) { if (LOG.isDebugEnabled()) { final String content = MessageHelper.getPayloadAsString(msg); final String deviceId = MessageHelper.getDeviceId(msg); final StringBuilder sb = new StringBuilder("received "). append(messageType). append(" [tenant: ").append(tenantId). append(", device: ").append(deviceId). append(", content-type: ").append(msg.getContentType()). append(" ]: [").append(content).append("]."); LOG.debug(sb.toString()); } }
private void handleMessage(final String endpoint, final Message msg) { final String deviceId = MessageHelper.getDeviceId(msg); final Buffer payload = MessageHelper.getPayload(msg); LOG.info("received {} message [device: {}, content-type: {}]: {}", endpoint, deviceId, msg.getContentType(), payload); if (msg.getApplicationProperties() != null) { LOG.info("... with application properties: {}", msg.getApplicationProperties().getValue()); } }
/** * Checks if an AMQP message contains a valid device identifier. * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the following conditions are met: * <ul> * <li>The message contains an application property {@link MessageHelper#APP_PROPERTY_DEVICE_ID}.</li> * <li>If the link target contains a resource ID, it matches the ID from the property.</li> * </ul> */ protected static final boolean hasValidDeviceId(final ResourceIdentifier linkTarget, final Message msg) { final String deviceIdProperty = MessageHelper.getDeviceId(msg); if (deviceIdProperty == null) { LOG.trace("message [{}] contains no {} application property", msg.getMessageId(), MessageHelper.APP_PROPERTY_DEVICE_ID); return false; } else if (linkTarget.getResourceId() != null && !deviceIdProperty.equals(linkTarget.getResourceId())) { LOG.trace("message's {} property contains invalid device ID [expected: {}, but was: {}]", MessageHelper.APP_PROPERTY_DEVICE_ID, linkTarget.getResourceId(), deviceIdProperty); return false; } else { return true; } }
/** * Checks if an AMQP message contains a valid device identifier. * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the following conditions are met: * <ul> * <li>The message contains an application property {@link MessageHelper#APP_PROPERTY_DEVICE_ID}.</li> * <li>If the link target contains a resource ID, it matches the ID from the property.</li> * </ul> */ protected static final boolean hasValidDeviceId(final ResourceIdentifier linkTarget, final Message msg) { final String deviceIdProperty = MessageHelper.getDeviceId(msg); if (deviceIdProperty == null) { LOG.trace("message [{}] contains no {} application property", msg.getMessageId(), MessageHelper.APP_PROPERTY_DEVICE_ID); return false; } else if (linkTarget.getResourceId() != null && !deviceIdProperty.equals(linkTarget.getResourceId())) { LOG.trace("message's {} property contains invalid device ID [expected: {}, but was: {}]", MessageHelper.APP_PROPERTY_DEVICE_ID, linkTarget.getResourceId(), deviceIdProperty); return false; } else { return true; } }
/** * Provide an instance of {@link TimeUntilDisconnectNotification} if a message indicates that the device sending it * is currently connected to a protocol adapter. * <p> * If this is not the case, the returned {@link Optional} will be empty. * * @param msg Message that is evaluated. * @return Optional containing an instance of the class {@link TimeUntilDisconnectNotification} if the device is considered * being ready to receive an upstream message or is empty otherwise. * @throws NullPointerException If msg is {@code null}. */ public static Optional<TimeUntilDisconnectNotification> fromMessage(final Message msg) { final Integer ttd = MessageHelper.getTimeUntilDisconnect(msg); if (ttd == null) { return Optional.empty(); } else if (ttd == 0 || MessageHelper.isDeviceCurrentlyConnected(msg)) { final String tenantId = MessageHelper.getTenantIdAnnotation(msg); final String deviceId = MessageHelper.getDeviceId(msg); if (tenantId != null && deviceId != null) { final Instant creationTime = Instant.ofEpochMilli(msg.getCreationTime()); final TimeUntilDisconnectNotification notification = new TimeUntilDisconnectNotification(tenantId, deviceId, ttd, getReadyUntilInstantFromTtd(ttd, creationTime), creationTime); return Optional.of(notification); } } return Optional.empty(); }
/** * Provide an instance of {@link TimeUntilDisconnectNotification} if a message indicates that the device sending it * is currently connected to a protocol adapter. * <p> * If this is not the case, the returned {@link Optional} will be empty. * * @param msg Message that is evaluated. * @return Optional containing an instance of the class {@link TimeUntilDisconnectNotification} if the device is considered * being ready to receive an upstream message or is empty otherwise. * @throws NullPointerException If msg is {@code null}. */ public static Optional<TimeUntilDisconnectNotification> fromMessage(final Message msg) { final Integer ttd = MessageHelper.getTimeUntilDisconnect(msg); if (ttd == null) { return Optional.empty(); } else if (ttd == 0 || MessageHelper.isDeviceCurrentlyConnected(msg)) { final String tenantId = MessageHelper.getTenantIdAnnotation(msg); final String deviceId = MessageHelper.getDeviceId(msg); if (tenantId != null && deviceId != null) { final Instant creationTime = Instant.ofEpochMilli(msg.getCreationTime()); final TimeUntilDisconnectNotification notification = new TimeUntilDisconnectNotification(tenantId, deviceId, ttd, getReadyUntilInstantFromTtd(ttd, creationTime), creationTime); return Optional.of(notification); } } return Optional.empty(); }
/** * Checks whether an AMQP message contains required standard properties. * <p> * This method checks if the message contains a valid device identifier using * the {@link #hasValidDeviceId(ResourceIdentifier, Message)} method. * <p> * After successful verification the following properties are added to the message's <em>annotations</em>: * <ul> * <li>{@link MessageHelper#APP_PROPERTY_DEVICE_ID} - the ID of the device that reported the data.</li> * <li>{@link MessageHelper#APP_PROPERTY_TENANT_ID} - the ID of the tenant as indicated by the link target's second segment.</li> * <li>{@link MessageHelper#APP_PROPERTY_RESOURCE} - the full resource path including the endpoint, the tenant and the device ID.</li> * </ul> * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the message passes all checks. */ protected static final boolean verifyStandardProperties(final ResourceIdentifier linkTarget, final Message msg) { if (!hasValidDeviceId(linkTarget, msg)) { return false; } else { final ResourceIdentifier targetResource = ResourceIdentifier .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), MessageHelper.getDeviceId(msg)); MessageHelper.annotate(msg, targetResource); return true; } }
/** * Checks whether an AMQP message contains required standard properties. * <p> * This method checks if the message contains a valid device identifier using * the {@link #hasValidDeviceId(ResourceIdentifier, Message)} method. * <p> * After successful verification the following properties are added to the message's <em>annotations</em>: * <ul> * <li>{@link MessageHelper#APP_PROPERTY_DEVICE_ID} - the ID of the device that reported the data.</li> * <li>{@link MessageHelper#APP_PROPERTY_TENANT_ID} - the ID of the tenant as indicated by the link target's second segment.</li> * <li>{@link MessageHelper#APP_PROPERTY_RESOURCE} - the full resource path including the endpoint, the tenant and the device ID.</li> * </ul> * * @param linkTarget The resource path to check the message's properties against for consistency. * @param msg The AMQP 1.0 message to perform the checks on. * @return {@code true} if the message passes all checks. */ protected static final boolean verifyStandardProperties(final ResourceIdentifier linkTarget, final Message msg) { if (!hasValidDeviceId(linkTarget, msg)) { return false; } else { final ResourceIdentifier targetResource = ResourceIdentifier .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), MessageHelper.getDeviceId(msg)); MessageHelper.annotate(msg, targetResource); return true; } }
final String deviceId = MessageHelper.getDeviceId(request); if (deviceId == null) { LOG.debug("sent request [target address: {}, subject: {}, correlation ID: {}] to service",
@Override public final Future<ProtonDelivery> send(final Message rawMessage, final SpanContext parent) { Objects.requireNonNull(rawMessage); if (!isRegistrationAssertionRequired()) { MessageHelper.getAndRemoveRegistrationAssertion(rawMessage); } final Span span = startSpan(parent, rawMessage); Tags.MESSAGE_BUS_DESTINATION.set(span, targetAddress); span.setTag(MessageHelper.APP_PROPERTY_TENANT_ID, tenantId); span.setTag(MessageHelper.APP_PROPERTY_DEVICE_ID, MessageHelper.getDeviceId(rawMessage)); tracer.inject(span.context(), Format.Builtin.TEXT_MAP, new MessageAnnotationsInjectAdapter(rawMessage)); return executeOrRunOnContext(result -> { if (sender.sendQueueFull()) { final ServiceInvocationException e = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no credit available"); logError(span, e); span.finish(); result.fail(e); } else { sendMessage(rawMessage, span).setHandler(result.completer()); } }); }
/** * {@inheritDoc} */ @Override public Future<ProtonDelivery> sendAndWaitForOutcome(final Message rawMessage, final SpanContext parent) { Objects.requireNonNull(rawMessage); // we create a child span (instead of a following span) because we depend // on the outcome of the sending operation final Span span = startChildSpan(parent, rawMessage); Tags.MESSAGE_BUS_DESTINATION.set(span, targetAddress); span.setTag(MessageHelper.APP_PROPERTY_TENANT_ID, tenantId); span.setTag(MessageHelper.APP_PROPERTY_DEVICE_ID, MessageHelper.getDeviceId(rawMessage)); tracer.inject(span.context(), Format.Builtin.TEXT_MAP, new MessageAnnotationsInjectAdapter(rawMessage)); if (!isRegistrationAssertionRequired()) { MessageHelper.getAndRemoveRegistrationAssertion(rawMessage); } return executeOrRunOnContext(result -> { if (sender.sendQueueFull()) { final ServiceInvocationException e = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no credit available"); logError(span, e); span.finish(); result.fail(e); } else { sendMessageAndWaitForOutcome(rawMessage, span).setHandler(result.completer()); } }); }