org.apache.qpid.proton.amqp.messaging.Accepted Java Examples

The following examples show how to use org.apache.qpid.proton.amqp.messaging.Accepted. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Server.java    From qpid-proton-j with Apache License 2.0 6 votes vote down vote up
@Override
public void onDelivery(Event evt) {
    Delivery dlv = evt.getDelivery();
    Link link = dlv.getLink();
    if (link instanceof Sender) {
        dlv.settle();
    } else {
        Receiver rcv = (Receiver) link;
        if (!dlv.isPartial()) {
            byte[] bytes = new byte[dlv.pending()];
            rcv.recv(bytes, 0, bytes.length);
            String address = router.getAddress(rcv);
            Message message = new Message(bytes);
            messages.put(address, message);
            dlv.disposition(Accepted.getInstance());
            dlv.settle();
            if (!quiet) {
                System.out.println(String.format("Got message(%s): %s", address, message));
            }
            send(address);
        }
    }
}
 
Example #2
Source File: AmqpTransactionCoordinatorBuilder.java    From qpid-jms with Apache License 2.0 6 votes vote down vote up
@Override
protected Sender createEndpoint(JmsSessionInfo resourceInfo) {
    Coordinator coordinator = new Coordinator();
    coordinator.setCapabilities(TxnCapability.LOCAL_TXN);

    Symbol[] outcomes = new Symbol[]{ Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL };

    Source source = new Source();
    source.setOutcomes(outcomes);

    String coordinatorName = "qpid-jms:coordinator:" + resourceInfo.getId().toString();

    Sender sender = getParent().getSession().getEndpoint().sender(coordinatorName);
    sender.setSource(source);
    sender.setTarget(coordinator);
    sender.setSenderSettleMode(SenderSettleMode.UNSETTLED);
    sender.setReceiverSettleMode(ReceiverSettleMode.FIRST);

    return sender;
}
 
Example #3
Source File: FastPathAcceptedType.java    From qpid-proton-j with Apache License 2.0 6 votes vote down vote up
@Override
public Accepted readValue() {
    DecoderImpl decoder = getDecoder();
    byte typeCode = decoder.getBuffer().get();

    switch (typeCode) {
        case EncodingCodes.LIST0:
            break;
        case EncodingCodes.LIST8:
            decoder.getBuffer().get();
            decoder.getBuffer().get();
            break;
        case EncodingCodes.LIST32:
            decoder.getBuffer().getInt();
            decoder.getBuffer().getInt();
            break;
        default:
            throw new DecodeException("Incorrect type found in Accepted type encoding: " + typeCode);
    }

    return Accepted.getInstance();
}
 
Example #4
Source File: AbstractAmqpAdapterClientDownstreamSenderTestBase.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sets up fixture.
 */
@BeforeEach
public void setUp() {
    sender = HonoClientUnitTestHelper.mockProtonSender();

    protonDelivery = mock(ProtonDelivery.class);
    when(protonDelivery.remotelySettled()).thenReturn(true);
    final Accepted deliveryState = new Accepted();
    when(protonDelivery.getRemoteState()).thenReturn(deliveryState);

    when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenReturn(protonDelivery);

    final Span span = mock(Span.class);
    when(span.context()).thenReturn(mock(SpanContext.class));
    spanBuilder = HonoClientUnitTestHelper.mockSpanBuilder(span);

    final Tracer tracer = mock(Tracer.class);
    when(tracer.buildSpan(anyString())).thenReturn(spanBuilder);

    connection = HonoClientUnitTestHelper.mockHonoConnection(mock(Vertx.class));

    when(connection.getTracer()).thenReturn(tracer);
    when(connection.createSender(any(), any(), any())).thenReturn(Future.succeededFuture(sender));

}
 
Example #5
Source File: GenericMessageSenderImpl.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sends an AMQP 1.0 message to the peer this client is configured for
 * and waits for the outcome of the transfer.
 *
 * @param message The message to send.
 * @return A future indicating the outcome of transferring the message.
 *         <p>
 *         The future will succeed with the updated delivery from the peer if
 *         the message has been settled with the <em>accepted</em> outcome.
 *         <p>
 *         The future will be failed with a {@link ServerErrorException} if the
 *         message could not be sent, e.g. due to a lack of credit. It will be
 *         failed with a {@link ClientErrorException} if the message has not
 *         been accepted by the peer.
 * @throws NullPointerException if the message is {@code null}.
 */
@Override
public Future<ProtonDelivery> sendAndWaitForOutcome(final Message message) {
    return connection.executeOnContext(result -> {
        if (sender.isOpen() && sender.getCredit() > 0) {
            sender.send(message, updatedDelivery -> {
                if (updatedDelivery.getRemoteState() instanceof Accepted) {
                    result.complete(updatedDelivery);
                } else if (updatedDelivery.getRemoteState() instanceof Released) {
                    result.fail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE));
                } else {
                    result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
                }
            });
        } else {
            result.fail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE));
        }
    });
}
 
Example #6
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that a request to upload a pre-settled telemetry message results
 * in the downstream sender not waiting for the consumer's acknowledgment.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUploadTelemetryWithAtMostOnceDeliverySemantics(final VertxTestContext ctx) {
    // GIVEN an AMQP adapter with a configured server
    final VertxBasedAmqpProtocolAdapter adapter = givenAnAmqpAdapter();
    final DownstreamSender telemetrySender = givenATelemetrySenderForAnyTenant();
    when(telemetrySender.send(any(Message.class), (SpanContext) any())).thenReturn(Future.succeededFuture(mock(ProtonDelivery.class)));

    // which is enabled for a tenant
    final TenantObject tenantObject = givenAConfiguredTenant(TEST_TENANT_ID, true);

    // IF a device sends a 'fire and forget' telemetry message
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    when(delivery.remotelySettled()).thenReturn(true);
    final Buffer payload = Buffer.buffer("payload");
    final String to = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, TEST_DEVICE).toString();

    adapter.onMessageReceived(AmqpContext.fromMessage(delivery, getFakeMessage(to, payload), null))
        .onComplete(ctx.succeeding(d -> {
            ctx.verify(() -> {
                // THEN the adapter has forwarded the message downstream
                verify(telemetrySender).send(any(Message.class), (SpanContext) any());
                // and acknowledged the message to the device
                verify(delivery).disposition(any(Accepted.class), eq(true));
                // and has reported the telemetry message
                verify(metrics).reportTelemetry(
                        eq(EndpointType.TELEMETRY),
                        eq(TEST_TENANT_ID),
                        eq(tenantObject),
                        eq(ProcessingOutcome.FORWARDED),
                        eq(QoS.AT_MOST_ONCE),
                        eq(payload.length()),
                        any());
            });
            ctx.completeNow();
        }));
}
 
Example #7
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
@SuppressWarnings("unchecked")
private void testHandleMessageSendsResponseWithStatusCode(final Throwable error, final int expectedStatus) {

    final Message msg = ProtonHelper.message();
    msg.setSubject("get");
    msg.setReplyTo(REPLY_RESOURCE.toString());
    msg.setCorrelationId(UUID.randomUUID().toString());
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final AuthorizationService authService = mock(AuthorizationService.class);
    when(authService.isAuthorized(any(HonoUser.class), any(ResourceIdentifier.class), anyString())).thenReturn(Future.succeededFuture(Boolean.TRUE));

    final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true);
    endpoint.setAuthorizationService(authService);
    endpoint.onLinkAttach(connection, sender, REPLY_RESOURCE);

    // WHEN a request for an operation is received that the client is authorized to invoke
    endpoint.handleRequestMessage(connection, receiver, resource, delivery, msg);

    // THEN then the message is accepted
    verify(delivery).disposition(argThat(d -> d instanceof Accepted), eq(Boolean.TRUE));
    // and forwarded to the service instance
    final ArgumentCaptor<Handler<AsyncResult<io.vertx.core.eventbus.Message<Object>>>> replyHandler = ArgumentCaptor.forClass(Handler.class);
    verify(eventBus).request(eq(EVENT_BUS_ADDRESS), any(JsonObject.class), any(DeliveryOptions.class), replyHandler.capture());

    // WHEN the service invocation times out
    replyHandler.getValue().handle(Future.failedFuture(error));

    // THEN a response with status 500 is sent to the client
    verify(sender).send(argThat(m -> hasStatusCode(m, expectedStatus)));
    verify(receiver).flow(1);
}
 
Example #8
Source File: AbstractSender.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a log entry in the given span with information about the message delivery outcome given in the delivery
 * parameter. Sets the {@link Tags#HTTP_STATUS} as well.
 * <p>
 * Also corresponding log output is created.
 *
 * @param currentSpan The current span to log to.
 * @param message The message.
 * @param delivery The updated delivery.
 * @throws NullPointerException if any of the parameters is {@code null}.
 */
protected final void logUpdatedDeliveryState(final Span currentSpan, final Message message, final ProtonDelivery delivery) {
    Objects.requireNonNull(currentSpan);
    final String messageId = message.getMessageId() != null ? message.getMessageId().toString() : "";
    final String messageAddress = getMessageAddress(message);
    final DeliveryState remoteState = delivery.getRemoteState();
    if (Accepted.class.isInstance(remoteState)) {
        log.trace("message [ID: {}, address: {}] accepted by peer", messageId, messageAddress);
        currentSpan.log("message accepted by peer");
        Tags.HTTP_STATUS.set(currentSpan, HttpURLConnection.HTTP_ACCEPTED);
    } else {
        final Map<String, Object> events = new HashMap<>();
        if (Rejected.class.isInstance(remoteState)) {
            final Rejected rejected = (Rejected) delivery.getRemoteState();
            Tags.HTTP_STATUS.set(currentSpan, HttpURLConnection.HTTP_BAD_REQUEST);
            if (rejected.getError() == null) {
                logMessageSendingError("message [ID: {}, address: {}] rejected by peer", messageId, messageAddress);
                events.put(Fields.MESSAGE, "message rejected by peer");
            } else {
                logMessageSendingError("message [ID: {}, address: {}] rejected by peer: {}, {}", messageId,
                        messageAddress, rejected.getError().getCondition(), rejected.getError().getDescription());
                events.put(Fields.MESSAGE, String.format("message rejected by peer: %s, %s",
                        rejected.getError().getCondition(), rejected.getError().getDescription()));
            }
        } else if (Released.class.isInstance(remoteState)) {
            logMessageSendingError("message [ID: {}, address: {}] not accepted by peer, remote state: {}",
                    messageId, messageAddress, remoteState.getClass().getSimpleName());
            Tags.HTTP_STATUS.set(currentSpan, HttpURLConnection.HTTP_UNAVAILABLE);
            events.put(Fields.MESSAGE, "message not accepted by peer, remote state: " + remoteState);
        } else if (Modified.class.isInstance(remoteState)) {
            final Modified modified = (Modified) delivery.getRemoteState();
            logMessageSendingError("message [ID: {}, address: {}] not accepted by peer, remote state: {}",
                    messageId, messageAddress, modified);
            Tags.HTTP_STATUS.set(currentSpan, modified.getUndeliverableHere() ? HttpURLConnection.HTTP_NOT_FOUND
                    : HttpURLConnection.HTTP_UNAVAILABLE);
            events.put(Fields.MESSAGE, "message not accepted by peer, remote state: " + remoteState);
        }
        TracingHelper.logError(currentSpan, events);
    }
}
 
Example #9
Source File: AbstractRequestResponseClientTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the client succeeds the result handler if the peer accepts
 * the request message for a one-way request.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testSendOneWayRequestSucceedsOnAcceptedMessage(final VertxTestContext ctx) {

    // GIVEN a request-response client that times out requests after 200 ms
    client.setRequestTimeout(200);

    // WHEN sending a one-way request message with some headers and payload
    final JsonObject payload = new JsonObject().put("key", "value");
    final Map<String, Object> applicationProps = new HashMap<>();

    final Message request = ProtonHelper.message();
    request.setMessageId("12345");
    request.setCorrelationId("23456");
    request.setSubject("aRequest");
    request.setApplicationProperties(new ApplicationProperties(applicationProps));
    MessageHelper.setPayload(request, "application/json", payload.toBuffer());

    final SpanContext spanContext = mock(SpanContext.class);
    final Span span = mock(Span.class);
    when(span.context()).thenReturn(spanContext);

    client.sendRequest(request, ctx.succeeding(t -> {
        // THEN the result handler is succeeded
        ctx.completeNow();
    }), null, span);
    // and the peer accepts the message
    final Accepted accepted = new Accepted();
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    when(delivery.getRemoteState()).thenReturn(accepted);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<ProtonDelivery>> dispositionHandlerCaptor = ArgumentCaptor.forClass(Handler.class);
    verify(sender).send(any(Message.class), dispositionHandlerCaptor.capture());
    dispositionHandlerCaptor.getValue().handle(delivery);
}
 
Example #10
Source File: EventSenderImplTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the sender waits for the peer to settle and
 * accept a message before succeeding the returned future.
 */
@Test
public void testSendMessageWaitsForAcceptedOutcome() {

    // GIVEN a sender that has credit
    when(sender.sendQueueFull()).thenReturn(Boolean.FALSE);
    final DownstreamSender messageSender = new EventSenderImpl(connection, sender, "tenant", "telemetry/tenant");
    final AtomicReference<Handler<ProtonDelivery>> handlerRef = new AtomicReference<>();
    doAnswer(invocation -> {
        handlerRef.set(invocation.getArgument(1));
        return mock(ProtonDelivery.class);
    }).when(sender).send(any(Message.class), VertxMockSupport.anyHandler());

    // WHEN trying to send a message
    final Future<ProtonDelivery> result = messageSender.send("device", "some payload", "application/text");

    // THEN the message has been sent
    // and the result is not completed yet
    verify(sender).send(any(Message.class), eq(handlerRef.get()));
    assertFalse(result.isComplete());

    // until it gets accepted by the peer
    final ProtonDelivery accepted = mock(ProtonDelivery.class);
    when(accepted.remotelySettled()).thenReturn(Boolean.TRUE);
    when(accepted.getRemoteState()).thenReturn(new Accepted());
    handlerRef.get().handle(accepted);

    assertTrue(result.succeeded());
}
 
Example #11
Source File: MappingAndDelegatingCommandHandlerTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies the behaviour of the <em>mapAndDelegateIncomingCommandMessage</em> method in a scenario where
 * the command shall get handled by another adapter instance.
 */
@Test
public void testMapWithCommandHandlerOnAnotherInstance() {
    final String deviceId = "4711";

    // GIVEN a deviceId commandHandler registered for another adapter instance (not the local one)
    final String otherAdapterInstance = "otherAdapterInstance";
    when(commandTargetMapper.getTargetGatewayAndAdapterInstance(anyString(), anyString(), any()))
            .thenReturn(Future.succeededFuture(createTargetAdapterInstanceJson(deviceId, otherAdapterInstance)));

    // AND an ACCEPTED result when sending the command message to another adapter instance
    final ProtonDelivery sendMsgDeliveryUpdate = mock(ProtonDelivery.class);
    when(sendMsgDeliveryUpdate.getRemoteState()).thenReturn(new Accepted());
    when(sendMsgDeliveryUpdate.remotelySettled()).thenReturn(true);
    final AtomicReference<Message> delegatedMessageRef = new AtomicReference<>();
    when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenAnswer(invocation -> {
        delegatedMessageRef.set(invocation.getArgument(0));
        final Handler<ProtonDelivery> dispositionHandler = invocation.getArgument(1);
        dispositionHandler.handle(sendMsgDeliveryUpdate);
        return mock(ProtonDelivery.class);
    });

    // register local command handler - that shall not get used
    final AtomicReference<CommandContext> localHandlerCmdContextRef = new AtomicReference<>();
    adapterInstanceCommandHandler.putDeviceSpecificCommandHandler(Constants.DEFAULT_TENANT, deviceId, null, localHandlerCmdContextRef::set);

    // WHEN mapping and delegating the command message
    final Message message = getValidCommandMessage(deviceId);
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    mappingAndDelegatingCommandHandler.mapAndDelegateIncomingCommandMessage(Constants.DEFAULT_TENANT, delivery, message);

    // THEN the delivery gets ACCEPTED as well
    verify(delivery).disposition(any(Accepted.class), eq(true));
    assertThat(localHandlerCmdContextRef.get()).isNull();
    final Message delegatedMessage = delegatedMessageRef.get();
    assertThat(delegatedMessage).isNotNull();
    assertThat(delegatedMessage.getAddress()).isEqualTo(String.format("%s/%s/%s",
            CommandConstants.COMMAND_ENDPOINT, Constants.DEFAULT_TENANT, deviceId));
}
 
Example #12
Source File: AmqpConsumer.java    From qpid-jms with Apache License 2.0 5 votes vote down vote up
private void handleAccepted(JmsInboundMessageDispatch envelope, Delivery delivery) {
    LOG.debug("Accepted Ack of message: {}", envelope);
    if (!delivery.remotelySettled()) {
        if (session.isTransacted() && !getResourceInfo().isBrowser()) {

            if (session.isTransactionFailed()) {
                LOG.trace("Skipping ack of message {} in failed transaction.", envelope);
                return;
            }

            Binary txnId = session.getTransactionContext().getAmqpTransactionId();
            if (txnId != null) {
                delivery.disposition(session.getTransactionContext().getTxnAcceptState());
                delivery.settle();
                session.getTransactionContext().registerTxConsumer(this);
            }
        } else {
            delivery.disposition(Accepted.getInstance());
            delivery.settle();
        }
    } else {
        delivery.settle();
    }

    if (envelope.isDelivered()) {
        deliveredCount--;
    }
    dispatchedCount--;
}
 
Example #13
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter signals successful forwarding of a one-way command
 * back to the sender of the command.
 */
@Test
public void testOneWayCommandAccepted() {

    final ProtonDelivery successfulDelivery = mock(ProtonDelivery.class);
    when(successfulDelivery.remotelySettled()).thenReturn(true);
    when(successfulDelivery.getRemoteState()).thenReturn(new Accepted());
    testOneWayCommandOutcome(successfulDelivery, Accepted.class, ProcessingOutcome.FORWARDED);
}
 
Example #14
Source File: CommandAndControlAmqpIT.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private ProtonMessageHandler createCommandConsumer(final VertxTestContext ctx, final ProtonReceiver cmdReceiver,
        final ProtonSender cmdResponseSender) {

    return (delivery, msg) -> {
        ctx.verify(() -> {
            assertThat(msg.getReplyTo()).isNotNull();
            assertThat(msg.getSubject()).isNotNull();
            assertThat(msg.getCorrelationId()).isNotNull();
        });
        final String command = msg.getSubject();
        final Object correlationId = msg.getCorrelationId();
        log.debug("received command [name: {}, reply-to: {}, correlation-id: {}]", command, msg.getReplyTo(), correlationId);
        ProtonHelper.accepted(delivery, true);
        cmdReceiver.flow(1);
        // send response
        final Message commandResponse = ProtonHelper.message(command + " ok");
        commandResponse.setAddress(msg.getReplyTo());
        commandResponse.setCorrelationId(correlationId);
        commandResponse.setContentType("text/plain");
        MessageHelper.addProperty(commandResponse, MessageHelper.APP_PROPERTY_STATUS, HttpURLConnection.HTTP_OK);
        log.debug("sending response [to: {}, correlation-id: {}]", commandResponse.getAddress(), commandResponse.getCorrelationId());
        cmdResponseSender.send(commandResponse, updatedDelivery -> {
            if (!Accepted.class.isInstance(updatedDelivery.getRemoteState())) {
                log.error("AMQP adapter did not accept command response [remote state: {}]",
                        updatedDelivery.getRemoteState().getClass().getSimpleName());
            }
        });
    };
}
 
Example #15
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the endpoint rejects request messages for operations the client
 * is not authorized to invoke.
 */
@SuppressWarnings("unchecked")
@Test
public void testHandleMessageSendsResponseForUnauthorizedRequests() {

    final Message msg = ProtonHelper.message();
    msg.setSubject("unauthorized");
    msg.setReplyTo(REPLY_RESOURCE.toString());
    msg.setCorrelationId(UUID.randomUUID().toString());
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final AuthorizationService authService = mock(AuthorizationService.class);
    when(authService.isAuthorized(any(HonoUser.class), any(ResourceIdentifier.class), anyString())).thenReturn(Future.succeededFuture(Boolean.FALSE));
    final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true);
    endpoint.setAuthorizationService(authService);
    endpoint.onLinkAttach(connection, sender, REPLY_RESOURCE);

    // WHEN a request for an operation is received that the client is not authorized to invoke
    endpoint.handleRequestMessage(connection, receiver, resource, delivery, msg);

    // THEN the message is accepted
    final ArgumentCaptor<DeliveryState> deliveryState = ArgumentCaptor.forClass(DeliveryState.class);
    verify(delivery).disposition(deliveryState.capture(), eq(Boolean.TRUE));
    assertThat(deliveryState.getValue()).isInstanceOf(Accepted.class);
    verify(receiver, never()).close();
    verify(authService).isAuthorized(Constants.PRINCIPAL_ANONYMOUS, resource, "unauthorized");
    // but not forwarded to the service instance
    verify(eventBus, never()).request(anyString(), any(), any(DeliveryOptions.class), any(Handler.class));
    // and a response is sent to the client with status 403
    verify(sender).send(argThat(m -> hasStatusCode(m, HttpURLConnection.HTTP_FORBIDDEN)));
}
 
