io.vertx.proton.ProtonReceiver Java Examples

The following examples show how to use io.vertx.proton.ProtonReceiver. 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: ProtonReceiverImplTest.java    From vertx-proton with Apache License 2.0 6 votes vote down vote up
@Test
public void testDrainWithExistingDrainOutstandingThrowsISE() {
  ProtonConnectionImpl conn = new ProtonConnectionImpl(null, null, null);
  conn.bindClient(null, Mockito.mock(NetSocketInternal.class), null, new ProtonTransportOptions());
  conn.fireDisconnect();
  ProtonReceiver receiver = conn.createReceiver("address");

  AtomicBoolean drain1complete = new AtomicBoolean();

  receiver.setPrefetch(0);
  receiver.flow(1);
  receiver.drain(0, h -> {
    drain1complete.set(true);
  });

  try {
    receiver.drain(0, h2-> {});
    fail("should have thrown due to outstanding drain operation");
  } catch (IllegalStateException ise) {
    // Expected
    assertFalse("first drain should not have been completed", drain1complete.get());
  }
}
 
Example #2
Source File: ProtocolAdapterCommandConsumerFactoryImpl.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private Future<ProtonReceiver> createAdapterSpecificConsumer() {
    log.trace("creating new adapter instance command consumer");
    final String adapterInstanceConsumerAddress = CommandConstants.INTERNAL_COMMAND_ENDPOINT + "/"
            + adapterInstanceId;
    return connection.createReceiver(
            adapterInstanceConsumerAddress,
            ProtonQoS.AT_LEAST_ONCE,
            (delivery, msg) -> adapterInstanceCommandHandler.handleCommandMessage(msg, delivery),
            connection.getConfig().getInitialCredits(),
            false, // no auto-accept
            sourceAddress -> { // remote close hook
                log.debug("command receiver link closed remotely");
                invokeRecreateConsumersWithDelay();
            }).map(receiver -> {
                log.debug("successfully created adapter specific command consumer");
                adapterSpecificConsumer = receiver;
                return receiver;
            }).recover(t -> {
                log.error("failed to create adapter specific command consumer", t);
                return Future.failedFuture(t);
            });
}
 
Example #3
Source File: VertxBasedAmqpProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the AMQP Adapter rejects (closes) AMQP links that contains a target address.
 */
@Test
public void testAdapterAcceptsAnonymousRelayReceiverOnly() {
    // GIVEN an AMQP adapter with a configured server.
    final ProtonServer server = getAmqpServer();
    final VertxBasedAmqpProtocolAdapter adapter = getAdapter(server);

    // WHEN the adapter receives a link that contains a target address
    final ResourceIdentifier targetAddress = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, TEST_DEVICE);
    final ProtonReceiver link = getReceiver(ProtonQoS.AT_LEAST_ONCE, getTarget(targetAddress));

    adapter.handleRemoteReceiverOpen(getConnection(null), link);

    // THEN the adapter closes the link.
    verify(link).close();
}
 
Example #4
Source File: CommandAndControlAmqpIT.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private Future<ProtonReceiver> subscribeToCommands(
        final AmqpCommandEndpointConfiguration endpointConfig,
        final String tenantId,
        final String commandTargetDeviceId) {

    final Promise<ProtonReceiver> result = Promise.promise();
    context.runOnContext(go -> {
        final ProtonReceiver recv = connection.createReceiver(endpointConfig.getSubscriptionAddress(tenantId, commandTargetDeviceId));
        recv.setAutoAccept(false);
        recv.setPrefetch(0);
        recv.setQoS(ProtonQoS.AT_LEAST_ONCE);
        recv.openHandler(result);
        recv.open();
    });
    return result.future().map(commandConsumer -> {
        log.debug("created command consumer [{}]", commandConsumer.getSource().getAddress());
        return commandConsumer;
    });
}
 
Example #5
Source File: DeviceConnectionClientImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sets up the fixture.
 */
@BeforeEach
public void setUp() {

    final SpanContext spanContext = mock(SpanContext.class);

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

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

    final Vertx vertx = mock(Vertx.class);
    final ProtonReceiver receiver = HonoClientUnitTestHelper.mockProtonReceiver();
    sender = HonoClientUnitTestHelper.mockProtonSender();

    final RequestResponseClientConfigProperties config = new RequestResponseClientConfigProperties();
    final HonoConnection connection = HonoClientUnitTestHelper.mockHonoConnection(vertx, config);
    when(connection.getTracer()).thenReturn(tracer);

    client = new DeviceConnectionClientImpl(connection, Constants.DEFAULT_TENANT, sender, receiver);
}
 
