/** Writes a request message and reads a response or error message. */
public synchronized Object request(String messageName, Object request)
throws Exception {
Transceiver t = getTransceiver();
BinaryDecoder in = null;
Message m;
RPCContext context = new RPCContext();
do {
ByteBufferOutputStream bbo = new ByteBufferOutputStream();
Encoder out = new BinaryEncoder(bbo);
// use local protocol to write request
m = getLocal().getMessages().get(messageName);
if (m == null)
throw new AvroRuntimeException("Not a local message: "+messageName);
context.setMessage(m);
writeRequest(m.getRequest(), request, out); // write request payload
List<ByteBuffer> payload = bbo.getBufferList();
writeHandshake(out); // prepend handshake if needed
META_WRITER.write(context.requestCallMeta(), out);
out.writeString(m.getName()); // write message name
context.setRequestPayload(payload);
for (RPCPlugin plugin : rpcMetaPlugins) {
plugin.clientSendRequest(context); // get meta-data from plugins
}
bbo.append(payload);
List<ByteBuffer> requestBytes = bbo.getBufferList();
if (m.isOneWay() && t.isConnected()) { // send one-way message
t.writeBuffers(requestBytes);
return null;
} else { // two-way message
List<ByteBuffer> response = t.transceive(requestBytes);
ByteBufferInputStream bbi = new ByteBufferInputStream(response);
in = DecoderFactory.defaultFactory().createBinaryDecoder(bbi, in);
}
} while (!readHandshake(in));
// use remote protocol to read response
Message rm = getRemote().getMessages().get(messageName);
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
context.setRequestCallMeta(META_READER.read(null, in));
if (!in.readBoolean()) { // no error
Object response = readResponse(rm.getResponse(), in);
context.setResponse(response);
for (RPCPlugin plugin : rpcMetaPlugins) {
plugin.clientReceiveResponse(context);
}
return response;
} else {
Exception error = readError(rm.getErrors(), in);
context.setError(error);
for (RPCPlugin plugin : rpcMetaPlugins) {
plugin.clientReceiveResponse(context);
}
throw error;