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);
}
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);
});
}
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);
}
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();
}));
}
Aggregations