Example #16
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the endpoint returns a response with status code 400
 * for a request that contains malformed payload. 
 */
@SuppressWarnings("unchecked")
@Test
public void testHandleMessageSendsResponseForMalformedPayload() {

    final Message msg = ProtonHelper.message();
    msg.setSubject("get");
    msg.setReplyTo(REPLY_RESOURCE.toString());
    msg.setCorrelationId(UUID.randomUUID().toString());
    msg.setBody(new Data(new Binary(new byte[] { 0x01, 0x02, 0x03 })));

    final ProtonDelivery delivery = mock(ProtonDelivery.class);

    final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true);
    endpoint.onLinkAttach(connection, sender, REPLY_RESOURCE);

    // WHEN a request for an operation is received that the client is authorized to invoke
    endpoint.handleRequestMessage(connection, receiver, resource, delivery, msg);

    // THEN then the message is accepted
    verify(delivery).disposition(argThat(d -> d instanceof Accepted), eq(Boolean.TRUE));

    // and not forwarded to the service instance
    verify(eventBus, never()).request(eq(EVENT_BUS_ADDRESS), any(JsonObject.class), any(DeliveryOptions.class), any(Handler.class));

    // and a response with the expected status is sent to the client
    verify(sender).send(argThat(m -> hasStatusCode(m, HttpURLConnection.HTTP_BAD_REQUEST)));
    verify(receiver).flow(1);
}
 
