io.vertx.proton.ProtonSender Java Examples

The following examples show how to use io.vertx.proton.ProtonSender. 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: AmqpSinkBridgeEndpointMockTest.java    From strimzi-kafka-bridge with Apache License 2.0 6 votes vote down vote up
@Test
public <K, V> void config_NoSuchConverterClass() throws AmqpErrorConditionException {
    Vertx vertx = Vertx.vertx();
    BridgeConfig config = BridgeConfig.fromMap(AmqpSinkBridgeEndpointMockTest.config);
    config.getAmqpConfig().setMessageConverter("foo.bar.Baz");
    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: foo.bar.Baz");
}
 
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: AbstractSender.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Creates a new sender.
 *
 * @param connection The connection to use for interacting with the server.
 * @param sender The sender link to send messages over.
 * @param tenantId The identifier of the tenant that the
 *           devices belong to which have published the messages
 *           that this sender is used to send downstream.
 * @param targetAddress The target address to send the messages to.
 */
protected AbstractSender(
        final HonoConnection connection,
        final ProtonSender sender,
        final String tenantId,
        final String targetAddress) {

    super(connection);
    this.sender = Objects.requireNonNull(sender);
    this.tenantId = Objects.requireNonNull(tenantId);
    this.targetAddress = targetAddress;
    if (sender.isOpen()) {
        this.offeredCapabilities = Optional.ofNullable(sender.getRemoteOfferedCapabilities())
                .map(caps -> Collections.unmodifiableList(Arrays.asList(caps)))
                .orElse(Collections.emptyList());
    }
}
 
Example #4
Source File: HonoConnectionImpl.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private void onRemoteDetach(
        final ProtonLink<?> link,
        final String remoteContainer,
        final boolean closed,
        final Handler<String> closeHook) {

    final ErrorCondition error = link.getRemoteCondition();
    final String type = link instanceof ProtonSender ? "sender" : "receiver";
    final String address = link instanceof ProtonSender ? link.getTarget().getAddress() :
        link.getSource().getAddress();
    if (error == null) {
        log.debug("{} [{}] detached (with closed={}) by peer [{}]",
                type, address, closed, remoteContainer);
    } else {
        log.debug("{} [{}] detached (with closed={}) by peer [{}]: {} - {}",
                type, address, closed, remoteContainer, error.getCondition(), error.getDescription());
    }
    link.close();
    if (HonoProtonHelper.isLinkEstablished(link) && closeHook != null) {
        closeHook.handle(address);
    }
}
 
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_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 #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 filters_nonIntegerPartitionFilter() 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), "not an integer");
    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_PARTITION_FILTER,
            "Wrong partition filter");
}
 
Example #7
Source File: DownstreamSenderFactoryImplTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that a concurrent request to create a sender fails the given future for tracking the attempt if the
 * initial request doesn't complete.
 *
 * @param ctx The helper to use for running async tests.
 */
@Test
public void testGetTelemetrySenderFailsIfInvokedConcurrently(final VertxTestContext ctx) {

    // GIVEN a factory that already tries to create a telemetry sender for "tenant" (and never completes doing so)
    final Promise<ProtonSender> sender = Promise.promise();
    when(connection.createSender(anyString(), any(ProtonQoS.class), VertxMockSupport.anyHandler()))
    .thenReturn(sender.future());
    final Future<DownstreamSender> result = factory.getOrCreateTelemetrySender("telemetry/tenant");
    assertThat(result.isComplete()).isFalse();

    // WHEN an additional, concurrent attempt is made to create a telemetry sender for "tenant"
    factory.getOrCreateTelemetrySender("telemetry/tenant").onComplete(ctx.failing(t -> {
        // THEN the concurrent attempt fails after having done the default number of retries.
        ctx.verify(() -> {
            assertThat(t).isInstanceOf(ServerErrorException.class);
            verify(vertx, times(CachingClientFactory.MAX_CREATION_RETRIES)).setTimer(anyLong(), notNull());
        });
    }));
    sender.complete(mock(ProtonSender.class));
    ctx.verify(() -> assertThat(result.isComplete()).isTrue());
    ctx.completeNow();
}
 
