Search in sources :

Example 6 with ServerErrorException

use of org.eclipse.hono.client.ServerErrorException in project hono by eclipse.

the class AbstractRequestResponseClientTest method testCreateAndSendRequestFailsWithServerErrorExceptionIfSendQueueFull.

/**
 * Verifies that the client fails the handler for sending a request message
 * with a {@link ServerErrorException} if the link to the peer has no credit left.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateAndSendRequestFailsWithServerErrorExceptionIfSendQueueFull(final TestContext ctx) {
    // GIVEN a request-response client with a full send queue
    when(sender.sendQueueFull()).thenReturn(Boolean.TRUE);
    // WHEN sending a request message
    final Async sendFailure = ctx.async();
    client.createAndSendRequest("get", null, ctx.asyncAssertFailure(t -> {
        ctx.assertTrue(ServerErrorException.class.isInstance(t));
        sendFailure.complete();
    }));
    // THEN the message is not sent and the request result handler is failed
    sendFailure.await();
    verify(sender, never()).send(any(Message.class));
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) TestContext(io.vertx.ext.unit.TestContext) ProtonReceiver(io.vertx.proton.ProtonReceiver) CoreMatchers(org.hamcrest.CoreMatchers) Async(io.vertx.ext.unit.Async) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) RunWith(org.junit.runner.RunWith) ExpiringValueCache(org.eclipse.hono.cache.ExpiringValueCache) Context(io.vertx.core.Context) Assert.assertThat(org.junit.Assert.assertThat) ArgumentCaptor(org.mockito.ArgumentCaptor) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue) Target(org.apache.qpid.proton.amqp.transport.Target) Duration(java.time.Duration) Map(java.util.Map) Timeout(org.junit.rules.Timeout) Message(org.apache.qpid.proton.message.Message) JsonObject(io.vertx.core.json.JsonObject) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) Before(org.junit.Before) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Test(org.junit.Test) ProtonHelper(io.vertx.proton.ProtonHelper) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) MessageHelper(org.eclipse.hono.util.MessageHelper) Mockito(org.mockito.Mockito) Rule(org.junit.Rule) ProtonSender(io.vertx.proton.ProtonSender) Handler(io.vertx.core.Handler) Collections(java.util.Collections) Message(org.apache.qpid.proton.message.Message) Async(io.vertx.ext.unit.Async) Test(org.junit.Test)

Example 7 with ServerErrorException

use of org.eclipse.hono.client.ServerErrorException in project hono by eclipse.

the class AbstractRequestResponseClientTest method testCreateAndSendRequestFailsIfReceiverIsNotOpen.

/**
 * Verifies that a response handler is immediately failed with a
 * {@link ServerErrorException} when the receiver link is not open (yet).
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateAndSendRequestFailsIfReceiverIsNotOpen(final TestContext ctx) {
    // GIVEN a client whose sender and receiver are not open
    when(receiver.isOpen()).thenReturn(Boolean.FALSE);
    // WHEN sending a request
    Async requestFailure = ctx.async();
    client.createAndSendRequest("get", null, ctx.asyncAssertFailure(t -> {
        ctx.assertTrue(ServerErrorException.class.isInstance(t));
        requestFailure.complete();
    }));
    // THEN the request fails immediately
    requestFailure.await();
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) TestContext(io.vertx.ext.unit.TestContext) ProtonReceiver(io.vertx.proton.ProtonReceiver) CoreMatchers(org.hamcrest.CoreMatchers) Async(io.vertx.ext.unit.Async) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) RunWith(org.junit.runner.RunWith) ExpiringValueCache(org.eclipse.hono.cache.ExpiringValueCache) Context(io.vertx.core.Context) Assert.assertThat(org.junit.Assert.assertThat) ArgumentCaptor(org.mockito.ArgumentCaptor) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue) Target(org.apache.qpid.proton.amqp.transport.Target) Duration(java.time.Duration) Map(java.util.Map) Timeout(org.junit.rules.Timeout) Message(org.apache.qpid.proton.message.Message) JsonObject(io.vertx.core.json.JsonObject) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) Before(org.junit.Before) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Test(org.junit.Test) ProtonHelper(io.vertx.proton.ProtonHelper) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) MessageHelper(org.eclipse.hono.util.MessageHelper) Mockito(org.mockito.Mockito) Rule(org.junit.Rule) ProtonSender(io.vertx.proton.ProtonSender) Handler(io.vertx.core.Handler) Collections(java.util.Collections) Async(io.vertx.ext.unit.Async) Test(org.junit.Test)

Example 8 with ServerErrorException

use of org.eclipse.hono.client.ServerErrorException in project hono by eclipse.

the class AbstractRequestResponseClientTest method testCreateAndSendRequestFailsIfSenderIsNotOpen.

/**
 * Verifies that a response handler is immediately failed with a
 * {@link ServerErrorException} when the sender link is not open (yet).
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testCreateAndSendRequestFailsIfSenderIsNotOpen(final TestContext ctx) {
    // GIVEN a client whose sender and receiver are not open
    when(sender.isOpen()).thenReturn(Boolean.FALSE);
    // WHEN sending a request
    Async requestFailure = ctx.async();
    client.createAndSendRequest("get", null, ctx.asyncAssertFailure(t -> {
        ctx.assertTrue(ServerErrorException.class.isInstance(t));
        requestFailure.complete();
    }));
    // THEN the request fails immediately
    requestFailure.await();
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) TestContext(io.vertx.ext.unit.TestContext) ProtonReceiver(io.vertx.proton.ProtonReceiver) CoreMatchers(org.hamcrest.CoreMatchers) Async(io.vertx.ext.unit.Async) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) RunWith(org.junit.runner.RunWith) ExpiringValueCache(org.eclipse.hono.cache.ExpiringValueCache) Context(io.vertx.core.Context) Assert.assertThat(org.junit.Assert.assertThat) ArgumentCaptor(org.mockito.ArgumentCaptor) AmqpValue(org.apache.qpid.proton.amqp.messaging.AmqpValue) Target(org.apache.qpid.proton.amqp.transport.Target) Duration(java.time.Duration) Map(java.util.Map) Timeout(org.junit.rules.Timeout) Message(org.apache.qpid.proton.message.Message) JsonObject(io.vertx.core.json.JsonObject) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) Before(org.junit.Before) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Test(org.junit.Test) ProtonHelper(io.vertx.proton.ProtonHelper) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) MessageHelper(org.eclipse.hono.util.MessageHelper) Mockito(org.mockito.Mockito) Rule(org.junit.Rule) ProtonSender(io.vertx.proton.ProtonSender) Handler(io.vertx.core.Handler) Collections(java.util.Collections) Async(io.vertx.ext.unit.Async) Test(org.junit.Test)

Example 9 with ServerErrorException

use of org.eclipse.hono.client.ServerErrorException in project hono by eclipse.

the class AbstractRequestResponseClient method sendRequest.

/**
 * Sends a request message via this client's sender link to the peer.
 * <p>
 * This method first checks if the sender has any credit left. If not, the result handler is failed immediately.
 * Otherwise, the request message is sent and a timer is started which fails the result handler,
 * if no response is received within <em>requestTimeoutMillis</em> milliseconds.
 *
 * @param request The message to send.
 * @param resultHandler The handler to notify about the outcome of the request.
 * @param cacheKey The key to use for caching the response (if the service allows caching).
 */
