io.vertx.proton.ProtonQoS Java Examples

The following examples show how to use io.vertx.proton.ProtonQoS. 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: HonoConnectionImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the attempt to create a sender 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 testCreateSenderFailsOnTimeout(final VertxTestContext ctx) {

    final ProtonSender sender = mock(ProtonSender.class);
    when(sender.isOpen()).thenReturn(Boolean.TRUE);
    when(con.createSender(anyString())).thenReturn(sender);
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> honoConnection.createSender(
            "target", ProtonQoS.AT_LEAST_ONCE, remoteCloseHook))
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> {
                assertThat(((ServerErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE);
                verify(sender).open();
                verify(sender).close();
                verify(remoteCloseHook, never()).handle(anyString());
            });
            ctx.completeNow();
        }));
}
 
Example #2
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void filters_nonLongOffsetFilter() throws Exception {
    String topic = "my_topic";
    Vertx vertx = Vertx.vertx();
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, BridgeConfig.fromMap(config),
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, topic + "/group.id/blah");
    // Call handle()
    Map<Symbol, Object> filter = new HashMap<>();
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_PARTITION_FILTER), 0);
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_OFFSET_FILTER), "not a long");
    ((Source) mockSender.getRemoteSource()).setFilter(filter);
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            // TODO really?
            AmqpBridge.AMQP_ERROR_WRONG_OFFSET_FILTER,
            "Wrong offset filter");
}
 
Example #3
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void filters_negativeIntegerPartitionFilter() throws Exception {
    String topic = "my_topic";
    Vertx vertx = Vertx.vertx();
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, BridgeConfig.fromMap(config),
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, topic + "/group.id/blah");
    // Call handle()
    Map<Symbol, Object> filter = new HashMap<>();
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_PARTITION_FILTER), -1);
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_OFFSET_FILTER), 10L);
    ((Source) mockSender.getRemoteSource()).setFilter(filter);
    endpoint.handle(new AmqpEndpoint(mockSender));

    ArgumentCaptor<ErrorCondition> errorCap = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(mockSender).setCondition(errorCap.capture());
    verify(mockSender).close();

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_WRONG_FILTER,
            "Wrong filter");
}
 
Example #4
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void filters_negativeLongOffsetFilter() throws Exception {
    String topic = "my_topic";
    Vertx vertx = Vertx.vertx();
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, BridgeConfig.fromMap(config),
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, topic + "/group.id/blah");
    // Call handle()
    Map<Symbol, Object> filter = new HashMap<>();
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_PARTITION_FILTER), 0);
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_OFFSET_FILTER), -10L);
    ((Source) mockSender.getRemoteSource()).setFilter(filter);
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_WRONG_FILTER,
            "Wrong filter");
}
 
Example #5
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void filters_offsetFilterButNoPartitionFilter() throws Exception {
    String topic = "my_topic";
    Vertx vertx = Vertx.vertx();
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, BridgeConfig.fromMap(config),
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, topic + "/group.id/blah");
    // Call handle()
    Map<Symbol, Object> filter = new HashMap<>();
    //filter.put(Symbol.getSymbol(Bridge.AMQP_PARTITION_FILTER), 0);
    filter.put(Symbol.getSymbol(AmqpBridge.AMQP_OFFSET_FILTER), 10L);
    ((Source) mockSender.getRemoteSource()).setFilter(filter);
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_NO_PARTITION_FILTER,
            "No partition filter specified");
}
 
Example #6
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void config_ConverterWrongType() throws AmqpErrorConditionException {
    Vertx vertx = Vertx.vertx();
    BridgeConfig config = BridgeConfig.fromMap(AmqpSinkBridgeEndpointMockTest.config);
    config.getAmqpConfig().setMessageConverter("java.util.HashSet");
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, config,
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, "");
    // Call handle()
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_CONFIGURATION,
            "configured message converter class is not an instanceof io.strimzi.kafka.bridge.converter.MessageConverter: java.util.HashSet");
}
 