Example #17
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the endpoint processes request messages for operations the client
 * is authorized to invoke.
 */
@SuppressWarnings("unchecked")
@Test
public void testHandleMessageProcessesAuthorizedRequests() {

    final Message msg = ProtonHelper.message();
    msg.setSubject("get");
    msg.setReplyTo(REPLY_RESOURCE.toString());
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final AuthorizationService authService = mock(AuthorizationService.class);
    when(authService.isAuthorized(any(HonoUser.class), any(ResourceIdentifier.class), anyString())).thenReturn(Future.succeededFuture(Boolean.TRUE));

    final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true);
    endpoint.setAuthorizationService(authService);
    endpoint.onLinkAttach(connection, sender, REPLY_RESOURCE);

    // WHEN a request for an operation is received that the client is authorized to invoke
    endpoint.handleRequestMessage(connection, receiver, resource, delivery, msg);

    // THEN then the message gets processed
    final ArgumentCaptor<DeliveryState> deliveryState = ArgumentCaptor.forClass(DeliveryState.class);
    verify(delivery).disposition(deliveryState.capture(), eq(Boolean.TRUE));
    assertThat(deliveryState.getValue()).isInstanceOf(Accepted.class);
    verify(receiver, never()).close();
    verify(authService).isAuthorized(Constants.PRINCIPAL_ANONYMOUS, resource, "get");
    // and forwarded to the service instance
    final ArgumentCaptor<Handler<AsyncResult<io.vertx.core.eventbus.Message<Object>>>> replyHandler = ArgumentCaptor.forClass(Handler.class);
    verify(eventBus).request(eq(EVENT_BUS_ADDRESS), any(JsonObject.class), any(DeliveryOptions.class), replyHandler.capture());

    // WHEN the service implementation sends the response
    final EventBusMessage response = EventBusMessage.forStatusCode(HttpURLConnection.HTTP_ACCEPTED);
    final io.vertx.core.eventbus.Message<Object> reply = mock(io.vertx.core.eventbus.Message.class);
    when(reply.body()).thenReturn(response.toJson());
    replyHandler.getValue().handle(Future.succeededFuture(reply));

    // THEN the response is sent to the client
    verify(sender).send(any(Message.class));
    verify(receiver).flow(1);
}
 
