Search in sources :

Example 1 with MessagingType

use of org.eclipse.hono.util.MessagingType in project hono by eclipse.

the class AssumeMessagingSystemCondition method evaluateExecutionCondition.

@Override
public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext context) {
    final Optional<AssumeMessagingSystem> annotation = AnnotationUtils.findAnnotation(context.getElement(), AssumeMessagingSystem.class);
    if (annotation.isPresent()) {
        final MessagingType assumedMessagingType = annotation.get().type();
        final MessagingType messagingType = IntegrationTestSupport.getConfiguredMessagingType();
        if (messagingType != assumedMessagingType) {
            return ConditionEvaluationResult.disabled(String.format("Test assumes to run on %s, but current test profile is %s. Skipping test!", assumedMessagingType, messagingType));
        } else {
            return ConditionEvaluationResult.enabled(String.format("Test assumes to run on %s, which matches current test profile is %s. Running test!", assumedMessagingType, messagingType));
        }
    }
    return ConditionEvaluationResult.enabled("Test makes no assumptions of messaging systems. Running test.");
}
Also used : MessagingType(org.eclipse.hono.util.MessagingType)

Example 2 with MessagingType

use of org.eclipse.hono.util.MessagingType in project hono by eclipse.

the class AbstractMappingAndDelegatingCommandHandler method mapAndDelegateIncomingCommand.

/**
 * Delegates an incoming command to the protocol adapter instance that the target
 * device is connected to.
 * <p>
 * Determines the target gateway (if applicable) and protocol adapter instance for an incoming command
 * and delegates the command to the resulting protocol adapter instance.
 *
 * @param commandContext The context of the command to send.
 * @param timer The timer indicating the amount of time used for processing the command message.
 * @return A future indicating the outcome of the operation.
 * @throws NullPointerException if any of the parameters are {@code null}.
 */
protected final Future<Void> mapAndDelegateIncomingCommand(final CommandContext commandContext, final Timer.Sample timer) {
    Objects.requireNonNull(commandContext);
    Objects.requireNonNull(timer);
    final Command command = commandContext.getCommand();
    // determine last used gateway device id
    if (log.isTraceEnabled()) {
        log.trace("determine command target gateway/adapter for [{}]", command);
    }
    final Future<TenantObject> tenantObjectFuture = tenantClient.get(command.getTenant(), commandContext.getTracingContext());
    return tenantObjectFuture.compose(tenantObject -> {
        TenantTraceSamplingHelper.applyTraceSamplingPriority(tenantObject, null, commandContext.getTracingSpan());
        commandContext.put(CommandContext.KEY_TENANT_CONFIG, tenantObject);
        // check whether the handler messaging type is equal to the messaging type of the tenant (if set)
        final MessagingType tenantMessagingType = Optional.ofNullable(tenantObject.getProperty(TenantConstants.FIELD_EXT, JsonObject.class)).map(ext -> ext.getString(TenantConstants.FIELD_EXT_MESSAGING_TYPE)).map(MessagingType::valueOf).orElse(null);
        if (tenantMessagingType != null && getMessagingType() != tenantMessagingType) {
            log.info("command received via {} but tenant is configured to use {} [{}]", getMessagingType(), tenantMessagingType, commandContext.getCommand());
            commandContext.getTracingSpan().log(String.format("command received via %s but tenant is configured to use %s", getMessagingType(), tenantMessagingType));
        }
        return commandTargetMapper.getTargetGatewayAndAdapterInstance(command.getTenant(), command.getDeviceId(), commandContext.getTracingContext());
    }).recover(cause -> {
        final Throwable error;
        if (tenantObjectFuture.failed() && ServiceInvocationException.extractStatusCode(cause) == HttpURLConnection.HTTP_NOT_FOUND) {
            error = new TenantDisabledOrNotRegisteredException(command.getTenant(), HttpURLConnection.HTTP_NOT_FOUND);
        } else if (cause instanceof DeviceDisabledOrNotRegisteredException) {
            error = cause;
        } else if (ServiceInvocationException.extractStatusCode(cause) == HttpURLConnection.HTTP_NOT_FOUND) {
            log.debug("no target adapter instance found for command with device id " + command.getDeviceId(), cause);
            error = new NoConsumerException("no target adapter instance found");
        } else {
            log.debug("error getting target gateway and adapter instance for command with device id " + command.getDeviceId(), cause);
            error = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "error getting target gateway and adapter instance", cause);
        }
        if (error instanceof ClientErrorException) {
            commandContext.reject(error);
        } else {
            commandContext.release(error);
        }
        reportCommandProcessingError(command, tenantObjectFuture.result(), error, timer);
        return Future.failedFuture(cause);
    }).compose(result -> {
        final String targetAdapterInstanceId = result.getString(DeviceConnectionConstants.FIELD_ADAPTER_INSTANCE_ID);
        final String targetDeviceId = result.getString(DeviceConnectionConstants.FIELD_PAYLOAD_DEVICE_ID);
        final String targetGatewayId = targetDeviceId.equals(command.getDeviceId()) ? null : targetDeviceId;
        if (Objects.isNull(targetGatewayId)) {
            log.trace("determined target adapter instance [{}] for [{}] (command not mapped to gateway)", targetAdapterInstanceId, command);
        } else {
            command.setGatewayId(targetGatewayId);
            log.trace("determined target gateway [{}] and adapter instance [{}] for [{}]", targetGatewayId, targetAdapterInstanceId, command);
            commandContext.getTracingSpan().log("determined target gateway [" + targetGatewayId + "]");
        }
        return sendCommand(commandContext, targetAdapterInstanceId, tenantObjectFuture.result(), timer);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) InternalCommandSender(org.eclipse.hono.client.command.InternalCommandSender) Command(org.eclipse.hono.client.command.Command) TenantConstants(org.eclipse.hono.util.TenantConstants) Lifecycle(org.eclipse.hono.util.Lifecycle) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Tags(io.opentracing.tag.Tags) NoConsumerException(org.eclipse.hono.client.NoConsumerException) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) MessagingType(org.eclipse.hono.util.MessagingType) Timer(io.micrometer.core.instrument.Timer) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) DeviceConnectionConstants(org.eclipse.hono.util.DeviceConnectionConstants) CommandContext(org.eclipse.hono.client.command.CommandContext) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) TenantClient(org.eclipse.hono.client.registry.TenantClient) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) Optional(java.util.Optional) Span(io.opentracing.Span) TenantObject(org.eclipse.hono.util.TenantObject) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) Command(org.eclipse.hono.client.command.Command) NoConsumerException(org.eclipse.hono.client.NoConsumerException) MessagingType(org.eclipse.hono.util.MessagingType) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Example 3 with MessagingType