Example #6
Source File: CommandAndControlAmqpIT.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private ProtonMessageHandler createRejectingCommandConsumer(final VertxTestContext ctx, final ProtonReceiver receiver) {
    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);
        final Rejected rejected = new Rejected();
        rejected.setError(new ErrorCondition(Constants.AMQP_BAD_REQUEST, REJECTED_COMMAND_ERROR_MESSAGE));
        delivery.disposition(rejected, true);
        receiver.flow(1);
    };
}
 
Example #7
Source File: TenantClientImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sets up the fixture.
 */
@SuppressWarnings("unchecked")
@BeforeEach
public void setUp() {

    final SpanContext spanContext = mock(SpanContext.class);

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

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

    vertx = mock(Vertx.class);
    final ProtonReceiver receiver = HonoClientUnitTestHelper.mockProtonReceiver();
    sender = HonoClientUnitTestHelper.mockProtonSender();

    final RequestResponseClientConfigProperties config = new RequestResponseClientConfigProperties();
    connection = HonoClientUnitTestHelper.mockHonoConnection(vertx, config);
    when(connection.getTracer()).thenReturn(tracer);

    cache = mock(ExpiringValueCache.class);
    client = new TenantClientImpl(connection, sender, receiver);
}
 
Example #8
Source File: HonoConnectionImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the attempt to create a receiver fails with a
 * {@code ServerErrorException} if the remote peer doesn't
 * send its attach frame in time.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateReceiverFailsOnTimeout(final VertxTestContext ctx) {

    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.isOpen()).thenReturn(Boolean.TRUE);
    when(con.createReceiver(anyString())).thenReturn(receiver);
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> honoConnection.createReceiver(
            "source", ProtonQoS.AT_LEAST_ONCE, (delivery, msg) -> {}, remoteCloseHook))
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> {
                assertThat(((ServerErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE);
                verify(receiver).open();
                verify(receiver).close();
                verify(remoteCloseHook, never()).handle(anyString());
            });
            ctx.completeNow();
        }));
}
 
Example #9
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Initializes common fixture.
 */
@BeforeEach
public void setUp() {

    connection = mock(ProtonConnection.class);
    vertx = mock(Vertx.class);
    eventBus = mock(EventBus.class);
    receiver = mock(ProtonReceiver.class);
    when(receiver.handler(any())).thenReturn(receiver);
    when(receiver.closeHandler(any())).thenReturn(receiver);
    when(receiver.setAutoAccept(any(Boolean.class))).thenReturn(receiver);
    when(receiver.setPrefetch(any(Integer.class))).thenReturn(receiver);
    when(receiver.setQoS(any(ProtonQoS.class))).thenReturn(receiver);

    when(vertx.eventBus()).thenReturn(eventBus);

    final ProtonSession session = mock(ProtonSession.class);
    when(session.getConnection()).thenReturn(connection);
    sender = mock(ProtonSender.class);
    when(sender.getName()).thenReturn("mocked sender");
    when(sender.isOpen()).thenReturn(Boolean.TRUE);
    when(sender.getSession()).thenReturn(session);
}
 
Example #10
Source File: AmqpServiceBaseTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the service notifies a registered endpoint about a client
 * that has established a link.
 */
@Test
public void testHandleReceiverOpenForwardsToEndpoint() {

    // GIVEN a server with an endpoint
    final ResourceIdentifier targetAddress = ResourceIdentifier.from(ENDPOINT, Constants.DEFAULT_TENANT, null);
    final AmqpEndpoint endpoint = mock(AmqpEndpoint.class);
    when(endpoint.getName()).thenReturn(ENDPOINT);
    final AuthorizationService authService = mock(AuthorizationService.class);
    when(authService.isAuthorized(Constants.PRINCIPAL_ANONYMOUS, targetAddress, Activity.WRITE))
        .thenReturn(Future.succeededFuture(Boolean.TRUE));
    final AmqpServiceBase<ServiceConfigProperties> server = createServer(endpoint);
    server.setAuthorizationService(authService);

    // WHEN a client connects to the server using this endpoint
    final Target target = getTarget(targetAddress);
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.getRemoteTarget()).thenReturn(target);
    when(receiver.attachments()).thenReturn(mock(Record.class));
    server.handleReceiverOpen(newConnection(Constants.PRINCIPAL_ANONYMOUS), receiver);

    // THEN the server delegates link establishment to the endpoint
    verify(endpoint).onLinkAttach(any(ProtonConnection.class), eq(receiver), eq(targetAddress));
}
 
