use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class StandaloneEventApiTest method testMalformedMessageGetsRejected.
/**
* Verifies that malformed messages are not forwarded downstream.
*
* @param ctx The vert.x test context.
*/
@Test
public void testMalformedMessageGetsRejected(final TestContext ctx) {
final Message msg = ProtonHelper.message("malformed");
msg.setMessageId("malformed-message");
final Future<MessageSender> senderTracker = getSender(Constants.DEFAULT_TENANT);
senderTracker.compose(sender -> {
return sender.send(msg);
}).setHandler(ctx.asyncAssertFailure(t -> {
ctx.assertTrue(ClientErrorException.class.isInstance(t));
ctx.assertTrue(senderTracker.result().isOpen());
}));
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class ClientTestBase method connect.
/**
* Sets up the environment:
* <ol>
* <li>connect to the AMQP messaging network</li>
* <li>connects to the Hono Server</li>
* <li>connects to the Hono Device Registry</li>
* <li>creates a RegistrationClient for TEST_TENANT_ID</li>
* <li>creates a MessageSender for TEST_TENANT_ID</li>
* </ul>
*
* @param ctx The test context
*/
@Before
public void connect(final TestContext ctx) {
final ClientConfigProperties downstreamProps = new ClientConfigProperties();
downstreamProps.setHost(IntegrationTestSupport.DOWNSTREAM_HOST);
downstreamProps.setPort(IntegrationTestSupport.DOWNSTREAM_PORT);
downstreamProps.setPathSeparator(IntegrationTestSupport.PATH_SEPARATOR);
downstreamProps.setUsername(IntegrationTestSupport.RESTRICTED_CONSUMER_NAME);
downstreamProps.setPassword(IntegrationTestSupport.RESTRICTED_CONSUMER_PWD);
downstreamClient = new HonoClientImpl(vertx, ConnectionFactoryBuilder.newBuilder(downstreamProps).vertx(vertx).build(), downstreamProps);
final ClientConfigProperties honoProps = new ClientConfigProperties();
honoProps.setHost(IntegrationTestSupport.HONO_HOST);
honoProps.setPort(IntegrationTestSupport.HONO_PORT);
honoProps.setUsername(IntegrationTestSupport.HONO_USER);
honoProps.setPassword(IntegrationTestSupport.HONO_PWD);
honoClient = new HonoClientImpl(vertx, ConnectionFactoryBuilder.newBuilder(honoProps).vertx(vertx).build(), honoProps);
final ClientConfigProperties registryProps = new ClientConfigProperties();
registryProps.setHost(IntegrationTestSupport.HONO_DEVICEREGISTRY_HOST);
registryProps.setPort(IntegrationTestSupport.HONO_DEVICEREGISTRY_AMQP_PORT);
registryProps.setUsername(IntegrationTestSupport.HONO_USER);
registryProps.setPassword(IntegrationTestSupport.HONO_PWD);
honoDeviceRegistryClient = new HonoClientImpl(vertx, ConnectionFactoryBuilder.newBuilder(registryProps).vertx(vertx).build(), registryProps);
final ProtonClientOptions options = new ProtonClientOptions();
// connect to AMQP messaging network
final Future<HonoClient> downstreamTracker = downstreamClient.connect(options);
// create sender
final Future<MessageSender> senderTracker = honoClient.connect(options).compose(connectedClient -> createProducer(TEST_TENANT_ID)).map(s -> {
sender = s;
return s;
});
// create registration client
final Future<RegistrationClient> registrationClientTracker = honoDeviceRegistryClient.connect(options).compose(connectedClient -> connectedClient.getOrCreateRegistrationClient(TEST_TENANT_ID)).map(c -> {
registrationClient = c;
return c;
});
CompositeFuture.all(downstreamTracker, senderTracker, registrationClientTracker).setHandler(ctx.asyncAssertSuccess(s -> {
LOGGER.info("connections to Hono server, Hono device registry and AMQP messaging network established");
}));
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class AbstractVertxBasedHttpProtocolAdapterTest method givenATelemetrySenderForOutcome.
private void givenATelemetrySenderForOutcome(final Future<ProtonDelivery> outcome) {
final MessageSender sender = mock(MessageSender.class);
when(sender.send(any(Message.class))).thenReturn(outcome);
when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapter method uploadMessage.
private Future<Void> uploadMessage(final MqttContext ctx, final String tenant, final String deviceId, final Buffer payload, final Future<MessageSender> senderTracker, final String endpointName) {
if (payload.length() == 0) {
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "payload must not be empty"));
} else {
final Future<JsonObject> tokenTracker = getRegistrationAssertion(tenant, deviceId, ctx.authenticatedDevice());
final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant);
return CompositeFuture.all(tokenTracker, tenantConfigTracker, senderTracker).compose(ok -> {
if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
final Message downstreamMessage = newMessage(String.format("%s/%s", endpointName, tenant), deviceId, ctx.message().topicName(), ctx.contentType(), payload, tokenTracker.result());
customizeDownstreamMessage(downstreamMessage, ctx);
return senderTracker.result().send(downstreamMessage);
} else {
// this adapter is not enabled for the tenant
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
}
}).compose(delivery -> {
LOG.trace("successfully processed message [topic: {}, QoS: {}] for device [tenantId: {}, deviceId: {}]", ctx.message().topicName(), ctx.message().qosLevel(), tenant, deviceId);
metrics.incrementProcessedMqttMessages(endpointName, tenant);
onMessageSent(ctx);
// check that the remote MQTT client is still connected before sending PUBACK
if (ctx.deviceEndpoint().isConnected() && ctx.message().qosLevel() == MqttQoS.AT_LEAST_ONCE) {
ctx.deviceEndpoint().publishAcknowledge(ctx.message().messageId());
}
return Future.<Void>succeededFuture();
}).recover(t -> {
if (ClientErrorException.class.isInstance(t)) {
ClientErrorException e = (ClientErrorException) t;
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]: {} - {}", tenant, deviceId, endpointName, e.getErrorCode(), e.getMessage());
} else {
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]", tenant, deviceId, endpointName, t);
metrics.incrementUndeliverableMqttMessages(endpointName, tenant);
onMessageUndeliverable(ctx);
}
return Future.failedFuture(t);
});
}
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testUploadTelemetryMessageFailsForDisabledTenant.
/**
* Verifies that the adapter does not forward a message published by a device
* if the device belongs to a tenant for which the adapter has been disabled.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUploadTelemetryMessageFailsForDisabledTenant(final TestContext ctx) {
// GIVEN an adapter
final MqttServer server = getMqttServer(false);
// which is disabled for tenant "my-tenant"
final TenantObject myTenantConfig = TenantObject.from("my-tenant", true);
myTenantConfig.addAdapterConfiguration(new JsonObject().put(TenantConstants.FIELD_ADAPTERS_TYPE, ADAPTER_TYPE).put(TenantConstants.FIELD_ENABLED, false));
when(tenantClient.get("my-tenant")).thenReturn(Future.succeededFuture(myTenantConfig));
final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
forceClientMocksToConnected();
final MessageSender sender = mock(MessageSender.class);
when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
// WHEN a device of "my-tenant" publishes a telemetry message
adapter.uploadTelemetryMessage(new MqttContext(mock(MqttPublishMessage.class), mock(MqttEndpoint.class)), "my-tenant", "the-device", Buffer.buffer("test")).setHandler(ctx.asyncAssertFailure(t -> {
// THEN the message has not been sent downstream
verify(sender, never()).send(any(Message.class));
// because the tenant is not enabled
ctx.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, ((ClientErrorException) t).getErrorCode());
}));
}
Aggregations