Example #18
Source File: Sender.java    From enmasse with Apache License 2.0 5 votes vote down vote up
private void sendNext(ProtonConnection connection, ProtonSender sender) {

        Message message;
        if (messageQueue.hasNext() && (message = messageQueue.next()) != null) {
            if (sender.getQoS().equals(ProtonQoS.AT_MOST_ONCE)) {
                sender.send(message);
                numSent.incrementAndGet();
                if (predicate.test(message)) {
                    resultPromise.complete(numSent.get());
                } else {
                    vertx.runOnContext(id -> sendNext(connection, sender));
                }
            } else {
                sender.send(message, protonDelivery -> {
                    if (protonDelivery.getRemoteState().equals(Accepted.getInstance())) {
                        numSent.incrementAndGet();
                        if (predicate.test(message)) {
                            resultPromise.complete(numSent.get());
                            connection.close();
                        } else {
                            sendNext(connection, sender);
                        }
                    } else {
                        resultPromise.completeExceptionally(new IllegalStateException("Message not accepted (remote state: " + protonDelivery.getRemoteState() + ") after " + numSent.get() + " messages sent"));
                        connectPromise.completeExceptionally(new IllegalStateException("Message not accepted (remote state: " + protonDelivery.getRemoteState() + ") after " + numSent.get() + " messages sent"));
                        connection.close();
                    }
                });
            }
        } else {
            if (predicate.test(null)) {
                resultPromise.complete(numSent.get());
            } else {
                resultPromise.completeExceptionally(new RuntimeException("No more messages to send after + " + numSent.get() + " messages sent"));
                connectPromise.completeExceptionally(new RuntimeException("No more messages to send after + " + numSent.get() + " messages sent"));
            }
            connection.close();
        }
    }
 