use of org.eclipse.hono.util.MessagingType in project hono by eclipse.

the class Commands method decodeRequestIdParameters.

/**
 * Decodes the given request identifier.
 *
 * @param requestId The request id to extract the values from.
 * @param deviceId The device identifier.
 * @return The object containing the parameters decoded from the request identifier.
 * @throws NullPointerException if any of the parameters is {@code null}.
 * @throws IllegalArgumentException if the given requestId is invalid.
 * @see #encodeRequestIdParameters(String, String, String, MessagingType) getRequestId() as the reverse operation.
 */
public static CommandRequestIdParameters decodeRequestIdParameters(final String requestId, final String deviceId) {
    Objects.requireNonNull(requestId);
    Objects.requireNonNull(deviceId);
    try {
        final String replyToOptionsBitFlag = requestId.substring(0, 1);
        final boolean addDeviceIdToReply = Commands.isReplyToContainedDeviceIdOptionSet(replyToOptionsBitFlag);
        final int lengthStringOne = Integer.parseInt(requestId.substring(1, 3), 16);
        final String replyIdWithoutDevice = requestId.substring(3 + lengthStringOne);
        final String correlationId = requestId.substring(3, 3 + lengthStringOne);
        final String replyToId = addDeviceIdToReply ? deviceId + "/" + replyIdWithoutDevice : replyIdWithoutDevice;
        final MessagingType messagingType = getMessagingTypeFromBitFlag(replyToOptionsBitFlag);
        return new CommandRequestIdParameters(correlationId, replyToId, messagingType);
    } catch (final IndexOutOfBoundsException e) {
        throw new IllegalArgumentException("invalid requestId", e);
    }
}
Also used : MessagingType(org.eclipse.hono.util.MessagingType)

Example 4 with MessagingType

use of org.eclipse.hono.util.MessagingType in project hono by eclipse.

the class Commands method getOriginalReplyToIdAndMessagingType.

/**
 * Gets the reply-to-id that was set in the original command message.
 * <p>
 * The input is the id returned by {@link #getDeviceFacingReplyToId(String, String, MessagingType)}, which is
 * used in the command message forwarded to the device.
 *
 * @param deviceFacingReplyToId The reply-to-id as returned by {@link #getDeviceFacingReplyToId(String, String, MessagingType)}.
 * @param deviceId The device id.
 * @return The pair of reply-to-id and messaging type.
 * @throws NullPointerException if deviceFacingReplyToId or deviceId is {@code null}.
 * @throws IllegalArgumentException if the given deviceFacingReplyToId is invalid.
 * @see #getDeviceFacingReplyToId(String, String, MessagingType) getDeviceFacingReplyToId() as the reverse operation.
 */
