/** * Creates a {@link ServerServiceDefinition} for Avro Interface and its implementation that can * be passed a gRPC Server. * * @param iface Avro generated RPC service interface for which service defintion is created. * @param impl Implementation of the service interface to be invoked for requests. * @return a new server service definition. */ public static ServerServiceDefinition createServiceDefinition(Class iface, Object impl) { Protocol protocol = AvroGrpcUtils.getProtocol(iface); ServiceDescriptor serviceDescriptor = ServiceDescriptor.create(iface); ServerServiceDefinition.Builder serviceDefinitionBuilder = ServerServiceDefinition.builder (serviceDescriptor.getServiceName()); Map<String, Protocol.Message> messages = protocol.getMessages(); for (Method method : iface.getMethods()) { Protocol.Message msg = messages.get(method.getName()); //setup a method handler only if corresponding message exists in avro protocol. if (msg != null) { UnaryMethodHandler methodHandler = msg.isOneWay() ? new OneWayUnaryMethodHandler(impl, method) : new UnaryMethodHandler(impl, method); serviceDefinitionBuilder.addMethod(serviceDescriptor.getMethod(method.getName(), MethodDescriptor.MethodType.UNARY), ServerCalls.asyncUnaryCall(methodHandler)); } } return serviceDefinitionBuilder.build(); }
/** Writes a request message and reads a response or error message. */ public Object request(String messageName, Object request) throws Exception { // Initialize request Request rpcRequest = new Request(messageName, request, new RPCContext()); CallFuture<Object> future = /* only need a Future for two-way messages */ rpcRequest.getMessage().isOneWay() ? null : new CallFuture<>(); // Send request request(rpcRequest, future); if (future == null) // the message is one-way, so return immediately return null; try { // the message is two-way, wait for the result return future.get(); } catch (ExecutionException e) { if (e.getCause() instanceof Exception) { throw (Exception)e.getCause(); } else { throw new AvroRemoteException(e.getCause()); } } }
private Protocol addStringType(Protocol p) { if (stringType != StringType.String) return p; Protocol newP = new Protocol(p.getName(), p.getDoc(), p.getNamespace()); Map<Schema,Schema> types = new LinkedHashMap<>(); for (Map.Entry<String, Object> a : p.getObjectProps().entrySet()) { newP.addProp(a.getKey(), a.getValue()); } // annotate types Collection<Schema> namedTypes = new LinkedHashSet<>(); for (Schema s : p.getTypes()) namedTypes.add(addStringType(s, types)); newP.setTypes(namedTypes); // annotate messages Map<String,Message> newM = newP.getMessages(); for (Message m : p.getMessages().values()) newM.put(m.getName(), m.isOneWay() ? newP.createMessage(m, addStringType(m.getRequest(), types)) : newP.createMessage(m, addStringType(m.getRequest(), types), addStringType(m.getResponse(), types), addStringType(m.getErrors(), types))); return newP; }
if (m.isOneWay() && t.isConnected()) { // send one-way message t.writeBuffers(requestBytes); if (rm == null) throw new AvroRuntimeException("Not a remote message: "+messageName); if (m.isOneWay() != rm.isOneWay()) throw new AvroRuntimeException("Not both one-way messages: "+messageName); if (m.isOneWay() && t.isConnected()) return null; // one-way w/ handshake
private OutputFile compileInterface(Protocol protocol) { OutputFile outputFile = new OutputFile(); String mangledName = mangle(protocol.getName()); outputFile.path = makePath(mangledName, protocol.getNamespace()); StringBuilder out = new StringBuilder(); header(out, protocol.getNamespace()); doc(out, 1, protocol.getDoc()); line(out, 0, "public interface " + mangledName + " {"); line(out, 1, "public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse(\"" +esc(protocol)+"\");"); for (Map.Entry<String,Message> e : protocol.getMessages().entrySet()) { String name = e.getKey(); Message message = e.getValue(); Schema request = message.getRequest(); String response = message.isOneWay() ? "void" : unbox(message.getResponse()); doc(out, 1, e.getValue().getDoc()); line(out, 1, response+" "+ mangle(name)+"("+params(request)+")" + (message.isOneWay() ? "" : (" throws org.apache.avro.ipc.AvroRemoteException" +errors(message.getErrors()))) +";"); } line(out, 0, "}"); outputFile.contents = out.toString(); return outputFile; }
/** Writes a request message and reads a response or error message. */ public Object request(String messageName, Object request) throws Exception { // Initialize request Request rpcRequest = new Request(messageName, request, new RPCContext()); CallFuture<Object> future = /* only need a Future for two-way messages */ rpcRequest.getMessage().isOneWay() ? null : new CallFuture<Object>(); // Send request request(rpcRequest, future); if (future == null) // the message is one-way, so return immediately return null; try { // the message is two-way, wait for the result return future.get(); } catch (ExecutionException e) { if (e.getCause() instanceof Exception) { throw (Exception)e.getCause(); } else { throw new AvroRemoteException(e.getCause()); } } }
Protocol.Message value = entry.getValue(); Protocol.Message nvalue; if (value.isOneWay()) { Schema replacement = resolve(replacements, value.getRequest(), protocol); nvalue = result.createMessage(value.getName(), value.getDoc(),
private int writeResponse(OutputStream target) throws IOException { int written; if (message.isOneWay()) { written = 0; } else if (response instanceof Exception) {
@Override public Object parse(InputStream stream) { try { if (message.isOneWay()) return null; BinaryDecoder in = DECODER_FACTORY.binaryDecoder(stream, null); if (!in.readBoolean()) { Object response = new SpecificDatumReader(message.getResponse()).read(null, in); return response; } else { Object value = new SpecificDatumReader(message.getErrors()).read(null, in); if (value instanceof Exception) { return value; } return new AvroRuntimeException(value.toString()); } } catch (IOException e) { throw Status.INTERNAL.withCause(e). withDescription("Error deserializing avro response").asRuntimeException(); } finally { AvroGrpcUtils.skipAndCloseQuietly(stream); } }
@Test public void oneWay() throws Exception { Message m; // permit one-way messages w/ null response m = parseMessage("\"ack\": {" +"\"request\": []," +"\"response\": \"null\"," +"\"one-way\": true}"); assertTrue(m.isOneWay()); // permit one-way messages w/o response m = parseMessage("\"ack\": {" +"\"request\": []," +"\"one-way\": true}"); assertTrue(m.isOneWay()); }