Example #7
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void config_ConverterNoDefaultConstructor() throws AmqpErrorConditionException {
    Vertx vertx = Vertx.vertx();
    BridgeConfig config = BridgeConfig.fromMap(AmqpSinkBridgeEndpointMockTest.config);
    config.getAmqpConfig().setMessageConverter(NoNullaryCtor.class.getName());
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, config,
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, "");
    // Call handle()
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_CONFIGURATION,
            "configured message converter class could not be instantiated: io.strimzi.kafka.bridge.amqp.AmqpSinkBridgeEndpointMockTest$NoNullaryCtor");
}
 
Example #8
Source File: AmqpClientFactory.java    From enmasse with Apache License 2.0 6 votes vote down vote up
public AmqpClient createClient(TerminusFactory terminusFactory, ProtonQoS qos, AddressSpace addressSpace) throws Exception {
    assertNotNull(addressSpace, "Address space is null");
    Endpoint messagingEndpoint = AddressSpaceUtils.getEndpointByServiceName(addressSpace, "messaging");
    if (messagingEndpoint == null) {
        String externalEndpointName = AddressSpaceUtils.getExternalEndpointName(addressSpace, "messaging");
        messagingEndpoint = Kubernetes.getInstance().getExternalEndpoint(externalEndpointName + "-" + AddressSpaceUtils.getAddressSpaceInfraUuid(addressSpace));
    }
    Endpoint clientEndpoint;
    ProtonClientOptions clientOptions = new ProtonClientOptions();
    clientOptions.setSsl(true);
    clientOptions.setTrustAll(true);
    clientOptions.setHostnameVerificationAlgorithm("");

    if (TestUtils.resolvable(messagingEndpoint)) {
        clientEndpoint = messagingEndpoint;
    } else {
        clientEndpoint = new Endpoint("localhost", 443);
        clientOptions.setSniServerName(messagingEndpoint.getHost());
    }
    log.info("External endpoint: " + clientEndpoint + ", internal: " + messagingEndpoint);
    probeEndpoint(messagingEndpoint);

    return createClient(terminusFactory, clientEndpoint, clientOptions, qos);
}
 
Example #9
Source File: CommandResponseSenderImpl.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Creates a new sender to send responses for commands back to the business application.
 * <p>
 * The underlying sender link will be created with the following properties:
 * <ul>
 * <li><em>flow latency</em> will be set to @{@link #DEFAULT_COMMAND_FLOW_LATENCY} if the configured value is
 * smaller than the default</li>
 * </ul>
 *
 * @param con The connection to the AMQP network.
 * @param tenantId The tenant that the command response will be send for and the device belongs to.
 * @param replyId The reply id as the unique postfix of the replyTo address.
 * @param closeHook A handler to invoke if the peer closes the link unexpectedly.
 * @return A future indicating the result of the creation attempt.
 * @throws NullPointerException if any of con, tenantId or replyId are {@code null}.
 */
public static Future<CommandResponseSender> create(
        final HonoConnection con,
        final String tenantId,
        final String replyId,
        final Handler<String> closeHook) {

    Objects.requireNonNull(con);
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(replyId);

    final String targetAddress = CommandResponseSenderImpl.getTargetAddress(tenantId, replyId);
    final ClientConfigProperties props = new ClientConfigProperties(con.getConfig());
    if (props.getFlowLatency() < DEFAULT_COMMAND_FLOW_LATENCY) {
        props.setFlowLatency(DEFAULT_COMMAND_FLOW_LATENCY);
    }

    return con.createSender(targetAddress, ProtonQoS.AT_LEAST_ONCE, closeHook)
            .map(sender -> (CommandResponseSender) new CommandResponseSenderImpl(con, sender, tenantId,
                    targetAddress));
}
 
Example #10
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 #11
Source File: ProtonLinkImpl.java    From vertx-proton with Apache License 2.0 6 votes vote down vote up
@Override
public T setQoS(ProtonQoS qos) {
  if (qos == null) {
    throw new IllegalArgumentException("Value must be specified");
  }
  switch (qos) {
  case AT_MOST_ONCE:
    link.setSenderSettleMode(SenderSettleMode.SETTLED);
    link.setReceiverSettleMode(ReceiverSettleMode.FIRST);
    break;
  case AT_LEAST_ONCE:
    link.setSenderSettleMode(SenderSettleMode.UNSETTLED);
    link.setReceiverSettleMode(ReceiverSettleMode.FIRST);
    break;
  }
  return self();
}
 
Example #12
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 #13
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 sender for a {@code null} target address
 * fails with a {@code ServerErrorException} if the remote peer doesn't
 * support the anonymous terminus.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateSenderFailsForUnsupportedAnonTerminus(final VertxTestContext ctx) {

    when(con.getRemoteOfferedCapabilities()).thenReturn(new Symbol[] {Symbol.valueOf("some-feature")});
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> honoConnection.createSender(
            null, ProtonQoS.AT_LEAST_ONCE, remoteCloseHook))
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> {
                // THEN the attempt fails
                assertThat(((ServerErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_NOT_IMPLEMENTED);
                // and the remote close hook is not invoked
                verify(remoteCloseHook, never()).handle(anyString());
            });
            ctx.completeNow();
        }));

}
 
