All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pipservices4.grpc.clients.CommandableGrpcClient Maven / Gradle / Ivy

package org.pipservices4.grpc.clients;

import org.pipservices4.commons.convert.JsonConverter;
import org.pipservices4.commons.errors.ApplicationExceptionFactory;
import org.pipservices4.commons.errors.ErrorDescription;
import org.pipservices4.components.context.ContextResolver;
import org.pipservices4.components.context.IContext;
import org.pipservices4.grpc.commandable.CommandableGrpc;
import org.pipservices4.grpc.commandable.InvokeReply;
import org.pipservices4.grpc.commandable.InvokeRequest;

import java.util.Map;

/**
 * Abstract client that calls commandable GRPC service.
 * 

* Commandable services are generated automatically for {@link org.pipservices4.rpc.commands.ICommandable} objects. * Each command is exposed as Invoke method that receives all parameters as args. *

* ### Configuration parameters ### * *

 * - connection(s):
 *   - discovery_key:         (optional) a key to retrieve the connection from {@link org.pipservices4.config.connect.IDiscovery}
 *   - protocol:              connection protocol: http or https
 *   - host:                  host name or IP address
 *   - port:                  port number
 *   - uri:                   resource URI or connection string with all parameters in it
 * - options:
 *   - retries:               number of retries (default: 3)
 *   - connect_timeout:       connection timeout in milliseconds (default: 10 sec)
 *   - timeout:               invocation timeout in milliseconds (default: 10 sec)
 *   
*

* ### References ### *

* - *:logger:\*:\*:1.0 (optional) {@link org.pipservices4.observability.log.ILogger} components to pass log messages * - *:counters:\*:\*:1.0 (optional) {@link org.pipservices4.observability.count.ICounters} components to pass collected measurements * - *:discovery:*:*:1.0 (optional) {@link org.pipservices4.config.connect.IDiscovery} services to resolve connection * ### Example ### *

 * {@code
 * class MyCommandableGrpcClient extends CommandableGrpcClient implements IMyClient {
 *
 *     public MyCommandableGrpcClient() {
 *         super("mydata");
 *     }
 *
 *     // ...
 *
 *     @Override
 *     public MyData getData(IContext context, String id) {
 *         return this.callCommand(MyData.class,
 *                 "get_data",
 *                 context,
 *                 Map.of("id", id)
 *         );
 *     }
 *
 *     public static void main(String[] args) throws ConfigException {
 *         var client = new MyCommandableGrpcClient();
 *         client.configure(ConfigParams.fromTuples(
 *                 "connection.protocol", "http",
 *                 "connection.host", "localhost",
 *                 "connection.port", 8080
 *         ));
 *
 *         var result = client.getData("123", "1");
 *     }
 * }
 * }
 */
public class CommandableGrpcClient extends GrpcClient {
    /**
     * The service name
     */
    protected String _name;

    /**
     * Create new instance of the commandable client
     *
     * @param name The service name
     */
    public CommandableGrpcClient(String name) {
        super(CommandableGrpc.getServiceDescriptor());
        _name = name;
    }

    /**
     * Calls a remote method via GRPC commadable protocol.
     * The call is made via Invoke method and all parameters are sent in args object.
     * The complete route to remote method is defined as serviceName + "." + name.
     *
     * @param returnType    generic type of the return object
     * @param name          a name of the command to call.
     * @param context     (optional) a context to trace execution through call chain.
     * @param params        command parameters.
     * @return the received result.
     */
    protected  T callCommand(Class returnType, String name, IContext context, Object params) {
        var method = this._name + '.' + name;
        var timing = this.instrument(context, method);

        try {
            var request = InvokeRequest.newBuilder()
                    .setMethod(method)
                    .setArgsEmpty(params == null || params instanceof Map && ((Map) params).isEmpty());

            if (context != null)
                request.setTraceId(ContextResolver.getTraceId(context));

            if (params != null)
                request.setArgsJson(JsonConverter.toJson(params));

            InvokeReply response = this.call("invoke", context, request.build());

            // Handle error response
            if (!response.getError().getMessage().equals(""))
                throw ApplicationExceptionFactory.create(convertErrorDescription(response.getError()));


            // Handle empty response
            if (response.getResultEmpty() || response.getResultJson().equals("") || response.getResultJson().equals("{}")) {
                return null;
            }

            // Handle regular response
            return JsonConverter.fromJson(returnType, response.getResultJson());
        } catch (Exception ex) {
            timing.endFailure(ex);
            throw new RuntimeException(ex);
        } finally {
            timing.endSuccess();
        }
    }

    private ErrorDescription convertErrorDescription(org.pipservices4.grpc.commandable.ErrorDescription ex) {
        var err = new ErrorDescription();
        err.setStatus(ex.getStatus());
        err.setCause(ex.getCause());
        err.setTraceId(ex.getTraceId());
        err.setMessage(ex.getMessage());
        err.setCause(ex.getCause());
        err.setStackTrace(ex.getStackTrace());
        err.setCategory(ex.getCategory());
        err.setCode(ex.getCode());

        return err;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy