Search in sources :

Example 11 with Released

use of org.apache.qpid.proton.amqp.messaging.Released in project hono by eclipse.

the class GenericSenderLink method mapUnacceptedOutcomeToErrorResult.

private Future<ProtonDelivery> mapUnacceptedOutcomeToErrorResult(final ProtonDelivery delivery) {
    final DeliveryState remoteState = delivery.getRemoteState();
    if (Accepted.class.isInstance(remoteState)) {
        throw new IllegalStateException("delivery is expected to be rejected, released or modified here, not accepted");
    }
    ServiceInvocationException e = null;
    if (Rejected.class.isInstance(remoteState)) {
        final Rejected rejected = (Rejected) remoteState;
        e = Optional.ofNullable(rejected.getError()).map(StatusCodeMapper::fromTransferError).orElseGet(() -> new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
    } else if (Released.class.isInstance(remoteState)) {
        e = new MessageNotProcessedException();
    } else if (Modified.class.isInstance(remoteState)) {
        final Modified modified = (Modified) remoteState;
        if (modified.getUndeliverableHere()) {
            e = new MessageUndeliverableException();
        } else {
            e = new MessageNotProcessedException();
        }
    }
    return Future.failedFuture(e);
}
Also used : MessageUndeliverableException(org.eclipse.hono.client.MessageUndeliverableException) Released(org.apache.qpid.proton.amqp.messaging.Released) Modified(org.apache.qpid.proton.amqp.messaging.Modified) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) MessageNotProcessedException(org.eclipse.hono.client.MessageNotProcessedException)

Example 12 with Released

use of org.apache.qpid.proton.amqp.messaging.Released in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapter method onMessageReceived.

/**
 * Processes an AMQP message received from a device.
 * <p>
 * This method settles the transfer with the following outcomes:
 * <ul>
 * <li><em>accepted</em> if the message has been successfully processed.</li>
 * <li><em>rejected</em> if the message could not be processed due to a problem caused by the device.</li>
 * <li><em>released</em> if the message could not be forwarded to a downstream consumer.</li>
 * </ul>
 *
 * @param ctx The context for the message.
 * @return A future indicating the outcome of processing the message.
 *         The future will succeed if the message has been processed successfully, otherwise it
 *         will fail with a {@link ServiceInvocationException}.
 */
protected Future<Void> onMessageReceived(final AmqpContext ctx) {
    log.trace("processing message [address: {}, qos: {}]", ctx.getAddress(), ctx.getRequestedQos());
    final Span msgSpan = ctx.getTracingSpan();
    return validateEndpoint(ctx).compose(validatedEndpoint -> validateAddress(validatedEndpoint.getAddress(), validatedEndpoint.getAuthenticatedDevice())).compose(validatedAddress -> uploadMessage(ctx, validatedAddress, msgSpan)).map(d -> {
        ProtonHelper.accepted(ctx.delivery(), true);
        return d;
    }).recover(t -> {
        if (t instanceof ClientErrorException) {
            MessageHelper.rejected(ctx.delivery(), getErrorCondition(t));
        } else {
            ProtonHelper.released(ctx.delivery(), true);
        }
        log.debug("failed to process message from device", t);
        TracingHelper.logError(msgSpan, t);
        return Future.failedFuture(t);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) DeviceChangeNotification(org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification) Tags(io.opentracing.tag.Tags) ProtonServer(io.vertx.proton.ProtonServer) HonoProtonHelper(org.eclipse.hono.util.HonoProtonHelper) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) EndpointType(org.eclipse.hono.service.metric.MetricsTags.EndpointType) Modified(org.apache.qpid.proton.amqp.messaging.Modified) DeviceCredentials(org.eclipse.hono.adapter.auth.device.DeviceCredentials) Map(java.util.Map) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) AuthorizationException(org.eclipse.hono.adapter.AuthorizationException) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) Fields(io.opentracing.log.Fields) AmqpError(org.apache.qpid.proton.amqp.transport.AmqpError) TracingHelper(org.eclipse.hono.tracing.TracingHelper) ProtonSaslAuthenticatorFactory(io.vertx.proton.sasl.ProtonSaslAuthenticatorFactory) AllDevicesOfTenantDeletedNotification(org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification) TenantServiceBasedX509Authentication(org.eclipse.hono.adapter.auth.device.TenantServiceBasedX509Authentication) Predicate(java.util.function.Predicate) Collection(java.util.Collection) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) List(java.util.List) QoS(org.eclipse.hono.service.metric.MetricsTags.QoS) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Optional(java.util.Optional) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) ProtonLink(io.vertx.proton.ProtonLink) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) ProtonServerOptions(io.vertx.proton.ProtonServerOptions) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ConnectionLimitManager(org.eclipse.hono.adapter.limiting.ConnectionLimitManager) Command(org.eclipse.hono.client.command.Command) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AdapterDisabledException(org.eclipse.hono.adapter.AdapterDisabledException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) OptionalInt(java.util.OptionalInt) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Commands(org.eclipse.hono.client.command.Commands) Constants(org.eclipse.hono.util.Constants) CompositeFuture(io.vertx.core.CompositeFuture) ProtonSession(io.vertx.proton.ProtonSession) Symbol(org.apache.qpid.proton.amqp.Symbol) AdapterConnectionsExceededException(org.eclipse.hono.adapter.AdapterConnectionsExceededException) Target(org.apache.qpid.proton.amqp.transport.Target) UnsignedLong(org.apache.qpid.proton.amqp.UnsignedLong) Message(org.apache.qpid.proton.message.Message) HttpUtils(org.eclipse.hono.service.http.HttpUtils) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification) Strings(org.eclipse.hono.util.Strings) UsernamePasswordAuthProvider(org.eclipse.hono.adapter.auth.device.UsernamePasswordAuthProvider) CredentialsApiAuthProvider(org.eclipse.hono.adapter.auth.device.CredentialsApiAuthProvider) AbstractProtocolAdapterBase(org.eclipse.hono.adapter.AbstractProtocolAdapterBase) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) Promise(io.vertx.core.Promise) ServerErrorException(org.eclipse.hono.client.ServerErrorException) ProtonHelper(io.vertx.proton.ProtonHelper) Sample(io.micrometer.core.instrument.Timer.Sample) Released(org.apache.qpid.proton.amqp.messaging.Released) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Source(org.apache.qpid.proton.amqp.transport.Source) ConnectionAttemptOutcome(org.eclipse.hono.service.metric.MetricsTags.ConnectionAttemptOutcome) MemoryBasedConnectionLimitStrategy(org.eclipse.hono.adapter.limiting.MemoryBasedConnectionLimitStrategy) X509AuthProvider(org.eclipse.hono.adapter.auth.device.X509AuthProvider) Handler(io.vertx.core.Handler) Collections(java.util.Collections) DefaultConnectionLimitManager(org.eclipse.hono.adapter.limiting.DefaultConnectionLimitManager) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Span(io.opentracing.Span)

Example 13 with Released

use of org.apache.qpid.proton.amqp.messaging.Released in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest method testOneWayCommandReleased.

/**
 * Verifies that the adapter signals a released one-way command
 * back to the sender of the command.
 */
@Test
public void testOneWayCommandReleased() {
    final DeliveryState remoteState = new Released();
    final ProtonDelivery unsuccessfulDelivery = mock(ProtonDelivery.class);
    when(unsuccessfulDelivery.remotelySettled()).thenReturn(true);
    when(unsuccessfulDelivery.getRemoteState()).thenReturn(remoteState);
    testOneWayCommandOutcome(unsuccessfulDelivery, ctx -> verify(ctx).release(), ProcessingOutcome.UNDELIVERABLE);
}
Also used : Released(org.apache.qpid.proton.amqp.messaging.Released) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) ProtonDelivery(io.vertx.proton.ProtonDelivery) Test(org.junit.jupiter.api.Test)

Example 14 with Released

use of org.apache.qpid.proton.amqp.messaging.Released in project hono by eclipse.

the class ProtonBasedApplicationClientTest method testCreateTelemetryConsumerReleasesMessageOnException.

/**
 * Verifies that the message consumer created by the factory catches an exception
 * thrown by the client provided handler and releases the message.
 *
 * @param ctx The vert.x test context.
 */