Example #11
Source File: AmqpServiceBaseTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the service rejects sender links on resources that
 * the client is not authorized to write to.
 */
@Test
public void testHandleReceiverOpenRejectsUnauthorizedClient() {

    // GIVEN a server with a endpoint
    final ResourceIdentifier restrictedTargetAddress = ResourceIdentifier.from(ENDPOINT, "RESTRICTED_TENANT", null);
    final AmqpEndpoint endpoint = mock(AmqpEndpoint.class);
    when(endpoint.getName()).thenReturn(ENDPOINT);
    final AuthorizationService authService = mock(AuthorizationService.class);
    when(authService.isAuthorized(Constants.PRINCIPAL_ANONYMOUS, restrictedTargetAddress, Activity.WRITE))
        .thenReturn(Future.succeededFuture(Boolean.FALSE));
    final AmqpServiceBase<ServiceConfigProperties> server = createServer(endpoint);
    server.setAuthorizationService(authService);

    // WHEN a client connects to the server using a address for a tenant it is not authorized to write to
    final Target target = getTarget(restrictedTargetAddress);
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.getRemoteTarget()).thenReturn(target);
    when(receiver.setCondition(any())).thenReturn(receiver);
    server.handleReceiverOpen(newConnection(Constants.PRINCIPAL_ANONYMOUS), receiver);

    // THEN the server closes the link with the client
    verify(receiver).close();
}
 
Example #12
Source File: RegistrationClientImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sets up the fixture.
 */
@SuppressWarnings("unchecked")
@BeforeEach
public void setUp() {

    final SpanContext spanContext = mock(SpanContext.class);

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

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

    vertx = mock(Vertx.class);
    final ProtonReceiver receiver = HonoClientUnitTestHelper.mockProtonReceiver();
    sender = HonoClientUnitTestHelper.mockProtonSender();

    cache = mock(ExpiringValueCache.class);
    final RequestResponseClientConfigProperties config = new RequestResponseClientConfigProperties();
    connection = HonoClientUnitTestHelper.mockHonoConnection(vertx, config);
    when(connection.getTracer()).thenReturn(tracer);

    client = new RegistrationClientImpl(connection, "tenant", sender, receiver);
}
 
Example #13
Source File: AbstractRequestResponseClientTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private AbstractRequestResponseClient<SimpleRequestResponseResult> getClient(final String tenant, final ProtonSender sender, final ProtonReceiver receiver) {

        final HonoConnection connection = HonoClientUnitTestHelper.mockHonoConnection(vertx);
        return new AbstractRequestResponseClient<SimpleRequestResponseResult>(connection, tenant, sender, receiver) {

            @Override
            protected String getName() {
                return "peer";
            }

            @Override
            protected String createMessageId() {
                return MESSAGE_ID;
            }

            @Override
            protected SimpleRequestResponseResult getResult(
                    final int status,
                    final String contentType,
                    final Buffer payload,
                    final CacheDirective cacheDirective,
                    final ApplicationProperties applicationProperties) {
                return SimpleRequestResponseResult.from(status, payload, cacheDirective, applicationProperties);
            }
        };
    }
 
Example #14
Source File: AmqpBridge.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
/**
 * Handler for attached link by a remote sender
 *
 * @param connection connection which the receiver link belong to
 * @param receiver receiver link created by the underlying Proton library
 *                 by which handling communication with remote sender
 */
private void processOpenReceiver(ProtonConnection connection, ProtonReceiver receiver) {

    log.info("Remote sender attached {}", receiver.getName());

    ConnectionEndpoint endpoint = this.endpoints.get(connection);
    SourceBridgeEndpoint source = endpoint.getSource();
    // the source endpoint is only one, handling more AMQP receiver links internally
    if (source == null) {
        // TODO: the AMQP client should be able to specify the format during link attachment
        source = new AmqpSourceBridgeEndpoint<>(this.vertx, this.bridgeConfig,
                EmbeddedFormat.JSON, new StringSerializer(), new ByteArraySerializer());

        source.closeHandler(s -> {
            endpoint.setSource(null);
        });
        source.open();
        endpoint.setSource(source);
    }
    source.handle(new AmqpEndpoint(receiver));
}
 