private final void sendRequest(final Message request, final Handler<AsyncResult<R>> resultHandler, final Object cacheKey) {
    context.runOnContext(req -> {
        if (sender.sendQueueFull()) {
            LOG.debug("cannot send request to peer, no credit left for link [target: {}]", targetAddress);
            resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no credit available for sending request")));
        } else {
            final Object correlationId = Optional.ofNullable(request.getCorrelationId()).orElse(request.getMessageId());
            final TriTuple<Handler<AsyncResult<R>>, Object, Object> handler = TriTuple.of(resultHandler, cacheKey, null);
            replyMap.put(correlationId, handler);
            sender.send(request, deliveryUpdated -> {
                if (Rejected.class.isInstance(deliveryUpdated.getRemoteState())) {
                    final Rejected rejected = (Rejected) deliveryUpdated.getRemoteState();
                    if (rejected.getError() != null) {
                        LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]: {}", targetAddress, request.getSubject(), correlationId, rejected.getError());
                        cancelRequest(correlationId, Future.failedFuture(StatusCodeMapper.from(rejected.getError())));
                    } else {
                        LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]", targetAddress, request.getSubject(), correlationId);
                        cancelRequest(correlationId, Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)));
                    }
                } else if (Accepted.class.isInstance(deliveryUpdated.getRemoteState())) {
                    LOG.trace("service has accepted request [target address: {}, subject: {}, correlation ID: {}]", targetAddress, request.getSubject(), correlationId);
                } else {
                    LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]: {}", targetAddress, request.getSubject(), correlationId, deliveryUpdated.getRemoteState());
                    cancelRequest(correlationId, Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE)));
                }
            });
            if (requestTimeoutMillis > 0) {
                context.owner().setTimer(requestTimeoutMillis, tid -> {
                    cancelRequest(correlationId, Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "request timed out after " + requestTimeoutMillis + "ms")));
                });
            }
            if (LOG.isDebugEnabled()) {
                final String deviceId = MessageHelper.getDeviceId(request);
                if (deviceId == null) {
                    LOG.debug("sent request [target address: {}, subject: {}, correlation ID: {}] to service", targetAddress, request.getSubject(), correlationId);
                } else {
                    LOG.debug("sent request [target address: {}, subject: {}, correlation ID: {}, device ID: {}] to service", targetAddress, request.getSubject(), correlationId, deviceId);
                }
            }
        }
    });
}
Also used : Handler(io.vertx.core.Handler) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted)