@Test
@SuppressWarnings("unchecked")
void testCreateTelemetryConsumerReleasesMessageOnException(final VertxTestContext ctx) {
    // GIVEN a client provided message handler that throws an exception on
    // each message received
    final Handler<DownstreamMessage<AmqpMessageContext>> consumer = VertxMockSupport.mockHandler();
    doThrow(new IllegalArgumentException("message does not contain required properties"), new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)).when(consumer).handle(any(DownstreamMessage.class));
    client.createTelemetryConsumer("tenant", consumer, t -> {
    }).onComplete(ctx.succeeding(mc -> {
        final ArgumentCaptor<ProtonMessageHandler> messageHandler = ArgumentCaptor.forClass(ProtonMessageHandler.class);
        ctx.verify(() -> {
            verify(connection).createReceiver(eq("telemetry/tenant"), eq(ProtonQoS.AT_LEAST_ONCE), messageHandler.capture(), anyInt(), anyBoolean(), VertxMockSupport.anyHandler());
            final var msg = ProtonHelper.message();
            // WHEN a message is received and the client provided consumer
            // throws an IllegalArgumentException
            var delivery = mock(ProtonDelivery.class);
            messageHandler.getValue().handle(delivery, msg);
            // THEN the message is forwarded to the client provided handler
            verify(consumer).handle(any(DownstreamMessage.class));
            // AND the AMQP message is being released
            verify(delivery).disposition(any(Released.class), eq(Boolean.TRUE));
            // WHEN a message is received and the client provided consumer
            // throws a ClientErrorException
            delivery = mock(ProtonDelivery.class);
            messageHandler.getValue().handle(delivery, msg);
            // THEN the message is forwarded to the client provided handler
            verify(consumer, times(2)).handle(any(DownstreamMessage.class));
            // AND the AMQP message is being rejected
            verify(delivery).disposition(any(Rejected.class), eq(Boolean.TRUE));
        });
        ctx.completeNow();
    }));
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) ProtonReceiver(io.vertx.proton.ProtonReceiver) BeforeEach(org.junit.jupiter.api.BeforeEach) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) AmqpClientUnitTestHelper(org.eclipse.hono.client.amqp.test.AmqpClientUnitTestHelper) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ArgumentMatchers.anyBoolean(org.mockito.ArgumentMatchers.anyBoolean) Timeout(io.vertx.junit5.Timeout) Mockito.doThrow(org.mockito.Mockito.doThrow) ArgumentCaptor(org.mockito.ArgumentCaptor) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Modified(org.apache.qpid.proton.amqp.messaging.Modified) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) DisconnectListener(org.eclipse.hono.client.DisconnectListener) AsyncResult(io.vertx.core.AsyncResult) HonoConnection(org.eclipse.hono.client.HonoConnection) ArgumentMatchers.anyInt(org.mockito.ArgumentMatchers.anyInt) Promise(io.vertx.core.Promise) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) Vertx(io.vertx.core.Vertx) Mockito.times(org.mockito.Mockito.times) ProtonHelper(io.vertx.proton.ProtonHelper) ProtonQoS(io.vertx.proton.ProtonQoS) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) VertxExtension(io.vertx.junit5.VertxExtension) Released(org.apache.qpid.proton.amqp.messaging.Released) Future(io.vertx.core.Future) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) ProtonSender(io.vertx.proton.ProtonSender) Handler(io.vertx.core.Handler) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Mockito.mock(org.mockito.Mockito.mock) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) ArgumentCaptor(org.mockito.ArgumentCaptor) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) ProtonDelivery(io.vertx.proton.ProtonDelivery) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Test(org.junit.jupiter.api.Test)

Aggregations

Released (org.apache.qpid.proton.amqp.messaging.Released)14 Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)9 DeliveryState (org.apache.qpid.proton.amqp.transport.DeliveryState)8 Message (org.apache.qpid.proton.message.Message)8 Accepted (org.apache.qpid.proton.amqp.messaging.Accepted)7 Modified (org.apache.qpid.proton.amqp.messaging.Modified)7 Handler (io.vertx.core.Handler)6 ProtonDelivery (io.vertx.proton.ProtonDelivery)6 AsyncResult (io.vertx.core.AsyncResult)4 ProtonConnection (io.vertx.proton.ProtonConnection)4 ErrorCondition (org.apache.qpid.proton.amqp.transport.ErrorCondition)4 ClientErrorException (org.eclipse.hono.client.ClientErrorException)4 Future (io.vertx.core.Future)3 Async (io.vertx.ext.unit.Async)3 TestContext (io.vertx.ext.unit.TestContext)3 VertxUnitRunner (io.vertx.ext.unit.junit.VertxUnitRunner)3 ProtonHelper (io.vertx.proton.ProtonHelper)3 ProtonQoS (io.vertx.proton.ProtonQoS)3 ProtonReceiver (io.vertx.proton.ProtonReceiver)3 ProtonSender (io.vertx.proton.ProtonSender)3