Example #14
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 #15
Source File: AuthenticationEndpoint.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonSender sender, final ResourceIdentifier targetResource) {

    if (ProtonQoS.AT_LEAST_ONCE.equals(sender.getRemoteQoS())) {
        final HonoUser user = Constants.getClientPrincipal(con);
        sender.setQoS(ProtonQoS.AT_LEAST_ONCE).open();
        logger.debug("transferring token to client...");
        final Message tokenMsg = ProtonHelper.message(user.getToken());
        MessageHelper.addProperty(tokenMsg, AuthenticationConstants.APPLICATION_PROPERTY_TYPE, AuthenticationConstants.TYPE_AMQP_JWT);
        sender.send(tokenMsg, disposition -> {
            if (disposition.remotelySettled()) {
                logger.debug("successfully transferred auth token to client");
            } else {
                logger.debug("failed to transfer auth token to client");
            }
            sender.close();
        });
    } else {
        onLinkDetach(sender, ProtonHelper.condition(AmqpError.INVALID_FIELD, "supports AT_LEAST_ONCE delivery mode only"));
    }
}
 
Example #16
Source File: ProtocolAdapterCommandConsumerFactoryImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that creating a command consumer with a positive lifespan and
 * closing the consumer afterwards succeeds.
 *
 * @param ctx The test context.
 */
@Test
public void testCreateTimeLimitedCommandConsumerSucceeds(final VertxTestContext ctx) {

    final Handler<CommandContext> commandHandler = VertxMockSupport.mockHandler();

    final Duration lifespan = Duration.ofSeconds(10);
    final Future<ProtocolAdapterCommandConsumer> commandConsumerFuture = commandConsumerFactory.createCommandConsumer(tenantId,
            deviceId, commandHandler, lifespan, null);
    commandConsumerFuture.onComplete(ctx.succeeding(consumer -> {
        ctx.verify(() -> {
            verify(connection).createReceiver(eq(tenantCommandAddress), eq(ProtonQoS.AT_LEAST_ONCE), any(), anyInt(),
                    eq(false), any());
            verify(devConClient).setCommandHandlingAdapterInstance(eq(deviceId), anyString(), any(), any());
            // verify closing the consumer is successful
            consumer.close(any()).onComplete(ctx.succeeding(v -> {
                ctx.verify(() -> {
                    // verify command handling adapter instance has been explicitly removed (since lifespan hasn't elapsed yet)
                    verify(devConClient).removeCommandHandlingAdapterInstance(eq(deviceId), anyString(), any());
                });
                ctx.completeNow();
            }));
        });
    }));
}
 
Example #17
Source File: ProtocolAdapterCommandConsumerFactoryImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that creating a command consumer successfully creates a tenant-scoped
 * receiver link and registers the command handling adapter instance.
 *
 * @param ctx The test context.
 */