Example 10 with ServerErrorException

use of org.eclipse.hono.client.ServerErrorException in project hono by eclipse.

the class HonoClientImpl method getOrCreateRequestResponseClient.

/**
 * Gets an existing or creates a new request-response client for a particular service.
 *
 * @param key The key to look-up the client by.
 * @param clientSupplier A consumer for an attempt to create a new client.
 * @param resultHandler The handler to inform about the outcome of the operation.
 */
void getOrCreateRequestResponseClient(final String key, final Supplier<Future<RequestResponseClient>> clientSupplier, final Handler<AsyncResult<RequestResponseClient>> resultHandler) {
    context.runOnContext(get -> {
        final RequestResponseClient client = activeRequestResponseClients.get(key);
        if (client != null && client.isOpen()) {
            LOG.debug("reusing existing client [target: {}]", key);
            resultHandler.handle(Future.succeededFuture(client));
        } else if (!creationLocks.computeIfAbsent(key, k -> Boolean.FALSE)) {
            // register a handler to be notified if the underlying connection to the server fails
            // so that we can fail the result handler passed in
            final Handler<Void> connectionFailureHandler = connectionLost -> {
                // remove lock so that next attempt to open a sender doesn't fail
                creationLocks.remove(key);
                resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service")));
            };
            creationRequests.add(connectionFailureHandler);
            creationLocks.put(key, Boolean.TRUE);
            LOG.debug("creating new client for {}", key);
            clientSupplier.get().setHandler(creationAttempt -> {
                if (creationAttempt.succeeded()) {
                    LOG.debug("successfully created new client for {}", key);
                    activeRequestResponseClients.put(key, creationAttempt.result());
                } else {
                    LOG.debug("failed to create new client for {}", key, creationAttempt.cause());
                    activeRequestResponseClients.remove(key);
                }
                creationLocks.remove(key);
                creationRequests.remove(connectionFailureHandler);
                resultHandler.handle(creationAttempt);
            });
        } else {
            LOG.debug("already trying to create a client for {}", key);
            resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service")));
        }
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) RequestResponseClient(org.eclipse.hono.client.RequestResponseClient) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonDelivery(io.vertx.proton.ProtonDelivery) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) MessageConsumer(org.eclipse.hono.client.MessageConsumer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Supplier(java.util.function.Supplier) Constants(org.eclipse.hono.util.Constants) Context(io.vertx.core.Context) ArrayList(java.util.ArrayList) ConnectionFactory(org.eclipse.hono.connection.ConnectionFactory) CredentialsClient(org.eclipse.hono.client.CredentialsClient) ProtonClientOptions(io.vertx.proton.ProtonClientOptions) TenantClient(org.eclipse.hono.client.TenantClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConnectionFactoryBuilder(org.eclipse.hono.connection.ConnectionFactoryImpl.ConnectionFactoryBuilder) Map(java.util.Map) MessageSender(org.eclipse.hono.client.MessageSender) BiConsumer(java.util.function.BiConsumer) Message(org.apache.qpid.proton.message.Message) RegistrationClient(org.eclipse.hono.client.RegistrationClient) AsyncResult(io.vertx.core.AsyncResult) HonoClient(org.eclipse.hono.client.HonoClient) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CacheProvider(org.eclipse.hono.cache.CacheProvider) Future(io.vertx.core.Future) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Handler(io.vertx.core.Handler) RequestResponseClient(org.eclipse.hono.client.RequestResponseClient) Handler(io.vertx.core.Handler) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Aggregations

ServerErrorException (org.eclipse.hono.client.ServerErrorException)14 Handler (io.vertx.core.Handler)9 Vertx (io.vertx.core.Vertx)8 ProtonDelivery (io.vertx.proton.ProtonDelivery)8 HttpURLConnection (java.net.HttpURLConnection)8 JsonObject (io.vertx.core.json.JsonObject)7 Message (org.apache.qpid.proton.message.Message)7 ClientConfigProperties (org.eclipse.hono.config.ClientConfigProperties)7 Context (io.vertx.core.Context)6 TestContext (io.vertx.ext.unit.TestContext)6 VertxUnitRunner (io.vertx.ext.unit.junit.VertxUnitRunner)6 Map (java.util.Map)6 Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)6 ClientErrorException (org.eclipse.hono.client.ClientErrorException)6 Async (io.vertx.ext.unit.Async)5 Test (org.junit.Test)5 Future (io.vertx.core.Future)4 AmqpValue (org.apache.qpid.proton.amqp.messaging.AmqpValue)4 Before (org.junit.Before)4 Rule (org.junit.Rule)4