Example #8
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 #9
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 #10
Source File: AbstractTenantTimeoutRelatedClientFactoryTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the links are closed when a tenant timeout message is received for the tenant of this client.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testLinksCloseOnTenantTimeout(final VertxTestContext ctx) {

    final String tenantId = "tenant";

    // GIVEN a client factory that manages a client with a tenant-scoped link
    final HonoConnection connection = createConnection();
    getClientFuture(connection, tenantId).onComplete(ctx.succeeding(r -> {

        // WHEN a tenant timeout event occurs for this tenant
        connection.getVertx().eventBus().publish(Constants.EVENT_BUS_ADDRESS_TENANT_TIMED_OUT, tenantId);

        // THEN the link is closed
        ctx.verify(() -> {
            verify(connection, timeout(TIMEOUT)).closeAndFree(any(ProtonSender.class), VertxMockSupport.anyHandler());
        });
        ctx.completeNow();
    }));
}
 
Example #11
Source File: AbstractTenantTimeoutRelatedClientFactoryTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the links of other clients are not closed when a tenant timeout message is received.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testDontCloseLinksForOtherTenants(final VertxTestContext ctx) {

    final String tenantId = "tenant";
    final String otherTenant = "otherTenant";

    // GIVEN a client factory that manages a client with a tenant-scoped link
    final HonoConnection connection = createConnection();
    getClientFuture(connection, tenantId).onComplete(ctx.succeeding(r -> {

        // WHEN a tenant timeout event occurs for another tenant
        connection.getVertx().eventBus().publish(Constants.EVENT_BUS_ADDRESS_TENANT_TIMED_OUT, otherTenant);

        ctx.verify(() -> {
            // THEN the link is not closed
            verify(connection, timeout(TIMEOUT).times(0)).closeAndFree(any(ProtonSender.class), VertxMockSupport.anyHandler());
        });
        ctx.completeNow();
    }));
}
 
Example #12
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 #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 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 #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 receiver
 *
 * @param connection connection which the sender link belong to
 * @param sender sender link created by the underlying Proton library
 *               by which handling communication with remote receiver
 */
private void processOpenSender(ProtonConnection connection, ProtonSender sender) {

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

    // create and add a new sink to the map
    // TODO: the AMQP client should be able to specify the format during link attachment
    SinkBridgeEndpoint<?, ?> sink = new AmqpSinkBridgeEndpoint<>(this.vertx, this.bridgeConfig,
            EmbeddedFormat.JSON, new StringDeserializer(), new ByteArrayDeserializer());

    sink.closeHandler(s -> {
        this.endpoints.get(connection).getSinks().remove(s);
    });
    sink.open();
    this.endpoints.get(connection).getSinks().add(sink);

    sink.handle(new AmqpEndpoint(sender));
}
 
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: 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 #17
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 #18
Source File: VertxProtonExamples.java    From vertx-proton with Apache License 2.0 6 votes vote down vote up
public void example2(ProtonConnection connection) {
  connection.createSender("myQueue").openHandler(openResult -> {
    if (openResult.succeeded()) {
      ProtonSender sender = openResult.result();

      Message message = message();
      message.setBody(new AmqpValue("Hello World"));

      // Send message, providing an onUpdated delivery handler that prints updates
      sender.send(message, delivery -> {
        System.out.println(String.format("Message received by server: remote state=%s, remotely settled=%s",
                                         delivery.getRemoteState(), delivery.remotelySettled()));
      });
    }
  }).open();
}
 
Example #19
Source File: AmqpUploadTestBase.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Sets up the protocol adapter by doing the following:
 * <ul>
 * <li>Add a device (with credentials) for the tenant identified by the given tenantId.</li>
 * <li>Create an AMQP 1.0 client and authenticate it to the protocol adapter with username: {@code [device-id@tenantId]}.</li>
 * <li>After a successful connection, create a producer/sender for sending messages to the protocol adapter.</li>
 * </ul>
 *
 * @param tenantId The tenant to register with the device registry.
 * @param deviceId The device to add to the tenant identified by tenantId.
 * @param disableTenant If true, disable the protocol adapter for the tenant.
 *
 * @return A future succeeding with the created sender.
 */
private Future<ProtonSender> setupProtocolAdapter(
        final String tenantId,
        final String deviceId,
        final boolean disableTenant) {

    final String username = IntegrationTestSupport.getUsername(deviceId, tenantId);

    final Tenant tenant = new Tenant();
    if (disableTenant) {
        tenant.addAdapterConfig(new Adapter(Constants.PROTOCOL_ADAPTER_TYPE_AMQP).setEnabled(false));
    }

    return helper.registry
            .addDeviceForTenant(tenantId, tenant, deviceId, DEVICE_PASSWORD)
            .compose(ok -> connectToAdapter(username, DEVICE_PASSWORD))
            .compose(con -> createProducer(null))
            .recover(t -> {
                log.error("error setting up AMQP protocol adapter", t);
                return Future.failedFuture(t);
            });
}
 
Example #20
Source File: RequestResponseEndpointTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verify that a second response link to the same address is being rejected.
 */
@Test
public void testDuplicateSubscription() {

    final ProtonConnection con1 = mock(ProtonConnection.class);
    final ProtonConnection con2 = mock(ProtonConnection.class);

    final ProtonSender sender1 = mock(ProtonSender.class);
    final ProtonSender sender2 = mock(ProtonSender.class);

    final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true);

    // WHEN a first sender attaches
    endpoint.onLinkAttach(con1, sender1, REPLY_RESOURCE);

    // THEN open has to be called
    verify(sender1).open();

    // WHEN a second sender attaches
    endpoint.onLinkAttach(con2, sender2, REPLY_RESOURCE);

    // THEN close has to be called
    verify(sender2).close();
}
 
Example #21
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 #22
Source File: AmqpServiceBase.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Handles a request from a client to establish a link for receiving messages from this server.
 *
 * @param con the connection to the client.
 * @param sender the sender created for the link.
 */
protected void handleSenderOpen(final ProtonConnection con, final ProtonSender sender) {
    final Source remoteSource = sender.getRemoteSource();
    log.debug("client [container: {}] wants to open a link [address: {}] for receiving messages",
            con.getRemoteContainer(), remoteSource);
    try {
        final ResourceIdentifier targetResource = getResourceIdentifier(remoteSource.getAddress());
        final AmqpEndpoint endpoint = getEndpoint(targetResource);
        if (endpoint == null) {
            handleUnknownEndpoint(con, sender, targetResource);
        } else {
            final HonoUser user = Constants.getClientPrincipal(con);
            getAuthorizationService().isAuthorized(user, targetResource, Activity.READ).onComplete(authAttempt -> {
                if (authAttempt.succeeded() && authAttempt.result()) {
                    Constants.copyProperties(con, sender);
                    sender.setSource(sender.getRemoteSource());
                    sender.setTarget(sender.getRemoteTarget());
                    endpoint.onLinkAttach(con, sender, targetResource);
                } else {
                    log.debug("subject [{}] is not authorized to READ from [{}]", user.getName(), targetResource);
                    sender.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized"));
                    sender.close();
                }
            });
        }
    } catch (final IllegalArgumentException e) {
        log.debug("client has provided invalid resource identifier as target address", e);
        sender.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address"));
        sender.close();
    }
}
 
Example #23
Source File: RequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private void registerSenderForReplyTo(final String replyTo, final ProtonSender sender) {

        final ProtonSender oldSender = replyToSenderMap.put(replyTo, sender);

        if (oldSender == null || oldSender == sender) {
            logger.debug("registered sender [{}] for replies to [{}]", sender, replyTo);
        } else {
            logger.info("replaced existing sender [{}] for replies to [{}] with sender [{}]",
                    oldSender, replyTo, sender);
        }
    }
 
Example #24
Source File: RequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private Future<ProtonSender> getSenderForConnection(final ProtonConnection con, final String replytoAddress) {

        final Promise<ProtonSender> result = Promise.promise();
        final ProtonSender sender = replyToSenderMap.get(replytoAddress);
        if (sender != null && sender.isOpen() && sender.getSession().getConnection() == con) {
            result.complete(sender);
        } else {
            result.fail(new ClientErrorException(
                    HttpURLConnection.HTTP_PRECON_FAILED,
                    "must open receiver link for reply-to address first"));
        }
        return result.future();
    }
 
Example #25
Source File: RequestResponseEndpoint.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private void unregisterSenderForReplyTo(final String replyTo) {

        final ProtonSender sender = replyToSenderMap.remove(replyTo);
        if (sender == null) {
            logger.warn("sender was not allocated for replyTo address [{}]", replyTo);
        } else {
            logger.debug("deallocated sender [{}] for replies to [{}]", sender.getName(), replyTo);
        }

    }
 
Example #26
Source File: HelloWorld.java    From vertx-proton with Apache License 2.0 5 votes vote down vote up
private static void helloWorldSendAndConsumeExample(ProtonConnection connection) {
  connection.open();

  // Receive messages from queue "foo" (using an ActiveMQ style address as example).
  String address = "queue://foo";

  connection.createReceiver(address).handler((delivery, msg) -> {
    Section body = msg.getBody();
    if (body instanceof AmqpValue) {
      String content = (String) ((AmqpValue) body).getValue();
      System.out.println("Received message with content: " + content);
    }
    // By default, the receiver automatically accepts (and settles) the delivery
    // when the handler returns, if no other disposition has been applied.
    // To change this and always manage dispositions yourself, use the
    // setAutoAccept method on the receiver.
  }).open();

  // Create an anonymous (no address) sender, have the message carry its destination
  ProtonSender sender = connection.createSender(null);

  // Create a message to send, have it carry its destination for use with the anonymous sender
  Message message = message(address, "Hello World from client");

  // Can optionally add an openHandler or sendQueueDrainHandler
  // to await remote sender open completing or credit to send being
  // granted. But here we will just buffer the send immediately.
  sender.open();
  System.out.println("Sending message to server");
  sender.send(message, delivery -> {
    System.out.println(String.format("The message was received by the server: remote state=%s, remotely settled=%s",
        delivery.getRemoteState(), delivery.remotelySettled()));
  });
}
 
Example #27
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 #28
Source File: HonoProtonHelper.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Checks if a link is established.
 *
 * @param link The link to check.
 * @return {@code true} if the link has been established.
 */
public static boolean isLinkEstablished(final ProtonLink<?> link) {
    if (link instanceof ProtonSender) {
        return link.getRemoteTarget() != null;
    } else if (link instanceof ProtonReceiver) {
        return link.getRemoteSource() != null && link.getRemoteSource().getAddress() != null;
    } else {
        return false;
    }
}
 
Example #29
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 #30
Source File: AmqpAdapterTestBase.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a sender based on the connection to the AMQP adapter.
 *
 * @param target The target address to create the sender for or {@code null}
 *               if an anonymous sender should be created.
 * @return A future succeeding with the created sender.
 * @throws NullPointerException if qos is {@code null}.
 */
protected Future<ProtonSender> createProducer(final String target) {

    final Promise<ProtonSender>  result = Promise.promise();
    if (context == null) {
        result.fail(new IllegalStateException("not connected"));
    } else {
        context.runOnContext(go -> {
            final ProtonSender sender = connection.createSender(target);
            // vertx-proton doesn't support MIXED yet
            sender.setQoS(ProtonQoS.AT_LEAST_ONCE);
            sender.closeHandler(remoteClose -> {
                if (remoteClose.failed()) {
                    log.info("peer closed sender link [exception: {}]", remoteClose.cause().getClass().getName());
                    result.tryFail(remoteClose.cause());
                }
            });
            sender.openHandler(remoteAttach -> {
                if (remoteAttach.failed()) {
                    log.info("peer rejects opening of sender link", remoteAttach.cause());
                    result.fail(remoteAttach.cause());
                } else if (sender.getRemoteTarget() == null) {
                    log.info("peer wants to immediately close sender link");
                    result.fail("could not open sender link");
                } else {
                    result.complete(sender);
                }
            });
            sender.open();
        });
    }

    return result.future();
}