Example #19
Source File: CommandContext.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Settles the command message with the given {@code DeliveryState} outcome.
 * <p>
 * This method also finishes the OpenTracing span returned by
 * {@link #getCurrentSpan()}.
 *
 * @param deliveryState The deliveryState to set in the disposition frame.
 * @throws NullPointerException if deliveryState is {@code null}.
 */
public void disposition(final DeliveryState deliveryState) {

    Objects.requireNonNull(deliveryState);
    delivery.disposition(deliveryState, true);
    if (Accepted.class.isInstance(deliveryState)) {
        LOG.trace("accepted command message [{}]", getCommand());
        currentSpan.log("accepted command for device");

    } else if (Released.class.isInstance(deliveryState)) {
        LOG.debug("released command message [{}]", getCommand());
        TracingHelper.logError(currentSpan, "released command for device");

    } else if (Modified.class.isInstance(deliveryState)) {
        final Modified modified = (Modified) deliveryState;
        LOG.debug("modified command message [{}]", getCommand());
        TracingHelper.logError(currentSpan, "modified command for device"
                + (Boolean.TRUE.equals(modified.getDeliveryFailed()) ? "; delivery failed" : "")
                + (Boolean.TRUE.equals(modified.getUndeliverableHere()) ? "; undeliverable here" : ""));

    } else if (Rejected.class.isInstance(deliveryState)) {
        final ErrorCondition errorCondition = ((Rejected) deliveryState).getError();
        LOG.debug("rejected command message [error: {}, command: {}]", errorCondition, getCommand());
        TracingHelper.logError(currentSpan, "rejected command for device"
                + ((errorCondition != null && errorCondition.getDescription() != null) ? "; error: " + errorCondition.getDescription() : ""));
    } else {
        LOG.warn("unexpected delivery state [{}] when settling command message [{}]", deliveryState, getCommand());
        TracingHelper.logError(currentSpan, "unexpected delivery state: " + deliveryState);
    }
    currentSpan.finish();
}
 
Example #20
Source File: FastPathDispositionType.java    From qpid-proton-j with Apache License 2.0 5 votes vote down vote up
private byte deduceEncodingCode(Disposition value, int elementCount) {
    if (value.getState() == null) {
        return EncodingCodes.LIST8;
    } else if (value.getState() == Accepted.getInstance() || value.getState() == Released.getInstance()) {
        return EncodingCodes.LIST8;
    } else {
        return EncodingCodes.LIST32;
    }
}
 
Example #21
Source File: Benchmark.java    From qpid-proton-j with Apache License 2.0 5 votes vote down vote up
private void benchmarkDisposition() throws IOException {
    Disposition disposition = new Disposition();
    disposition.setRole(Role.RECEIVER);
    disposition.setSettled(true);
    disposition.setState(Accepted.getInstance());
    disposition.setFirst(UnsignedInteger.valueOf(2));
    disposition.setLast(UnsignedInteger.valueOf(2));

    resultSet.start();
    for (int i = 0; i < ITERATIONS; i++) {
        outputBuf.byteBuffer().clear();
        encoder.writeObject(disposition);
    }
    resultSet.encodesComplete();

    CompositeReadableBuffer inputBuf = convertToComposite(outputBuf);
    decoder.setBuffer(inputBuf);

    resultSet.start();
    for (int i = 0; i < ITERATIONS; i++) {
        decoder.readObject();
        inputBuf.flip();
    }
    resultSet.decodesComplete();

    time("Disposition", resultSet);
}
 
Example #22
Source File: DispositionBenchmark.java    From qpid-proton-j with Apache License 2.0 5 votes vote down vote up
private void initDisposition()
{
    disposition = new Disposition();
    disposition.setRole(Role.RECEIVER);
    disposition.setSettled(true);
    disposition.setState(Accepted.getInstance());
    disposition.setFirst(UnsignedInteger.valueOf(2));
    disposition.setLast(UnsignedInteger.valueOf(2));
}
 
Example #23
Source File: AmqpFlowControlFailTest.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
@Parameterized.Parameters(name = "useModified={0}")
public static Collection<Object[]> parameters() {
   return Arrays.asList(new Object[][] {
         {true, new Symbol[]{Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL}, "failure at remote"},
         {true, new Symbol[]{Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL}, "[condition = amqp:resource-limit-exceeded]"},
         {false, new Symbol[]{Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL}, "[condition = amqp:resource-limit-exceeded]"},
         {false, new Symbol[]{}, "[condition = amqp:resource-limit-exceeded]"}
   });
}
 
Example #24
Source File: AmqpReceiver.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
protected void configureSource(Source source) {
   Map<Symbol, DescribedType> filters = new HashMap<>();
   Symbol[] outcomes = new Symbol[] {Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL};

   if (getSubscriptionName() != null && !getSubscriptionName().isEmpty()) {
      source.setExpiryPolicy(TerminusExpiryPolicy.NEVER);
      source.setDurable(TerminusDurability.UNSETTLED_STATE);
      source.setDistributionMode(COPY);
   } else {
      source.setDurable(TerminusDurability.NONE);
      source.setExpiryPolicy(TerminusExpiryPolicy.LINK_DETACH);
   }

   source.setOutcomes(outcomes);

   Modified modified = new Modified();
   modified.setDeliveryFailed(true);
   modified.setUndeliverableHere(false);

   source.setDefaultOutcome(modified);

   if (isNoLocal()) {
      filters.put(NO_LOCAL_NAME, AmqpNoLocalFilter.NO_LOCAL);
   }

   if (getSelector() != null && !getSelector().trim().equals("")) {
      filters.put(JMS_SELECTOR_NAME, new AmqpJmsSelectorFilter(getSelector()));
   }

   if (!filters.isEmpty()) {
      source.setFilter(filters);
   }
}
 
Example #25
Source File: ProtonServerSenderContext.java    From activemq-artemis with Apache License 2.0 5 votes vote down vote up
@Override
public void onMessage(Delivery delivery) throws ActiveMQAMQPException {
   if (closed) {
      return;
   }

   OperationContext oldContext = sessionSPI.recoverContext();

   try {
      Message message = ((MessageReference) delivery.getContext()).getMessage();
      DeliveryState remoteState = delivery.getRemoteState();

      if (remoteState != null && remoteState.getType() == DeliveryStateType.Accepted) {
         // this can happen in the twice ack mode, that is the receiver accepts and settles separately
         // acking again would show an exception but would have no negative effect but best to handle anyway.
         if (!delivery.isSettled()) {
            // we have to individual ack as we can't guarantee we will get the delivery updates
            // (including acks) in order from dealer, a performance hit but a must
            try {
               sessionSPI.ack(null, brokerConsumer, message);
            } catch (Exception e) {
               log.warn(e.toString(), e);
               throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.errorAcknowledgingMessage(message.toString(), e.getMessage());
            }

            delivery.settle();
         }
      } else {
         handleExtendedDeliveryOutcomes(message, delivery, remoteState);
      }

      if (!preSettle) {
         protonSession.replaceTag(delivery.getTag());
      }
   } finally {
      sessionSPI.afterIO(connectionFlusher);
      sessionSPI.resetContext(oldContext);
   }
}
 
Example #26
Source File: ProtonSessionImpl.java    From vertx-proton with Apache License 2.0 5 votes vote down vote up
@Override
public ProtonReceiver createReceiver(String address, ProtonLinkOptions receiverOptions) {
  Receiver receiver = session.receiver(getOrCreateLinkName(receiverOptions));

  Symbol[] outcomes = new Symbol[] { Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL,
      Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL };

  Source source = new Source();
  source.setAddress(address);
  source.setOutcomes(outcomes);
  source.setDefaultOutcome(Released.getInstance());
  if(receiverOptions.isDynamic()) {
    source.setDynamic(true);
  }

  Target target = new Target();

  receiver.setSource(source);
  receiver.setTarget(target);

  ProtonReceiverImpl r = new ProtonReceiverImpl(receiver);
  r.openHandler((result) -> {
    LOG.trace("Receiver open completed");
  });
  r.closeHandler((result) -> {
    if (result.succeeded()) {
      LOG.trace("Receiver closed");
    } else {
      LOG.warn("Receiver closed with error", result.cause());
    }
  });

  // Default to at-least-once
  r.setQoS(ProtonQoS.AT_LEAST_ONCE);

  return r;
}
 
Example #27
Source File: ProtonSessionImpl.java    From vertx-proton with Apache License 2.0 5 votes vote down vote up
@Override
public ProtonSender createSender(String address, ProtonLinkOptions senderOptions) {
  Sender sender = session.sender(getOrCreateLinkName(senderOptions));

  Symbol[] outcomes = new Symbol[] { Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL,
      Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL };
  Source source = new Source();
  source.setOutcomes(outcomes);

  Target target = new Target();
  target.setAddress(address);
  if(senderOptions.isDynamic()) {
    target.setDynamic(true);
  }

  sender.setSource(source);
  sender.setTarget(target);

  ProtonSenderImpl s = new ProtonSenderImpl(sender);
  if (address == null) {
    s.setAnonymousSender(true);
  }

  s.openHandler((result) -> {
    LOG.trace("Sender open completed");
  });
  s.closeHandler((result) -> {
    if (result.succeeded()) {
      LOG.trace("Sender closed");
    } else {
      LOG.warn("Sender closed with error", result.cause());
    }
  });

  // Default to at-least-once
  s.setQoS(ProtonQoS.AT_LEAST_ONCE);

  return s;
}
 
Example #28
Source File: AmqpProducerBuilder.java    From qpid-jms with Apache License 2.0 5 votes vote down vote up
@Override
protected Sender createEndpoint(JmsProducerInfo resourceInfo) {
    JmsDestination destination = resourceInfo.getDestination();
    AmqpConnection connection = getParent().getConnection();

    String targetAddress = AmqpDestinationHelper.getDestinationAddress(destination, connection);

    Symbol[] outcomes = new Symbol[]{ Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL };
    String sourceAddress = resourceInfo.getId().toString();
    Source source = new Source();
    source.setAddress(sourceAddress);
    source.setOutcomes(outcomes);
    // TODO: default outcome. Accepted normally, Rejected for transaction controller?

    Target target = new Target();
    target.setAddress(targetAddress);
    Symbol typeCapability =  AmqpDestinationHelper.toTypeCapability(destination);
    if (typeCapability != null) {
        target.setCapabilities(typeCapability);
    }

    String senderName = "qpid-jms:sender:" + sourceAddress + ":" + targetAddress;

    Sender sender = getParent().getEndpoint().sender(senderName);
    sender.setSource(source);
    sender.setTarget(target);
    if (resourceInfo.isPresettle()) {
        sender.setSenderSettleMode(SenderSettleMode.SETTLED);
    } else {
        sender.setSenderSettleMode(SenderSettleMode.UNSETTLED);
    }
    sender.setReceiverSettleMode(ReceiverSettleMode.FIRST);

    if (!connection.getProperties().isDelayedDeliverySupported()) {
        validateDelayedDeliveryLinkCapability = true;
        sender.setDesiredCapabilities(new Symbol[] { AmqpSupport.DELAYED_DELIVERY });
    }

    return sender;
}
 
Example #29
Source File: FastPathDispositionType.java    From qpid-proton-j with Apache License 2.0 5 votes vote down vote up
private void writeElement(Disposition disposition, int index) {
    switch (index) {
        case 0:
            getEncoder().writeBoolean(disposition.getRole().getValue());
            break;
        case 1:
            getEncoder().writeUnsignedInteger(disposition.getFirst());
            break;
        case 2:
            getEncoder().writeUnsignedInteger(disposition.getLast());
            break;
        case 3:
            getEncoder().writeBoolean(disposition.getSettled());
            break;
        case 4:
            if (Accepted.getInstance().equals(disposition.getState())) {
                getEncoder().getBuffer().put(ACCEPTED_ENCODED_BYTES, 0, ACCEPTED_ENCODED_BYTES.length);
            } else {
                getEncoder().writeObject(disposition.getState());
            }
            break;
        case 5:
            getEncoder().writeBoolean(disposition.getBatchable());
            break;
        default:
            throw new IllegalArgumentException("Unknown Disposition value index: " + index);
    }
}
 
Example #30
Source File: ProtonServerReceiverContextTest.java    From activemq-artemis with Apache License 2.0 4 votes vote down vote up
@Test
public void addressFull_SourceDoesNotSupportModified() throws Exception {
   doOnMessageWithDeliveryException(asList(Rejected.DESCRIPTOR_SYMBOL, Accepted.DESCRIPTOR_SYMBOL), null, new ActiveMQAddressFullException(), Rejected.class);
}