public static Pair<String, MessagingType> getOriginalReplyToIdAndMessagingType(final String deviceFacingReplyToId, final String deviceId) {
    Objects.requireNonNull(deviceFacingReplyToId);
    Objects.requireNonNull(deviceId);
    try {
        // deviceFacingReplyToId starts with deviceId/[bit flag]
        final String replyToOptionsBitFlag = deviceFacingReplyToId.substring(deviceId.length() + 1, deviceId.length() + 2);
        final boolean replyToContainedDeviceId = isReplyToContainedDeviceIdOptionSet(replyToOptionsBitFlag);
        final MessagingType messagingType = getMessagingTypeFromBitFlag(replyToOptionsBitFlag);
        final String originalReplyToId = deviceFacingReplyToId.replaceFirst(deviceId + "/" + replyToOptionsBitFlag, replyToContainedDeviceId ? deviceId + "/" : "");
        return Pair.of(originalReplyToId, messagingType);
    } catch (final IndexOutOfBoundsException e) {
        throw new IllegalArgumentException("invalid deviceFacingReplyToId", e);
    }
}
Also used : MessagingType(org.eclipse.hono.util.MessagingType)

Example 5 with MessagingType

use of org.eclipse.hono.util.MessagingType in project hono by eclipse.

the class CommandResponse method fromAddressAndCorrelationId.

/**
 * Creates a response for a given response message address and correlation ID.
 *
 * @param address The address of the response message. It has to contain a tenant segment followed by the segments
 *                returned by {@link Commands#getDeviceFacingReplyToId(String, String, MessagingType)}.
 * @param correlationId The correlation ID of the command that this is the response for.
 * @param payload The payload of the response or {@code null} if the response has no payload.
 * @param contentType The contentType of the response or {@code null} if the response has no payload.
 * @param status The HTTP status code indicating the outcome of the command.
 * @return The response or {@code null} if correlation ID is {@code null}, the address cannot be parsed,
 *         the status is {@code null} or if the status code is &lt; 200 or &gt;= 600.
 */
public static CommandResponse fromAddressAndCorrelationId(final String address, final String correlationId, final Buffer payload, final String contentType, final Integer status) {
    if (correlationId == null || !ResourceIdentifier.isValid(address) || status == null) {
        LOG.debug("cannot create CommandResponse: invalid message (correlationId: {}, address: {}, status: {})", correlationId, address, status);
        return null;
    } else if (INVALID_STATUS_CODE.test(status)) {
        LOG.debug("cannot create CommandResponse: status is invalid: {}", status);
        return null;
    }
    final ResourceIdentifier resource = ResourceIdentifier.fromString(address);
    final String tenantId = resource.getTenantId();
    final String deviceId = resource.getResourceId();
    if (tenantId == null || deviceId == null) {
        LOG.debug("cannot create CommandResponse: invalid address, missing tenant and/or device identifier");
        return null;
    }
    try {
        // resource.getPathWithoutBase() represents the result of Commands.getDeviceFacingReplyToId()
        final Pair<String, MessagingType> replyToIdMessagingTypePair = Commands.getOriginalReplyToIdAndMessagingType(resource.getPathWithoutBase(), deviceId);
        return new CommandResponse(tenantId, deviceId, payload, contentType, status, correlationId, replyToIdMessagingTypePair.one(), replyToIdMessagingTypePair.two());
    } catch (final IllegalArgumentException e) {
        LOG.debug("error creating CommandResponse: invalid address, invalid last path component", e);
        return null;
    }
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) MessagingType(org.eclipse.hono.util.MessagingType)

Aggregations

MessagingType (org.eclipse.hono.util.MessagingType)5 Timer (io.micrometer.core.instrument.Timer)1 Span (io.opentracing.Span)1 SpanContext (io.opentracing.SpanContext)1 Tracer (io.opentracing.Tracer)1 Tags (io.opentracing.tag.Tags)1 Future (io.vertx.core.Future)1 JsonObject (io.vertx.core.json.JsonObject)1 HttpURLConnection (java.net.HttpURLConnection)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 ClientErrorException (org.eclipse.hono.client.ClientErrorException)1 NoConsumerException (org.eclipse.hono.client.NoConsumerException)1 ServerErrorException (org.eclipse.hono.client.ServerErrorException)1 ServiceInvocationException (org.eclipse.hono.client.ServiceInvocationException)1 Command (org.eclipse.hono.client.command.Command)1 CommandContext (org.eclipse.hono.client.command.CommandContext)1 InternalCommandSender (org.eclipse.hono.client.command.InternalCommandSender)1 DeviceDisabledOrNotRegisteredException (org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException)1 TenantClient (org.eclipse.hono.client.registry.TenantClient)1