Example #15
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 #16
Source File: HonoConnectionImplTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the attempt to create a receiver fails with a
 * {@code ServerErrorException} if the connection gets disconnected
 * before the remote peer has sent its attach frame. It is verified
 * that this is done before the link establishment timeout.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateReceiverFailsOnDisconnectBeforeOpen(final VertxTestContext ctx) {

    final long linkEstablishmentTimeout = 444L; // choose a distinct value here
    props.setLinkEstablishmentTimeout(linkEstablishmentTimeout);
    // don't run linkEstablishmentTimeout timer handler
    when(vertx.setTimer(eq(linkEstablishmentTimeout), VertxMockSupport.anyHandler())).thenAnswer(invocation -> 0L);

    final Source source = mock(Source.class);
    when(source.getAddress()).thenReturn("source/address");
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.isOpen()).thenReturn(Boolean.TRUE);
    when(receiver.getSource()).thenReturn(source);
    when(receiver.getRemoteSource()).thenReturn(source);
    when(con.createReceiver(anyString())).thenReturn(receiver);

    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> {
            // WHEN creating a receiver link with a close hook
            final Future<ProtonReceiver> result = honoConnection.createReceiver("source", ProtonQoS.AT_LEAST_ONCE,
                    mock(ProtonMessageHandler.class), remoteCloseHook);
            // THEN the result is not completed at first
            ctx.verify(() -> assertThat(result.isComplete()).isFalse());
            // WHEN the downstream connection fails
            connectionFactory.getDisconnectHandler().handle(con);
            return result;
        })
        // THEN the attempt is failed
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> assertThat(((ServerErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE));
            ctx.completeNow();
        }));
}
 
Example #17
Source File: AbstractTenantTimeoutRelatedClientFactoryTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private HonoConnection createConnection() {
    final Vertx vertx = Vertx.vertx();
    final HonoConnection connection = HonoClientUnitTestHelper.mockHonoConnection(vertx);
    when(connection.getVertx()).thenReturn(vertx);

    when(connection.isConnected()).thenReturn(Future.succeededFuture());
    when(connection.isConnected(anyLong())).thenReturn(Future.succeededFuture());

    final ProtonReceiver receiver = HonoClientUnitTestHelper.mockProtonReceiver();
    when(connection.createReceiver(anyString(), any(), any(), any())).thenReturn(Future.succeededFuture(receiver));
    final ProtonSender sender = HonoClientUnitTestHelper.mockProtonSender();
    when(connection.createSender(anyString(), any(), any())).thenReturn(Future.succeededFuture(sender));
    return connection;
}
 
Example #18
Source File: HonoClientUnitTestHelper.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a mocked Proton receiver which always returns {@code true} when its isOpen method is called.
 *
 * @return The mocked receiver.
 */
public static ProtonReceiver mockProtonReceiver() {

    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.isOpen()).thenReturn(Boolean.TRUE);

    return receiver;
}
 
Example #19
Source File: RegistrationClientImpl.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a new client for accessing the Device Registration service.
 *
 * @param connection The connection to Hono.
 * @param tenantId The identifier of the tenant for which the client should be created.
 * @param sender The AMQP link to use for sending requests to the service.
 * @param receiver The AMQP link to use for receiving responses from the service.
 */
protected RegistrationClientImpl(
        final HonoConnection connection,
        final String tenantId,
        final ProtonSender sender,
        final ProtonReceiver receiver) {

    super(connection, tenantId, sender, receiver);
}
 
Example #20
Source File: AbstractRequestResponseClient.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a request-response client for a sender and receiver link.
 *
 * @param connection The connection to the service.
 * @param tenantId The tenant that the client should be scoped to or {@code null} if the
 *                 client should not be scoped to a tenant.
 * @param sender The AMQP 1.0 link to use for sending requests to the peer.
 * @param receiver The AMQP 1.0 link to use for receiving responses from the peer.
 * @throws NullPointerException if any of the parameters other than tenant are {@code null}.
 */
protected AbstractRequestResponseClient(
        final HonoConnection connection,
        final String tenantId,
        final ProtonSender sender,
        final ProtonReceiver receiver) {

    this(connection, tenantId);
    this.sender = Objects.requireNonNull(sender);
    this.receiver = Objects.requireNonNull(receiver);
}
 
