private Long getSenderTimeFromMessageProperties(final Message message) { final Long senderTime = MessageHelper.getApplicationProperty(message.getApplicationProperties(), TIME_STAMP_VARIABLE, Long.class); if (senderTime == null) { LOGGER.warn("could not get sender time from '" + TIME_STAMP_VARIABLE + "' message application property"); } return senderTime; }
/** * Adds a tenant ID to a message's <em>application properties</em>. * <p> * The name of the application property is {@link #APP_PROPERTY_TENANT_ID}. * * @param msg The message. * @param tenantId The tenant identifier to add. * @throws NullPointerException if any of the parameters are {@code null}. */ public static void addTenantId(final Message msg, final String tenantId) { addProperty(msg, APP_PROPERTY_TENANT_ID, tenantId); }
private R getRequestResponseResult(final Message message) { final Integer status = MessageHelper.getApplicationProperty( message.getApplicationProperties(), MessageHelper.APP_PROPERTY_STATUS, Integer.class); if (status == null) { return null; } else { final CacheDirective cacheDirective = CacheDirective.from(MessageHelper.getCacheDirective(message)); return getResult(status, message.getContentType(), MessageHelper.getPayload(message), cacheDirective); } }
private void addProperties(final Message msg, final String deviceId, final String registrationAssertion) { MessageHelper.addDeviceId(msg, deviceId); if (isRegistrationAssertionRequired()) { MessageHelper.addRegistrationAssertion(msg, registrationAssertion); } }
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()); } }
MessageHelper.addDeviceId(msg, target.getResourceId()); if (!regAssertionRequired) { MessageHelper.annotate(msg, target); MessageHelper.addProperty(msg, MessageHelper.APP_PROPERTY_ORIG_ADDRESS, publishAddress); MessageHelper.setPayload(msg, contentType, payload); msg.setContentType(contentType); if (timeUntilDisconnect != null) { MessageHelper.addTimeUntilDisconnect(msg, timeUntilDisconnect); MessageHelper.setCreationTime(msg);
private static Message createResponseMessage( final String targetAddress, final String correlationId, final String contentType, final Buffer payload, final Map<String, Object> properties, final int status) { Objects.requireNonNull(targetAddress); Objects.requireNonNull(correlationId); final Message msg = ProtonHelper.message(); msg.setCorrelationId(correlationId); msg.setAddress(targetAddress); MessageHelper.setPayload(msg, contentType, payload); if (properties != null) { msg.setApplicationProperties(new ApplicationProperties(properties)); } MessageHelper.setCreationTime(msg); MessageHelper.addProperty(msg, MessageHelper.APP_PROPERTY_STATUS, status); return msg; }
/** * 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(); }
MessageHelper.addRegistrationAssertion(message, registrationAssertion); MessageHelper.addProperty(message, MessageHelper.APP_PROPERTY_ORIG_ADAPTER, getTypeName()); if (getConfig().isDefaultsEnabled()) { final JsonObject defaults = registrationInfo.getJsonObject(RegistrationConstants.FIELD_DEFAULTS); MessageHelper.addJmsVendorProperties(message);
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()); } }
/** * Parses a message's body into a JSON object. * * @param msg The AMQP 1.0 message to parse the body of. * @return The message body parsed into a JSON object or {@code null} if the message does not have a <em>Data</em> * nor an <em>AmqpValue</em> section. * @throws NullPointerException if the message is {@code null}. * @throws DecodeException if the payload cannot be parsed into a JSON object. */ public static JsonObject getJsonPayload(final Message msg) { final Buffer buffer = getPayload(msg); return buffer != null ? buffer.toJsonObject() : null; }
/** * 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; } }
private void getToken(final ProtonConnection openCon, final Future<HonoUser> authResult) { final ProtonMessageHandler messageHandler = (delivery, message) -> { final String type = MessageHelper.getApplicationProperty( message.getApplicationProperties(), AuthenticationConstants.APPLICATION_PROPERTY_TYPE, String.class); if (AuthenticationConstants.TYPE_AMQP_JWT.equals(type)) { final String payload = MessageHelper.getPayloadAsString(message); if (payload != null) { final HonoUser user = new HonoUserAdapter() { @Override public String getToken() { return payload; } }; LOG.debug("successfully retrieved token from Authentication service"); authResult.complete(user); } else { authResult.fail("message from Authentication service contains no body"); } } else { authResult.fail("Authentication service issued unsupported token [type: " + type + "]"); } }; openReceiver(openCon, messageHandler).compose(openReceiver -> { LOG.debug("opened receiver link to Authentication service, waiting for token ..."); }, authResult); }
/** * Set the JSON payload of the message using a {@link Data} section. * <p> * If the payload is {@code null}, then neither the payload, nor content type will be set. * </p> * <p> * <b>Note:</b> No formal check is done if the payload actually is a JSON string. * </p> * * @param message The message to update. * @param payload The optional message payload. * * @throws NullPointerException If the parameter {@code message} was {@code null}. */ public static void setJsonPayload(final Message message, final String payload) { Objects.requireNonNull(message); setPayload(message, CONTENT_TYPE_APPLICATION_JSON, payload != null ? payload.getBytes(StandardCharsets.UTF_8) : null); }
/** * 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; }
messageCount++; if (!MessageHelper.hasDataBody(message)) { errorCount++; setSampleStartIfNotSetYet(sampleReceivedTime); return; final Buffer payload = MessageHelper.getPayload(message); final byte[] messageBody = payload.getBytes(); bytesReceived += messageBody.length;
/** * Construct a message consumer that detects an indication that a device is ready to receive an upstream * message and delegates to the passed callback handlers. * * @param messageConsumer Message consumer that handles generic messages. * @param notificationReadyToDeliverConsumer Consumer<TimeUntilDisconnectNotification> that is called when the message indicates the current readiness * to receive an upstream message. * @return The message consumer that invokes the specific handlers depending on the event type. * @throws NullPointerException if any of the parameters are {@code null}. */ public static Consumer<Message> getConsumer(final Consumer<Message> messageConsumer, final Consumer<TimeUntilDisconnectNotification> notificationReadyToDeliverConsumer) { Objects.requireNonNull(messageConsumer); Objects.requireNonNull(notificationReadyToDeliverConsumer); return new MessageTap( msg -> { if (msg.getBody() == null || MessageHelper.hasDataBody(msg, false)) { TimeUntilDisconnectNotification.fromMessage(msg).ifPresent( notificationObject -> notificationReadyToDeliverConsumer.accept(notificationObject)); messageConsumer.accept(msg); } }); }
/** * Verifies that the endpoint forwards a request message via the event bus. */ @Test public void testProcessMessageSendsRequestViaEventBus() { final Message msg = ProtonHelper.message(); msg.setMessageId("random-id"); msg.setSubject(CredentialsConstants.CredentialsAction.add.toString()); MessageHelper.addDeviceId(msg, "4711"); MessageHelper.addTenantId(msg, Constants.DEFAULT_TENANT); MessageHelper.annotate(msg, resource); msg.setBody(new AmqpValue(new JsonObject().put("temp", 15).encode())); endpoint.processRequest(msg, resource, Constants.PRINCIPAL_ANONYMOUS); verify(eventBus).send(eq(CredentialsConstants.EVENT_BUS_ADDRESS_CREDENTIALS_IN), any(JsonObject.class), any(DeliveryOptions.class)); } }
@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()); } }); }
/** * Sets an AMQP 1.0 message delivery state to either RELEASED in the case of a <em>ServerErrorException</em> or REJECTED in the * case of a <em>ClientErrorException</em>. In the REJECTED case, the supplied exception will provide * the error condition value and description as reason for rejection. * * @param t The service invocation exception. * @throws NullPointerException if error is {@code null}. */ void handleFailure(final Throwable t) { Objects.requireNonNull(t); final ErrorCondition condition = getErrorCondition(t); if (ServiceInvocationException.class.isInstance(t)) { final ServiceInvocationException error = (ServiceInvocationException) t; if (ServerErrorException.class.isInstance(error)) { ProtonHelper.released(delivery, true); } else { MessageHelper.rejected(delivery, condition); } } else { MessageHelper.rejected(delivery, condition); } }