Search in sources :

Example 16 with InvalidResponseException

use of io.smallrye.graphql.client.InvalidResponseException in project smallrye-graphql by smallrye.

the class GraphQLTransportWSSubprotocolHandler method handleComplete.

private void handleComplete(String operationId) {
    UniEmitter<? super String> emitter = uniOperations.remove(operationId);
    if (emitter != null) {
        // For a uni operation, we should have received a 'next' message before the 'complete' message.
        // If that happened, the emitter was already completed and operation removed from the map.
        // If that didn't happen, then this is an issue with the server, let's fail the operation then.
        emitter.fail(new InvalidResponseException("Protocol error: received a 'complete' message for" + " this operation before the actual data"));
    } else {
        MultiEmitter<? super String> multiEmitter = multiOperations.remove(operationId);
        if (multiEmitter != null) {
            log.debug("Completed operation " + operationId);
            multiEmitter.complete();
        }
    }
}
Also used : InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException)

Example 17 with InvalidResponseException

use of io.smallrye.graphql.client.InvalidResponseException in project smallrye-graphql by smallrye.

the class GraphQLWSSubprotocolHandler method initialize.

private Uni<Void> initialize() {
    return Uni.createFrom().emitter(initializationEmitter -> {
        if (log.isTraceEnabled()) {
            log.trace("Initializing websocket with graphql-ws protocol");
        }
        webSocket.closeHandler((v) -> {
            onClose.run();
            if (webSocket.closeStatusCode() != null) {
                if (webSocket.closeStatusCode() == 1000) {
                    log.debug("WebSocket closed with status code 1000");
                    // even if the status code is OK, any unfinished single-result operation
                    // should be marked as failed
                    uniOperations.forEach((id, emitter) -> emitter.fail(new InvalidResponseException("Connection closed before data was received")));
                    multiOperations.forEach((id, emitter) -> emitter.complete());
                } else {
                    InvalidResponseException exception = new InvalidResponseException("Server closed the websocket connection with code: " + webSocket.closeStatusCode() + " and reason: " + webSocket.closeReason());
                    uniOperations.forEach((id, emitter) -> emitter.fail(exception));
                    multiOperations.forEach((id, emitter) -> emitter.fail(exception));
                }
            } else {
                InvalidResponseException exception = new InvalidResponseException("Connection closed");
                uniOperations.forEach((id, emitter) -> emitter.fail(exception));
                multiOperations.forEach((id, emitter) -> emitter.fail(exception));
            }
        });
        webSocket.exceptionHandler(this::failAllActiveOperationsWith);
        send(webSocket, createConnectionInitMessage());
        // set up a timeout for subscription initialization
        Cancellable timeoutWaitingForConnectionAckMessage = null;
        if (subscriptionInitializationTimeout != null) {
            timeoutWaitingForConnectionAckMessage = Uni.createFrom().item(1).onItem().delayIt().by(Duration.ofMillis(subscriptionInitializationTimeout)).subscribe().with(timeout -> {
                initializationEmitter.fail(new InvalidResponseException("Server did not send a connection_ack message"));
                webSocket.close((short) 1002, "Timeout waiting for a connection_ack message");
            });
        }
        // make an effectively final copy of this value to use it in a lambda expression
        Cancellable finalTimeoutWaitingForConnectionAckMessage = timeoutWaitingForConnectionAckMessage;
        webSocket.handler(text -> {
            if (log.isTraceEnabled()) {
                log.trace("<<< " + text);
            }
            try {
                JsonObject message = parseIncomingMessage(text.toString());
                MessageType messageType = getMessageType(message);
                switch(messageType) {
                    case GQL_CONNECTION_ERROR:
                        failAllActiveOperationsWith(new InvalidResponseException(message.get("payload").toString()));
                        webSocket.close();
                        break;
                    case GQL_CONNECTION_ACK:
                        if (finalTimeoutWaitingForConnectionAckMessage != null) {
                            finalTimeoutWaitingForConnectionAckMessage.cancel();
                        }
                        initializationEmitter.complete(null);
                        break;
                    case GQL_DATA:
                        handleData(message.getString("id"), message.getJsonObject("payload"));
                        break;
                    case GQL_ERROR:
                        handleOperationError(message.getString("id"), message.getJsonObject("payload"));
                        break;
                    case GQL_COMPLETE:
                        handleComplete(message.getString("id"));
                        break;
                    case GQL_START:
                    case GQL_STOP:
                    case GQL_CONNECTION_KEEP_ALIVE:
                    case GQL_CONNECTION_INIT:
                    case GQL_CONNECTION_TERMINATE:
                        break;
                }
            } catch (JsonParsingException | IllegalArgumentException e) {
                log.error("Unexpected message from server: " + text);
            // should we fail the operations here?
            }
        });
    });
}
Also used : JsonObject(javax.json.JsonObject) WebSocketSubprotocolHandler(io.smallrye.graphql.client.vertx.websocket.WebSocketSubprotocolHandler) GraphQLClientException(io.smallrye.graphql.client.GraphQLClientException) MultiEmitter(io.smallrye.mutiny.subscription.MultiEmitter) Logger(org.jboss.logging.Logger) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) UniEmitter(io.smallrye.mutiny.subscription.UniEmitter) CompletableFuture(java.util.concurrent.CompletableFuture) WebSocket(io.vertx.core.http.WebSocket) JsonString(javax.json.JsonString) Uni(io.smallrye.mutiny.Uni) JsonValue(javax.json.JsonValue) ResponseReader(io.smallrye.graphql.client.impl.ResponseReader) IncrementingNumberOperationIDGenerator(io.smallrye.graphql.client.vertx.websocket.opid.IncrementingNumberOperationIDGenerator) StringReader(java.io.StringReader) GraphQLError(io.smallrye.graphql.client.GraphQLError) OperationIDGenerator(io.smallrye.graphql.client.vertx.websocket.opid.OperationIDGenerator) Duration(java.time.Duration) Map(java.util.Map) Json(javax.json.Json) Cancellable(io.smallrye.mutiny.subscription.Cancellable) JsonParsingException(javax.json.stream.JsonParsingException) JsonObjectBuilder(javax.json.JsonObjectBuilder) InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException) Cancellable(io.smallrye.mutiny.subscription.Cancellable) JsonObject(javax.json.JsonObject) InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException) JsonParsingException(javax.json.stream.JsonParsingException)

