/** Called by a server to deserialize a request, compute and serialize
* a response or error. */
public List<ByteBuffer> respond(List<ByteBuffer> buffers) throws IOException {
Decoder in = new BinaryDecoder(new ByteBufferInputStream(buffers));
ByteBufferOutputStream bbo = new ByteBufferOutputStream();
Encoder out = new BinaryEncoder(bbo);
AvroRemoteException error = null;
RPCContext context = new RPCContext();
try {
Protocol remote = handshake(in, out);
if (remote == null) // handshake failed
return bbo.getBufferList();
// read request using remote protocol specification
context.setRequestCallMeta(META_READER.read(null, in));
String messageName = in.readString(null).toString();
Message m = remote.getMessages().get(messageName);
if (m == null)
throw new AvroRuntimeException("No such remote message: "+messageName);
Object request = readRequest(m.getRequest(), in);
for (RPCPlugin plugin : rpcMetaPlugins) {
plugin.serverReceiveRequest(context);
}
// create response using local protocol specification
m = getLocal().getMessages().get(messageName);
if (m == null)
throw new AvroRuntimeException("No such local message: "+messageName);
Object response = null;
try {
response = respond(m, request);
context.setResponse(response);
} catch (AvroRemoteException e) {
error = e;
context.setError(error);
} catch (Exception e) {
LOG.warn("application error", e);
error = new AvroRemoteException(new Utf8(e.toString()));
context.setError(error);
}
for (RPCPlugin plugin : rpcMetaPlugins) {
plugin.serverSendResponse(context);
}
META_WRITER.write(context.responseCallMeta(), out);
out.writeBoolean(error != null);
if (error == null)
writeResponse(m.getResponse(), response, out);
else
writeError(m.getErrors(), error, out);
} catch (AvroRuntimeException e) { // system error
LOG.warn("system error", e);
error = new AvroRemoteException(e);
context.setError(error);
bbo = new ByteBufferOutputStream();
out = new BinaryEncoder(bbo);
META_WRITER.write(context.responseCallMeta(), out);
out.writeBoolean(true);
writeError(Protocol.SYSTEM_ERRORS, error, out);
}
return bbo.getBufferList();
}