Ballerina

copy sample and run.

orderMgt.proto

syntax = "proto3";
package grpc_service;
import "google/protobuf/wrappers.proto";
 
service orderMgt {
  rpc findOrder(google.protobuf.StringValue) returns (google.protobuf.StringValue);
  rpc addOrder(orderInfo) returns (google.protobuf.StringValue);
  rpc updateOrder(orderInfo) returns (google.protobuf.StringValue);
  rpc cancelOrder(google.protobuf.StringValue) returns (google.protobuf.StringValue);
}
message orderInfo {
  string id = 1;
  string name = 2;
  string description = 3;
}

order_mgt_service.bal

import ballerina/grpc;
import ballerina/log;
 
// gRPC service endpoint definition.
listener grpc:Listener ep = new (3000);
 
// Order management is done using an in memory map.
// Add some sample orders to 'orderMap' at startup.
map<orderInfo> ordersMap = {};
 
// gRPC service.
service orderMgt on ep {
 
    // gRPC method to find an order.
    resource function findOrder(grpc:Caller caller, string orderId) {
        string payload = "";
        error? result = ();
        // Find the requested order from the map.
        if (ordersMap.hasKey(orderId)) {
            var jsonValue = json.convert(ordersMap[orderId]);
            if (jsonValue is error) {
                // Send casting error as internal error.
                result = caller->sendError(grpc:INTERNAL, <string>jsonValue.detail().message);
            } else {
                json orderDetails = jsonValue;
                payload = orderDetails.toString();
                // Send response to the caller.
                result = caller->send(payload);
                result = caller->complete();
            }
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
 
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to create a new Order.
    resource function addOrder(grpc:Caller caller, orderInfo orderReq) {
        // Add the new order to the map.
        string orderId = orderReq.id;
        ordersMap[orderReq.id] = orderReq;
        // Create response message.
        string payload = "Status : Order created; OrderID : " + orderId;
 
        // Send response to the caller.
        error? result = caller->send(payload);
        result = caller->complete();
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to update an existing Order.
    resource function updateOrder(grpc:Caller caller, orderInfo updatedOrder) {
        string payload;
        error? result = ();
        // Find the order that needs to be updated.
        string orderId = updatedOrder.id;
        if (ordersMap.hasKey(orderId)) {
            // Update the existing order.
            ordersMap[orderId] = updatedOrder;
            payload = "Order : '" + orderId + "' updated.";
            // Send response to the caller.
            result = caller->send(payload);
            result = caller->complete();
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
 
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to delete an existing Order.
    resource function cancelOrder(grpc:Caller caller, string orderId) {
        string payload;
        error? result = ();
        // Find the order that needs to be updated.
        if (ordersMap.hasKey(orderId)) {
            // Remove the requested order from the map.
            _ = ordersMap.remove(orderId);
            payload = "Order : '" + orderId + "' removed.";
            // Send response to the caller.
            result = caller->send(payload);
            result = caller->complete();
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
}
 
For simplicity, we use an in-memory map to record all the order details. As shown in the above code, to create a gRPC service you need to import the ballerina/grpc and define a grpc:Listener endpoint. 

grpc_service/orderMgt_sample_service.bal

import ballerina/grpc;
import ballerina/log;
 
// gRPC service endpoint definition.
listener grpc:Listener ep = new (9090);
 
// Order management is done using an in memory map.
// Add some sample orders to 'orderMap' at startup.
map<orderInfo> ordersMap = {};
 
// gRPC service.
service orderMgt on ep {
 
  // gRPC method to find an order.
  resource function findOrder(grpc:Caller caller, string orderId) {
    string payload = "";
    error? result = ();
    // Find the requested order from the map.
    if (ordersMap.hasKey(orderId)) {
      var jsonValue = json.convert(ordersMap[orderId]);
      if (jsonValue is error) {
        // Send casting error as internal error.
        result = caller->sendError(grpc:INTERNAL, <string>jsonValue.detail().message);
      } else {
        json orderDetails = jsonValue;
        payload = orderDetails.toString();
        // Send response to the caller.
        result = caller->send(payload);
        result = caller->complete();
      }
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
 
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to create a new Order.
  resource function addOrder(grpc:Caller caller, orderInfo orderReq) {
    // Add the new order to the map.
    string orderId = orderReq.id;
    ordersMap[orderReq.id] = orderReq;
    // Create response message.
    string payload = "Status : Order created; OrderID : " + orderId;
 
    // Send response to the caller.
    error? result = caller->send(payload);
    result = caller->complete();
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to update an existing Order.
  resource function updateOrder(grpc:Caller caller, orderInfo updatedOrder) {
    string payload;
    error? result = ();
    // Find the order that needs to be updated.
    string orderId = updatedOrder.id;
    if (ordersMap.hasKey(orderId)) {
      // Update the existing order.
      ordersMap[orderId] = updatedOrder;
      payload = "Order : '" + orderId + "' updated.";
      // Send response to the caller.
      result = caller->send(payload);
      result = caller->complete();
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
 
    if (result is error) {
        log:printError("Error from Connector: " + result.reason() + " - "
           <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to delete an existing Order.
  resource function cancelOrder(grpc:Caller caller, string orderId) {
    string payload;
    error? result = ();
    // Find the order that needs to be updated.
    if (ordersMap.hasKey(orderId)) {
      // Remove the requested order from the map.
      _ = ordersMap.remove(orderId);
      payload = "Order : '" + orderId + "' removed.";
      // Send response to the caller.
      result = caller->send(payload);
      result = caller->complete();
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
}

grpc_client/orderMgt_sample_client.bal

import ballerina/grpc;
import ballerina/io;
import ballerina/log;
 
// This is client implementation for unary blocking scenario
public function main(string... args) {
    // Client endpoint configuration
    orderMgtBlockingClient orderMgtBlockingEp = new("http://localhost:9090");
 
    // Create an order
    log:printInfo("-----------------------Create a new order-----------------------");
    orderInfo orderReq = {id:"100500", name:"XYZ", description:"Sample order."};
    var addResponse = orderMgtBlockingEp->addOrder(orderReq);
    if (addResponse is error) {
        log:printError("Error from Connector: " + addResponse.reason() + " - "
                                                 <string>addResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = addResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Update an order
    log:printInfo("--------------------Update an existing order--------------------");
    orderInfo updateReq = {id:"100500", name:"XYZ", description:"Updated."};
    var updateResponse = orderMgtBlockingEp->updateOrder(updateReq);
    if (updateResponse is error) {
        log:printError("Error from Connector: " + updateResponse.reason() + " - "
                                                 <string>updateResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = updateResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Find an order
    log:printInfo("---------------------Find an existing order---------------------");
    var findResponse = orderMgtBlockingEp->findOrder("100500");
    if (findResponse is error) {
        log:printError("Error from Connector: " + findResponse.reason() + " - "
                                                 <string>findResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = findResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Cancel an order
    log:printInfo("-------------------------Cancel an order------------------------");
    var cancelResponse = orderMgtBlockingEp->cancelOrder("100500");
    if (cancelResponse is error) {
        log:printError("Error from Connector: " + cancelResponse.reason() + " - "
                 <string>cancelResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = cancelResponse;
        log:printInfo("Response - " + result + "\n");
    }
}
 
service orderMgtMessageListener = service {
 
    resource function onMessage(string message) {
        io:println("Response received from server: " + message);
    }
 
    resource function onError(error err) {
        io:println("Error from Connector: " + err.reason() + " - " + <string>err.detail().message);
    }
 
    resource function onComplete() {
        io:println("Server Complete Sending Responses.");
    }
};
 
 
```# Ballerina
## 2019/4/10 - ballerina_grpc
copy [sample](https://ballerina.io/learn/by-guide/grpc-service/) and run.
 
### orderMgt.proto
```proto
syntax = "proto3";
package grpc_service;
import "google/protobuf/wrappers.proto";
 
service orderMgt {
  rpc findOrder(google.protobuf.StringValue) returns (google.protobuf.StringValue);
  rpc addOrder(orderInfo) returns (google.protobuf.StringValue);
  rpc updateOrder(orderInfo) returns (google.protobuf.StringValue);
  rpc cancelOrder(google.protobuf.StringValue) returns (google.protobuf.StringValue);
}
message orderInfo {
  string id = 1;
  string name = 2;
  string description = 3;
}

order_mgt_service.bal

import ballerina/grpc;
import ballerina/log;
 
// gRPC service endpoint definition.
listener grpc:Listener ep = new (3000);
 
// Order management is done using an in memory map.
// Add some sample orders to 'orderMap' at startup.
map<orderInfo> ordersMap = {};
 
// gRPC service.
service orderMgt on ep {
 
    // gRPC method to find an order.
    resource function findOrder(grpc:Caller caller, string orderId) {
        string payload = "";
        error? result = ();
        // Find the requested order from the map.
        if (ordersMap.hasKey(orderId)) {
            var jsonValue = json.convert(ordersMap[orderId]);
            if (jsonValue is error) {
                // Send casting error as internal error.
                result = caller->sendError(grpc:INTERNAL, <string>jsonValue.detail().message);
            } else {
                json orderDetails = jsonValue;
                payload = orderDetails.toString();
                // Send response to the caller.
                result = caller->send(payload);
                result = caller->complete();
            }
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
 
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to create a new Order.
    resource function addOrder(grpc:Caller caller, orderInfo orderReq) {
        // Add the new order to the map.
        string orderId = orderReq.id;
        ordersMap[orderReq.id] = orderReq;
        // Create response message.
        string payload = "Status : Order created; OrderID : " + orderId;
 
        // Send response to the caller.
        error? result = caller->send(payload);
        result = caller->complete();
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to update an existing Order.
    resource function updateOrder(grpc:Caller caller, orderInfo updatedOrder) {
        string payload;
        error? result = ();
        // Find the order that needs to be updated.
        string orderId = updatedOrder.id;
        if (ordersMap.hasKey(orderId)) {
            // Update the existing order.
            ordersMap[orderId] = updatedOrder;
            payload = "Order : '" + orderId + "' updated.";
            // Send response to the caller.
            result = caller->send(payload);
            result = caller->complete();
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
 
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
 
    // gRPC method to delete an existing Order.
    resource function cancelOrder(grpc:Caller caller, string orderId) {
        string payload;
        error? result = ();
        // Find the order that needs to be updated.
        if (ordersMap.hasKey(orderId)) {
            // Remove the requested order from the map.
            _ = ordersMap.remove(orderId);
            payload = "Order : '" + orderId + "' removed.";
            // Send response to the caller.
            result = caller->send(payload);
            result = caller->complete();
        } else {
            // Send entity not found error.
            payload = "Order : '" + orderId + "' cannot be found.";
            result = caller->sendError(grpc:NOT_FOUND, payload);
        }
        if (result is error) {
            log:printError("Error from Connector: " + result.reason() + " - "
                     <string>result.detail().message + "\n");
        }
    }
}
 
For simplicity, we use an in-memory map to record all the order details. As shown in the above code, to create a gRPC service you need to import the ballerina/grpc and define a grpc:Listener endpoint. 

grpc_service/orderMgt_sample_service.bal

import ballerina/grpc;
import ballerina/log;
 
// gRPC service endpoint definition.
listener grpc:Listener ep = new (9090);
 
// Order management is done using an in memory map.
// Add some sample orders to 'orderMap' at startup.
map<orderInfo> ordersMap = {};
 
// gRPC service.
service orderMgt on ep {
 
  // gRPC method to find an order.
  resource function findOrder(grpc:Caller caller, string orderId) {
    string payload = "";
    error? result = ();
    // Find the requested order from the map.
    if (ordersMap.hasKey(orderId)) {
      var jsonValue = json.convert(ordersMap[orderId]);
      if (jsonValue is error) {
        // Send casting error as internal error.
        result = caller->sendError(grpc:INTERNAL, <string>jsonValue.detail().message);
      } else {
        json orderDetails = jsonValue;
        payload = orderDetails.toString();
        // Send response to the caller.
        result = caller->send(payload);
        result = caller->complete();
      }
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
 
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to create a new Order.
  resource function addOrder(grpc:Caller caller, orderInfo orderReq) {
    // Add the new order to the map.
    string orderId = orderReq.id;
    ordersMap[orderReq.id] = orderReq;
    // Create response message.
    string payload = "Status : Order created; OrderID : " + orderId;
 
    // Send response to the caller.
    error? result = caller->send(payload);
    result = caller->complete();
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to update an existing Order.
  resource function updateOrder(grpc:Caller caller, orderInfo updatedOrder) {
    string payload;
    error? result = ();
    // Find the order that needs to be updated.
    string orderId = updatedOrder.id;
    if (ordersMap.hasKey(orderId)) {
      // Update the existing order.
      ordersMap[orderId] = updatedOrder;
      payload = "Order : '" + orderId + "' updated.";
      // Send response to the caller.
      result = caller->send(payload);
      result = caller->complete();
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
 
    if (result is error) {
        log:printError("Error from Connector: " + result.reason() + " - "
           <string>result.detail().message + "\n");
    }
  }
 
  // gRPC method to delete an existing Order.
  resource function cancelOrder(grpc:Caller caller, string orderId) {
    string payload;
    error? result = ();
    // Find the order that needs to be updated.
    if (ordersMap.hasKey(orderId)) {
      // Remove the requested order from the map.
      _ = ordersMap.remove(orderId);
      payload = "Order : '" + orderId + "' removed.";
      // Send response to the caller.
      result = caller->send(payload);
      result = caller->complete();
    } else {
      // Send entity not found error.
      payload = "Order : '" + orderId + "' cannot be found.";
      result = caller->sendError(grpc:NOT_FOUND, payload);
    }
    if (result is error) {
      log:printError("Error from Connector: " + result.reason() + " - "
         <string>result.detail().message + "\n");
    }
  }
}

grpc_client/orderMgt_sample_client.bal

import ballerina/grpc;
import ballerina/io;
import ballerina/log;
 
// This is client implementation for unary blocking scenario
public function main(string... args) {
    // Client endpoint configuration
    orderMgtBlockingClient orderMgtBlockingEp = new("http://localhost:9090");
 
    // Create an order
    log:printInfo("-----------------------Create a new order-----------------------");
    orderInfo orderReq = {id:"100500", name:"XYZ", description:"Sample order."};
    var addResponse = orderMgtBlockingEp->addOrder(orderReq);
    if (addResponse is error) {
        log:printError("Error from Connector: " + addResponse.reason() + " - "
                                                 <string>addResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = addResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Update an order
    log:printInfo("--------------------Update an existing order--------------------");
    orderInfo updateReq = {id:"100500", name:"XYZ", description:"Updated."};
    var updateResponse = orderMgtBlockingEp->updateOrder(updateReq);
    if (updateResponse is error) {
        log:printError("Error from Connector: " + updateResponse.reason() + " - "
                                                 <string>updateResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = updateResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Find an order
    log:printInfo("---------------------Find an existing order---------------------");
    var findResponse = orderMgtBlockingEp->findOrder("100500");
    if (findResponse is error) {
        log:printError("Error from Connector: " + findResponse.reason() + " - "
                                                 <string>findResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = findResponse;
        log:printInfo("Response - " + result + "\n");
    }
 
    // Cancel an order
    log:printInfo("-------------------------Cancel an order------------------------");
    var cancelResponse = orderMgtBlockingEp->cancelOrder("100500");
    if (cancelResponse is error) {
        log:printError("Error from Connector: " + cancelResponse.reason() + " - "
                 <string>cancelResponse.detail().message + "\n");
    } else {
        string result;
        grpc:Headers resHeaders;
        (result, resHeaders) = cancelResponse;
        log:printInfo("Response - " + result + "\n");
    }
}
 
service orderMgtMessageListener = service {
 
    resource function onMessage(string message) {
        io:println("Response received from server: " + message);
    }
 
    resource function onError(error err) {
        io:println("Error from Connector: " + err.reason() + " - " + <string>err.detail().message);
    }
 
    resource function onComplete() {
        io:println("Server Complete Sending Responses.");
    }
};