Example 18 with InvalidResponseException

use of io.smallrye.graphql.client.InvalidResponseException in project smallrye-graphql by smallrye.

the class JsonArrayReader method readItem.

private Object readItem(IndexedLocationBuilder locationBuilder, JsonValue itemValue) {
    Location itemLocation = locationBuilder.nextLocation();
    TypeInfo itemType = getItemType();
    if (itemValue.getValueType() == ValueType.NULL && itemType.isNonNull())
        throw new InvalidResponseException("invalid null " + itemLocation);
    return JsonReader.readJson(itemLocation, itemType, itemValue, field);
}
Also used : TypeInfo(io.smallrye.graphql.client.impl.typesafe.reflection.TypeInfo) InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException)

Example 19 with InvalidResponseException

use of io.smallrye.graphql.client.InvalidResponseException in project smallrye-graphql by smallrye.

the class JsonMapReader method read.

@Override
Object read() {
    GraphQLClientValueHelper.check(location, value, type.isMap());
    MapLocationBuilder locationBuilder = new MapLocationBuilder(location);
    Map result = new HashMap<>();
    for (JsonValue entry : value) {
        Location keyLocation = locationBuilder.nextKeyLocation();
        Location valueLocation = locationBuilder.nextValueLocation();
        JsonValue keyJson = entry.asJsonObject().get(JSON_KEY_FOR_KEY);
        if (keyJson.getValueType() == JsonValue.ValueType.NULL) {
            throw new InvalidResponseException("unexpected null key at " + keyLocation);
        }
        JsonValue valueJson = entry.asJsonObject().get(JSON_KEY_FOR_VALUE);
        if (valueJson.getValueType() == JsonValue.ValueType.NULL && valueType.isNonNull()) {
            throw new InvalidResponseException("unexpected null value at " + keyLocation);
        }
        Object keyDeserialized = JsonReader.readJson(keyLocation, keyType, keyJson, field);
        Object valueDeserialized = JsonReader.readJson(valueLocation, valueType, valueJson, field);
        result.put(keyDeserialized, valueDeserialized);
    }
    return result;
}
Also used : HashMap(java.util.HashMap) JsonValue(javax.json.JsonValue) Map(java.util.Map) HashMap(java.util.HashMap) InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException)

Example 20 with InvalidResponseException

use of io.smallrye.graphql.client.InvalidResponseException in project smallrye-graphql by smallrye.

the class JsonObjectReader method buildValue.

private Object buildValue(Location location, JsonObject value, FieldInfo field) {
    String fieldName = field.getAlias().orElseGet(field::getName);
    Location fieldLocation = new Location(field.getType(), location.getDescription() + "." + fieldName);
    JsonValue jsonFieldValue = value.get(fieldName);
    if (jsonFieldValue == null) {
        if (field.isNonNull())
            throw new InvalidResponseException("missing " + fieldLocation);
        return null;
    }
    return readJson(fieldLocation, field.getType(), jsonFieldValue, field);
}
Also used : JsonValue(javax.json.JsonValue) InvalidResponseException(io.smallrye.graphql.client.InvalidResponseException)

Aggregations

InvalidResponseException (io.smallrye.graphql.client.InvalidResponseException)25 Test (org.junit.jupiter.api.Test)15 WebSocketSubprotocolHandler (io.smallrye.graphql.client.vertx.websocket.WebSocketSubprotocolHandler)4 JsonObject (javax.json.JsonObject)4 JsonValue (javax.json.JsonValue)4 Map (java.util.Map)3 JsonString (javax.json.JsonString)3 GraphQLClientException (io.smallrye.graphql.client.GraphQLClientException)2 GraphQLError (io.smallrye.graphql.client.GraphQLError)2 ResponseReader (io.smallrye.graphql.client.impl.ResponseReader)2 ResultBuilder (io.smallrye.graphql.client.impl.typesafe.ResultBuilder)2 IncrementingNumberOperationIDGenerator (io.smallrye.graphql.client.vertx.websocket.opid.IncrementingNumberOperationIDGenerator)2 OperationIDGenerator (io.smallrye.graphql.client.vertx.websocket.opid.OperationIDGenerator)2 Uni (io.smallrye.mutiny.Uni)2 Cancellable (io.smallrye.mutiny.subscription.Cancellable)2 MultiEmitter (io.smallrye.mutiny.subscription.MultiEmitter)2 UniEmitter (io.smallrye.mutiny.subscription.UniEmitter)2 WebSocket (io.vertx.core.http.WebSocket)2 StringReader (java.io.StringReader)2 Duration (java.time.Duration)2