Example #21
Source File: CommandAndControlAmqpIT.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private void connectAndSubscribe(
        final VertxTestContext ctx,
        final String commandTargetDeviceId,
        final AmqpCommandEndpointConfiguration endpointConfig,
        final BiFunction<ProtonReceiver, ProtonSender, ProtonMessageHandler> commandConsumerFactory) throws InterruptedException {

    final VertxTestContext setup = new VertxTestContext();
    final Checkpoint notificationReceived = setup.checkpoint();

    connectToAdapter(tenantId, tenant, deviceId, password, () -> createEventConsumer(tenantId, msg -> {
        // expect empty notification with TTD -1
        ctx.verify(() -> assertThat(msg.getContentType()).isEqualTo(EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION));
        final TimeUntilDisconnectNotification notification = TimeUntilDisconnectNotification.fromMessage(msg).orElse(null);
        log.debug("received notification [{}]", notification);
        ctx.verify(() -> assertThat(notification).isNotNull());
        if (notification.getTtd() == -1) {
            notificationReceived.flag();
        }
    }))
    // use anonymous sender
    .compose(con -> createProducer(null))
    .compose(sender -> subscribeToCommands(endpointConfig, tenantId, commandTargetDeviceId)
        .map(recv -> {
            recv.handler(commandConsumerFactory.apply(recv, sender));
            recv.flow(50);
            return null;
        }))
    .onComplete(setup.completing());

    assertThat(setup.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
    if (setup.failed()) {
        ctx.failNow(setup.causeOfFailure());
    }
}
 
Example #22
Source File: ProtonReceiverImpl.java    From vertx-proton with Apache License 2.0 5 votes vote down vote up
@Override
public ProtonReceiver drain(long timeout, Handler<AsyncResult<Void>> completionHandler) {
  if (prefetch > 0) {
    throw new IllegalStateException("Manual credit management not available while prefetch is non-zero");
  }

  if (completionHandler == null) {
    throw new IllegalArgumentException("A completion handler must be provided");
  }

  if (drainCompleteHandler != null) {
    throw new IllegalStateException("A previous drain operation has not yet completed");
  }

  if ((getCredit() - getQueued()) <= 0) {
    // We have no remote credit
    if (getQueued() == 0) {
      // All the deliveries have been processed, drain is a no-op, nothing to do but complete.
      completionHandler.handle(Future.succeededFuture());
    } else {
        // There are still deliveries to process, wait for them to be.
        setDrainHandlerAndTimeoutTask(timeout, completionHandler);
    }
  } else {
    setDrainHandlerAndTimeoutTask(timeout, completionHandler);

    getReceiver().drain(0);
    flushConnection();
  }

  return this;
}
 
Example #23
Source File: CommandAndControlAmqpIT.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private ProtonMessageHandler createNotSendingDeliveryUpdateCommandConsumer(final VertxTestContext ctx,
        final ProtonReceiver receiver, final AtomicInteger receivedMessagesCounter) {
    return (delivery, msg) -> {
        receivedMessagesCounter.incrementAndGet();
        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);
        receiver.flow(1);
    };
}
 