@Test
public void testCreateCommandConsumerSucceeds(final VertxTestContext ctx) {

    final Handler<CommandContext> commandHandler = VertxMockSupport.mockHandler();

    commandConsumerFactory.createCommandConsumer(tenantId, deviceId, commandHandler, null, null)
        .onComplete(ctx.succeeding(c -> {
            ctx.verify(() -> {
                verify(connection).createReceiver(eq(tenantCommandAddress), eq(ProtonQoS.AT_LEAST_ONCE), any(), anyInt(),
                        eq(false), any());
                verify(devConClient).setCommandHandlingAdapterInstance(eq(deviceId), anyString(), any(), any());
            });
            ctx.completeNow();
        }));
}
 
Example #18
Source File: ProtocolAdapterCommandConsumerFactoryImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that an attempt to open a command consumer fails if the peer
 * rejects to open a receiver link.
 *
 * @param ctx The test context.
 */
@Test
public void testCreateCommandConsumerFailsIfPeerRejectsLink(final VertxTestContext ctx) {

    final Handler<CommandContext> commandHandler = VertxMockSupport.mockHandler();
    final ServerErrorException ex = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE);
    when(connection.createReceiver(
            anyString(),
            any(ProtonQoS.class),
            any(ProtonMessageHandler.class),
            anyInt(),
            anyBoolean(),
            VertxMockSupport.anyHandler()))
    .thenReturn(Future.failedFuture(ex));

    commandConsumerFactory.createCommandConsumer(tenantId, deviceId, commandHandler, null, null)
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> assertThat(((ServiceInvocationException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE));
            ctx.completeNow();
        }));
}
 
Example #19
Source File: DownstreamSenderFactoryImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that a request to create a sender is failed immediately when the
 * underlying connection to the server fails.
 */
@Test
public void testGetTelemetrySenderFailsOnConnectionFailure() {

    // GIVEN a factory that tries to create a telemetry sender for "tenant"
    final Promise<ProtonSender> sender = Promise.promise();
    when(connection.createSender(anyString(), any(ProtonQoS.class), VertxMockSupport.anyHandler()))
        .thenReturn(sender.future());
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<DisconnectListener<HonoConnection>> disconnectHandler = ArgumentCaptor.forClass(DisconnectListener.class);
    verify(connection).addDisconnectListener(disconnectHandler.capture());

    final Future<DownstreamSender> result = factory.getOrCreateTelemetrySender("telemetry/tenant");
    assertThat(result.isComplete()).isFalse();

    // WHEN the underlying connection fails
    disconnectHandler.getValue().onDisconnect(connection);

    // THEN all creation requests are failed
    assertThat(result.failed()).isTrue();
}
 
Example #20
Source File: EventConsumerImpl.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Creates a new event consumer for a tenant.
 *
 * @param con The connection to the server.
 * @param tenantId The tenant to consumer events for.
 * @param eventConsumer The consumer to invoke with each event received.
 * @param closeHook The handler to invoke when the link is closed by the peer (may be {@code null}).
 * @return A future indicating the outcome.
 * @throws NullPointerException if any of the parameters except the closeHook are {@code null}.
 */
public static Future<MessageConsumer> create(
        final HonoConnection con,
        final String tenantId,
        final BiConsumer<ProtonDelivery, Message> eventConsumer,
        final Handler<String> closeHook) {

    Objects.requireNonNull(con);
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(eventConsumer);

    final String sourceAddress = String.format("%s/%s", EventConstants.EVENT_ENDPOINT, tenantId);
    return con.createReceiver(
            sourceAddress,
            ProtonQoS.AT_LEAST_ONCE,
            eventConsumer::accept,
            closeHook)
            .compose(receiver -> Future.succeededFuture(new EventConsumerImpl(con, receiver)));
}
 
Example #21
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 sender succeeds when sender never gets credits.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateSenderThatGetsNoCredits(final VertxTestContext ctx) {
    final ProtonSender sender = mock(ProtonSender.class);
    when(sender.isOpen()).thenReturn(Boolean.TRUE);
    when(con.createSender(anyString())).thenReturn(sender);
    final Target target = new Target();
    target.setAddress("someAddress");
    when(sender.getRemoteTarget()).thenReturn(target);
    when(sender.getCredit()).thenReturn(0);
    // just invoke openHandler with succeeded future
    doAnswer(AdditionalAnswers.answerVoid(
            (final Handler<AsyncResult<ProtonSender>> handler) -> handler.handle(Future.succeededFuture(sender))))
                    .when(sender).openHandler(VertxMockSupport.anyHandler());
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> honoConnection.createSender(
            "target", ProtonQoS.AT_LEAST_ONCE, remoteCloseHook))
        .onComplete(ctx.succeeding(s -> {
                ctx.verify(() -> {
                    assertThat(s).isEqualTo(sender);
                    // sendQueueDrainHandler gets unset
                    verify(sender).sendQueueDrainHandler(null);
                });
                ctx.completeNow();
            }));
}
 