Example #24
Source File: RequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a client's request to establish a link for sending service invocation requests.
 * <p>
 * Configure and check the receiver link of the endpoint.
 * The remote link of the receiver must not demand the AT_MOST_ONCE QoS (not supported).
 * The receiver link itself is configured with the AT_LEAST_ONCE QoS and grants the configured credits
 * ({@link ServiceConfigProperties#getReceiverLinkCredit()}) with autoAcknowledge.
 * <p>
 * Handling of request messages is delegated to
 * {@link #handleRequestMessage(ProtonConnection, ProtonReceiver, ResourceIdentifier, ProtonDelivery, Message)}.
 *
 * @param con The AMQP connection that the link is part of.
 * @param receiver The ProtonReceiver that has already been created for this endpoint.
 * @param targetAddress The resource identifier for this endpoint (see {@link ResourceIdentifier} for details).
 */
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonReceiver receiver, final ResourceIdentifier targetAddress) {

    if (ProtonQoS.AT_MOST_ONCE.equals(receiver.getRemoteQoS())) {
        logger.debug("client wants to use unsupported AT MOST ONCE delivery mode for endpoint [{}], closing link ...", getName());
        receiver.setCondition(ProtonHelper.condition(AmqpError.PRECONDITION_FAILED.toString(), "endpoint requires AT_LEAST_ONCE QoS"));
        receiver.close();
    } else {

        logger.debug("establishing link for receiving request messages from client [{}]", receiver.getName());

        receiver.setQoS(ProtonQoS.AT_LEAST_ONCE);
        receiver.setAutoAccept(true); // settle received messages if the handler succeeds
        receiver.setTarget(receiver.getRemoteTarget());
        receiver.setSource(receiver.getRemoteSource());
        // We do manual flow control, credits are replenished after responses have been sent.
        receiver.setPrefetch(0);

        // set up handlers

        receiver.handler((delivery, message) -> {
            try {
                handleRequestMessage(con, receiver, targetAddress, delivery, message);
            } catch (final Exception ex) {
                logger.warn("error handling message", ex);
                ProtonHelper.released(delivery, true);
            }
        });
        HonoProtonHelper.setCloseHandler(receiver, remoteClose -> onLinkDetach(receiver));
        HonoProtonHelper.setDetachHandler(receiver, remoteDetach -> onLinkDetach(receiver));

        // acknowledge the remote open
        receiver.open();

        // send out initial credits, after opening
        logger.debug("flowing {} credits to client", config.getReceiverLinkCredit());
        receiver.flow(config.getReceiverLinkCredit());
    }
}
 
Example #25
Source File: AbstractRequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a client's request to establish a link for sending service invocation requests.
 * <p>
 * Configure and check the receiver link of the endpoint.
 * The remote link of the receiver must not demand the AT_MOST_ONCE QoS (not supported).
 * The receiver link itself is configured with the AT_LEAST_ONCE QoS and grants the configured credits
 * ({@link ServiceConfigProperties#getReceiverLinkCredit()}) with autoAcknowledge.
 * <p>
 * Handling of request messages is delegated to
 * {@link #handleRequestMessage(ProtonConnection, ProtonReceiver, ResourceIdentifier, ProtonDelivery, Message)}.
 *
 * @param con The AMQP connection that the link is part of.
 * @param receiver The ProtonReceiver that has already been created for this endpoint.
 * @param targetAddress The resource identifier for this endpoint (see {@link ResourceIdentifier} for details).
 */
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonReceiver receiver, final ResourceIdentifier targetAddress) {

    if (ProtonQoS.AT_MOST_ONCE.equals(receiver.getRemoteQoS())) {
        logger.debug("client wants to use unsupported AT MOST ONCE delivery mode for endpoint [{}], closing link ...", getName());
        receiver.setCondition(ProtonHelper.condition(AmqpError.PRECONDITION_FAILED.toString(), "endpoint requires AT_LEAST_ONCE QoS"));
        receiver.close();
    } else {

        logger.debug("establishing link for receiving request messages from client [{}]", receiver.getName());

        receiver.setQoS(ProtonQoS.AT_LEAST_ONCE);
        receiver.setAutoAccept(true); // settle received messages if the handler succeeds
        receiver.setTarget(receiver.getRemoteTarget());
        receiver.setSource(receiver.getRemoteSource());
        // We do manual flow control, credits are replenished after responses have been sent.
        receiver.setPrefetch(0);

        // set up handlers

        receiver.handler((delivery, message) -> {
            try {
                handleRequestMessage(con, receiver, targetAddress, delivery, message);
            } catch (final Exception ex) {
                logger.warn("error handling message", ex);
                ProtonHelper.released(delivery, true);
            }
        });
        HonoProtonHelper.setCloseHandler(receiver, remoteClose -> onLinkDetach(receiver));
        HonoProtonHelper.setDetachHandler(receiver, remoteDetach -> onLinkDetach(receiver));

        // acknowledge the remote open
        receiver.open();

        // send out initial credits, after opening
        logger.debug("flowing {} credits to client", config.getReceiverLinkCredit());
        receiver.flow(config.getReceiverLinkCredit());
    }
}
 
Example #26
Source File: CommandAndControlClient.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private Future<ProtonReceiver> startCommandReceiver(final ProtonMessageHandler msgHandler) {
    return connectToAdapter()
    .compose(con -> {
        log.info("connection to AMQP adapter established");
        adapterConnection = con;
        return createSender();
    }).compose(s -> {
        sender = s;
        return subscribeToCommands(msgHandler);
    });
}
 
Example #27
Source File: CommandAndControlClient.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Opens a receiver link to receive commands from the org.eclipse.hono.cli.app.adapter.
 *
 * @param msgHandler The handler to invoke when a command message is received.
 * @return A succeeded future with the created receiver link or a failed future
 *         if the receiver link cannot be created.
 *
 */
private Future<ProtonReceiver> subscribeToCommands(final ProtonMessageHandler msgHandler) {
    final Promise<ProtonReceiver> result = Promise.promise();
    final ProtonReceiver receiver = adapterConnection.createReceiver(CommandConstants.COMMAND_ENDPOINT);
    receiver.setQoS(ProtonQoS.AT_LEAST_ONCE);
    receiver.handler(msgHandler);
    receiver.openHandler(result);
    receiver.open();
    return result.future().map(recver -> {
        writer.println("Device is now ready to receive commands (Press Ctrl + c to terminate)");
        writer.flush();
        return recver;
    });
}
 
Example #28
Source File: AmqpSourceBridgeEndpoint.java    From strimzi-kafka-bridge with Apache License 2.0 5 votes vote down vote up
/**
 * Process the message received on the related receiver link
 *
 * @param receiver Proton receiver instance
 * @param delivery Proton delivery instance
 * @param message AMQP message received
 */
private void processMessage(ProtonReceiver receiver, ProtonDelivery delivery, Message message) {

    // replace unsupported "/" (in a topic name in Kafka) with "."
    String kafkaTopic = (receiver.getTarget().getAddress() != null) ?
            receiver.getTarget().getAddress().replace('/', '.') :
            null;

    KafkaProducerRecord<K, V> krecord = this.converter.toKafkaRecord(kafkaTopic, null, message);

    if (delivery.remotelySettled()) {

        // message settled (by sender), no feedback need by Apache Kafka, no disposition to be sent
        this.send(krecord, null);

    } else {
        // message unsettled (by sender), feedback needed by Apache Kafka, disposition to be sent accordingly
        this.send(krecord, writeResult -> {

            if (writeResult.failed()) {

                Throwable exception = writeResult.cause();
                // record not delivered, send REJECTED disposition to the AMQP sender
                log.error("Error on delivery to Kafka {}", exception.getMessage());
                this.rejectedDelivery(receiver.getName(), delivery, exception);

            } else {

                RecordMetadata metadata = writeResult.result();
                // record delivered, send ACCEPTED disposition to the AMQP sender
                log.debug("Delivered to Kafka on topic {} at partition {} [{}]", metadata.getTopic(), metadata.getPartition(), metadata.getOffset());
                this.acceptedDelivery(receiver.getName(), delivery);
            }
        });
    }
}
 
Example #29
Source File: AmqpSourceBridgeEndpoint.java    From strimzi-kafka-bridge with Apache License 2.0 5 votes vote down vote up
/**
 * Handle for detached link by the remote sender
 * @param receiver Proton receiver instance
 */
private void processCloseReceiver(ProtonReceiver receiver) {

    log.info("Remote AMQP sender detached");

    // close and remove the receiver link
    receiver.close();
    this.receivers.remove(receiver.getName());

    // if the source endpoint has no receiver links, it can be closed
    if (this.receivers.isEmpty()) {
        this.close();
    }
}
 
Example #30
Source File: BlockingClient.java    From enmasse with Apache License 2.0 5 votes vote down vote up
public List<Message> recv(String address, int numMessages, long timeout, TimeUnit timeUnit) throws InterruptedException {
    ProtonClient client = ProtonClient.create(vertx);
    CountDownLatch latch = new CountDownLatch(1);
    List<Message> messages = new ArrayList<>();
    client.connect(host, port, connectEvent -> {
        if (connectEvent.succeeded()) {
            ProtonConnection connection = connectEvent.result();
            connection.open();

            ProtonReceiver receiver = connection.createReceiver(address);
            receiver.setPrefetch(0);
            receiver.openHandler(r -> receiver.flow(1));
            receiver.handler((delivery, message) -> {
                messages.add(message);
                if (messages.size() == numMessages) {
                    vertx.runOnContext(h -> {
                        connection.close();
                        latch.countDown();
                    });
                } else {
                    receiver.flow(1);
                }
            });
            receiver.open();
        }
    });
    boolean ok = latch.await(timeout, timeUnit);
    if (!ok) {
        throw new RuntimeException("Sending messages timed out, " + messages.size() + " out of " + numMessages + " messages received");
    }
    return messages;
}