Example #22
Source File: AmqpClientFactory.java    From enmasse with Apache License 2.0 5 votes vote down vote up
protected AmqpClient createClient(TerminusFactory terminusFactory, Endpoint endpoint, ProtonClientOptions protonOptions, ProtonQoS qos) {
    AmqpConnectOptions connectOptions = new AmqpConnectOptions()
            .setTerminusFactory(terminusFactory)
            .setEndpoint(endpoint)
            .setProtonClientOptions(protonOptions)
            .setQos(qos)
            .setUsername(defaultUsername)
            .setPassword(defaultPassword);
    return createClient(connectOptions);
}
 
Example #23
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 sender 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 testCreateSenderFailsOnDisconnectBeforeOpen(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 ProtonSender sender = mock(ProtonSender.class);
    when(sender.isOpen()).thenReturn(Boolean.TRUE);
    when(con.createSender(anyString())).thenReturn(sender);
    final Target target = new Target();
    target.setAddress("someAddress");
    when(sender.getRemoteTarget()).thenReturn(target);
    when(sender.getCredit()).thenReturn(0);
    // mock handlers
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> {
            // WHEN creating a sender link with a close hook
            final Future<ProtonSender> result = honoConnection.createSender(
                    "target", ProtonQoS.AT_LEAST_ONCE, 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 #24
Source File: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 5 votes vote down vote up
@Test
public <K, V> void address_badAddressEmptyGroup() throws Exception {
    String topic = "my_topic";
    Vertx vertx = Vertx.vertx();
    AmqpSinkBridgeEndpoint<K, V> endpoint = (AmqpSinkBridgeEndpoint) new AmqpSinkBridgeEndpoint<>(vertx, BridgeConfig.fromMap(config),
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());
    endpoint.open();
    ProtonSender mockSender = mockSender(ProtonQoS.AT_MOST_ONCE, topic + "/group.id/");
    // Call handle()
    endpoint.handle(new AmqpEndpoint(mockSender));

    assertDetach(mockSender,
            AmqpBridge.AMQP_ERROR_NO_GROUPID,
            "Empty consumer group in specified address");
}
 
Example #25
Source File: HonoClientUnitTestHelper.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a mocked Proton sender which always returns {@code true} when its isOpen method is called.
 *
 * @return The mocked sender.
 */
public static ProtonSender mockProtonSender() {

    final ProtonSender sender = mock(ProtonSender.class);
    when(sender.isOpen()).thenReturn(Boolean.TRUE);
    when(sender.getQoS()).thenReturn(ProtonQoS.AT_LEAST_ONCE);
    when(sender.getTarget()).thenReturn(mock(Target.class));

    return sender;
}
 
Example #26
Source File: VertxBasedAmqpProtocolAdapter.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private Future<ProtocolAdapterCommandConsumer> openCommandSenderLink(
        final ProtonConnection connection,
        final ProtonSender sender,
        final ResourceIdentifier address,
        final Device authenticatedDevice,
        final Span span,
        final OptionalInt traceSamplingPriority) {

    return createCommandConsumer(sender, address, authenticatedDevice, span).map(consumer -> {

        final String tenantId = address.getTenantId();
        final String deviceId = address.getResourceId();
        sender.setSource(sender.getRemoteSource());
        sender.setTarget(sender.getRemoteTarget());

        sender.setQoS(ProtonQoS.AT_LEAST_ONCE);
        final Handler<AsyncResult<ProtonSender>> detachHandler = link -> {
            final Span detachHandlerSpan = newSpan("detach Command receiver", authenticatedDevice,
                    traceSamplingPriority);
            removeConnectionLossHandler(connection, address.toString());
            sendDisconnectedTtdEvent(tenantId, deviceId, authenticatedDevice, detachHandlerSpan.context());
            onLinkDetach(sender);
            consumer.close(detachHandlerSpan.context())
                    .onComplete(v -> detachHandlerSpan.finish());
        };
        HonoProtonHelper.setCloseHandler(sender, detachHandler);
        HonoProtonHelper.setDetachHandler(sender, detachHandler);
        sender.open();

        // At this point, the remote peer's receiver link is successfully opened and is ready to receive
        // commands. Send "device ready for command" notification downstream.
        log.debug("established link [address: {}] for sending commands to device", address);

        sendConnectedTtdEvent(tenantId, deviceId, authenticatedDevice, span.context());
        return consumer;
    }).recover(t -> Future.failedFuture(
            new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "cannot create command consumer")));
}
 
Example #27
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 #28
Source File: AmqpSinkBridgeEndpoint.java    From strimzi-kafka-bridge with Apache License 2.0 5 votes vote down vote up
/**
 * Map the ProtonQoS specific type to the QoS Endpoint generic type
 *
 * @param protonQoS ProtonQoS level
 * @return QoS endpoint specific
 */
private QoSEndpoint mapQoS(ProtonQoS protonQoS) {
    if (protonQoS == ProtonQoS.AT_MOST_ONCE)
        return QoSEndpoint.AT_MOST_ONCE;
    else if (protonQoS == ProtonQoS.AT_LEAST_ONCE)
        return QoSEndpoint.AT_LEAST_ONCE;
    else
        throw new IllegalArgumentException("Proton QoS not supported !");
}
 
Example #29
Source File: GenericMessageSenderImpl.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a new sender for sending messages.
 *
 * @param con The connection to the peer.
 * @param targetAddress The target address of the sender.
 * @param closeHook The handler to invoke when the Hono server closes the sender. The sender's
 *                  target address is provided as an argument to the handler.
 * @return The sender.
 * @throws NullPointerException if any of context, connection, tenant or handler is {@code null}.
 */
public static Future<MessageSender> create(
        final HonoConnection con,
        final String targetAddress,
        final Handler<String> closeHook) {

    Objects.requireNonNull(con);
    Objects.requireNonNull(targetAddress);

    return con.createSender(targetAddress, ProtonQoS.AT_LEAST_ONCE, closeHook).map(sender -> {
        return new GenericMessageSenderImpl(con, sender);
    });
}
 
Example #30
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 sender fails with a
 * {@code ServerErrorException} if the remote peer sends a
 * {@code null} target in its attach frame.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateSenderFailsIfPeerDoesNotCreateTerminus(final VertxTestContext ctx) {

    final ProtonSender sender = mock(ProtonSender.class);
    when(sender.getRemoteTarget()).thenReturn(null);
    when(con.createSender(anyString())).thenReturn(sender);
    final Handler<String> remoteCloseHook = VertxMockSupport.mockHandler();

    // GIVEN an established connection
    honoConnection.connect()
        .compose(c -> {
            // WHEN the client tries to open a sender link
            final Future<ProtonSender> s = c.createSender(
                    TelemetryConstants.TELEMETRY_ENDPOINT, ProtonQoS.AT_LEAST_ONCE, remoteCloseHook);
            ctx.verify(() -> {
                final ArgumentCaptor<Handler<AsyncResult<ProtonSender>>> openHandler = VertxMockSupport.argumentCaptorHandler();
                verify(sender).open();
                verify(sender).openHandler(openHandler.capture());
                // and the peer does not allocate a local terminus for the link
                openHandler.getValue().handle(Future.succeededFuture(sender));
            });
            return s;
        })
        .onComplete(ctx.failing(t -> {
            ctx.verify(() -> {

                // THEN the link does not get established
                assertThat(((ServerErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_UNAVAILABLE);
                // and the remote close hook does not get invoked
                verify(remoteCloseHook, never()).handle(anyString());
            });
            ctx.completeNow();
        }));

}