writeObject now throws XmlRpcException.
If an Error occurs while writing a response, a valid error message is generated.
This commit is contained in:
parent
9a1f750707
commit
ef36481edd
5 changed files with 50 additions and 31 deletions
|
@ -11,15 +11,15 @@ public class Benchmark implements Runnable {
|
||||||
|
|
||||||
XmlRpcClient client;
|
XmlRpcClient client;
|
||||||
static String url;
|
static String url;
|
||||||
static int clients = 8;
|
static int clients = 16;
|
||||||
static int loops = 200;
|
static int loops = 100;
|
||||||
|
|
||||||
int gCalls = 0, gErrors = 0;
|
int gCalls = 0, gErrors = 0;
|
||||||
|
|
||||||
Date date;
|
Date date;
|
||||||
|
|
||||||
public Benchmark () throws Exception {
|
public Benchmark () throws Exception {
|
||||||
client = new XmlRpcClient (url);
|
client = new XmlRpcClientLite (url);
|
||||||
|
|
||||||
Vector args = new Vector ();
|
Vector args = new Vector ();
|
||||||
// Some JITs (Symantec, IBM) have problems with several Threads
|
// Some JITs (Symantec, IBM) have problems with several Threads
|
||||||
|
|
|
@ -239,7 +239,7 @@ public abstract class XmlRpc extends HandlerBase {
|
||||||
/**
|
/**
|
||||||
* Writes the XML representation of a supported Java object to the XML writer.
|
* Writes the XML representation of a supported Java object to the XML writer.
|
||||||
*/
|
*/
|
||||||
void writeObject (Object what, XmlWriter writer) {
|
void writeObject (Object what, XmlWriter writer) throws XmlRpcException {
|
||||||
writer.startElement ("value");
|
writer.startElement ("value");
|
||||||
if (what == null) {
|
if (what == null) {
|
||||||
// try sending experimental <ni/> element
|
// try sending experimental <ni/> element
|
||||||
|
@ -295,7 +295,7 @@ public abstract class XmlRpc extends HandlerBase {
|
||||||
}
|
}
|
||||||
writer.endElement ("struct");
|
writer.endElement ("struct");
|
||||||
} else
|
} else
|
||||||
throw new RuntimeException ("unsupported Java type: " + what.getClass ());
|
throw new XmlRpcException (0, "Java class not supported in XML-RPC: " + what.getClass ());
|
||||||
writer.endElement ("value");
|
writer.endElement ("value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +542,7 @@ public abstract class XmlRpc extends HandlerBase {
|
||||||
|
|
||||||
public XmlWriter (StringBuffer buf, String enc) {
|
public XmlWriter (StringBuffer buf, String enc) {
|
||||||
this.buf = buf;
|
this.buf = buf;
|
||||||
|
buf.setLength (0);
|
||||||
this.enc = enc;
|
this.enc = enc;
|
||||||
// get name of encoding for XML prolog
|
// get name of encoding for XML prolog
|
||||||
String encName = encodings.getProperty (enc, enc);
|
String encName = encodings.getProperty (enc, enc);
|
||||||
|
|
|
@ -24,6 +24,8 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
// pool of worker instances
|
// pool of worker instances
|
||||||
Stack pool = new Stack ();
|
Stack pool = new Stack ();
|
||||||
int workers = 0;
|
int workers = 0;
|
||||||
|
int asyncWorkers = 0;
|
||||||
|
|
||||||
|
|
||||||
// average roundtrip of this method call. This is used to decide if
|
// average roundtrip of this method call. This is used to decide if
|
||||||
// additional threads are needed or not in async mode
|
// additional threads are needed or not in async mode
|
||||||
|
@ -82,7 +84,7 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
* @exception IOException: If the call could not be made because of lower level problems.
|
* @exception IOException: If the call could not be made because of lower level problems.
|
||||||
*/
|
*/
|
||||||
public Object execute (String method, Vector params) throws XmlRpcException, IOException {
|
public Object execute (String method, Vector params) throws XmlRpcException, IOException {
|
||||||
Worker worker = getWorker ();
|
Worker worker = getWorker (false);
|
||||||
long start = System.currentTimeMillis ();
|
long start = System.currentTimeMillis ();
|
||||||
try {
|
try {
|
||||||
Object retval = worker.execute (method, params);
|
Object retval = worker.execute (method, params);
|
||||||
|
@ -90,7 +92,7 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
roundtrip = (int) ((roundtrip*4)+(end-start))/5;
|
roundtrip = (int) ((roundtrip*4)+(end-start))/5;
|
||||||
return retval;
|
return retval;
|
||||||
} finally {
|
} finally {
|
||||||
releaseWorker (worker);
|
releaseWorker (worker, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +103,13 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void executeAsync (String method, Vector params, AsyncCallback callback) {
|
public void executeAsync (String method, Vector params, AsyncCallback callback) {
|
||||||
if (workers > 2) {
|
if (asyncWorkers > 2) {
|
||||||
enqueue (method, params, callback);
|
enqueue (method, params, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Worker worker = null;
|
Worker worker = null;
|
||||||
try {
|
try {
|
||||||
worker = getWorker ();
|
worker = getWorker (true);
|
||||||
worker.executeAsync (method, params, callback);
|
worker.executeAsync (method, params, callback);
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
// make a queued worker that doesn't run immediately
|
// make a queued worker that doesn't run immediately
|
||||||
|
@ -116,13 +118,19 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
synchronized Worker getWorker () throws IOException {
|
synchronized Worker getWorker (boolean async) throws IOException {
|
||||||
try {
|
try {
|
||||||
Worker w = (Worker) pool.pop ();
|
Worker w = (Worker) pool.pop ();
|
||||||
|
if (async)
|
||||||
|
asyncWorkers += 1;
|
||||||
|
else
|
||||||
workers += 1;
|
workers += 1;
|
||||||
return w;
|
return w;
|
||||||
} catch (EmptyStackException x) {
|
} catch (EmptyStackException x) {
|
||||||
if (workers < maxThreads) {
|
if (workers < maxThreads) {
|
||||||
|
if (async)
|
||||||
|
asyncWorkers += 1;
|
||||||
|
else
|
||||||
workers += 1;
|
workers += 1;
|
||||||
return new Worker ();
|
return new Worker ();
|
||||||
}
|
}
|
||||||
|
@ -133,11 +141,14 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
/**
|
/**
|
||||||
* Release possibly big per-call object references to allow them to be garbage collected
|
* Release possibly big per-call object references to allow them to be garbage collected
|
||||||
*/
|
*/
|
||||||
synchronized void releaseWorker (Worker w) {
|
synchronized void releaseWorker (Worker w, boolean async) {
|
||||||
w.result = null;
|
w.result = null;
|
||||||
w.call = null;
|
w.call = null;
|
||||||
if (pool.size() < 20 && !w.fault)
|
if (pool.size() < 20 && !w.fault)
|
||||||
pool.push (w);
|
pool.push (w);
|
||||||
|
if (async)
|
||||||
|
asyncWorkers -= 1;
|
||||||
|
else
|
||||||
workers -= 1;
|
workers -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +166,8 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
synchronized CallData dequeue () {
|
synchronized CallData dequeue () {
|
||||||
if (first == null)
|
if (first == null)
|
||||||
return null;
|
return null;
|
||||||
// if (workers > 2 && workers*4 > roundtrip)
|
if (asyncWorkers > 4 && asyncWorkers*4 > roundtrip)
|
||||||
// return null;
|
return null;
|
||||||
CallData call = first;
|
CallData call = first;
|
||||||
if (first == last)
|
if (first == last)
|
||||||
first = last = null;
|
first = last = null;
|
||||||
|
@ -187,11 +198,9 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
public void run () {
|
public void run () {
|
||||||
while (call != null) {
|
while (call != null) {
|
||||||
runAsync (call.method, call.params, call.callback);
|
runAsync (call.method, call.params, call.callback);
|
||||||
// System.err.println (workers+" ---- "+ roundtrip);
|
|
||||||
call = dequeue ();
|
call = dequeue ();
|
||||||
// if (call != null) System.err.print (".");
|
|
||||||
}
|
}
|
||||||
releaseWorker (this);
|
releaseWorker (this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runAsync (String method, Vector params, AsyncCallback callback) {
|
void runAsync (String method, Vector params, AsyncCallback callback) {
|
||||||
|
@ -203,8 +212,9 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.handleResult (res, url, method);
|
callback.handleResult (res, url, method);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (callback != null)
|
if (callback != null) try {
|
||||||
callback.handleError (x, url, method);
|
callback.handleError (x, url, method);
|
||||||
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
long end = System.currentTimeMillis ();
|
long end = System.currentTimeMillis ();
|
||||||
roundtrip = (int) ((roundtrip*4)+(end-start))/5;
|
roundtrip = (int) ((roundtrip*4)+(end-start))/5;
|
||||||
|
@ -218,8 +228,7 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
|
|
||||||
if (strbuf == null)
|
if (strbuf == null)
|
||||||
strbuf = new StringBuffer ();
|
strbuf = new StringBuffer ();
|
||||||
else
|
|
||||||
strbuf.setLength (0);
|
|
||||||
XmlWriter writer = new XmlWriter (strbuf);
|
XmlWriter writer = new XmlWriter (strbuf);
|
||||||
writeRequest (writer, method, params);
|
writeRequest (writer, method, params);
|
||||||
byte[] request = writer.getBytes();
|
byte[] request = writer.getBytes();
|
||||||
|
@ -272,7 +281,7 @@ public class XmlRpcClient implements XmlRpcHandler {
|
||||||
/**
|
/**
|
||||||
* Generate an XML-RPC request from a method name and a parameter vector.
|
* Generate an XML-RPC request from a method name and a parameter vector.
|
||||||
*/
|
*/
|
||||||
void writeRequest (XmlWriter writer, String method, Vector params) throws IOException {
|
void writeRequest (XmlWriter writer, String method, Vector params) throws IOException, XmlRpcException {
|
||||||
writer.startElement ("methodCall");
|
writer.startElement ("methodCall");
|
||||||
|
|
||||||
writer.startElement ("methodName");
|
writer.startElement ("methodName");
|
||||||
|
|
|
@ -41,13 +41,19 @@ public class XmlRpcClientLite extends XmlRpcClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
synchronized Worker getWorker () throws IOException {
|
synchronized Worker getWorker (boolean async) throws IOException {
|
||||||
try {
|
try {
|
||||||
Worker w = (Worker) pool.pop ();
|
Worker w = (Worker) pool.pop ();
|
||||||
|
if (async)
|
||||||
|
asyncWorkers += 1;
|
||||||
|
else
|
||||||
workers += 1;
|
workers += 1;
|
||||||
return w;
|
return w;
|
||||||
} catch (EmptyStackException x) {
|
} catch (EmptyStackException x) {
|
||||||
if (workers < maxThreads) {
|
if (workers < maxThreads) {
|
||||||
|
if (async)
|
||||||
|
asyncWorkers += 1;
|
||||||
|
else
|
||||||
workers += 1;
|
workers += 1;
|
||||||
return new LiteWorker ();
|
return new LiteWorker ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,7 @@ public class XmlRpcServer {
|
||||||
inParams = new Vector ();
|
inParams = new Vector ();
|
||||||
if (strbuf == null)
|
if (strbuf == null)
|
||||||
strbuf = new StringBuffer ();
|
strbuf = new StringBuffer ();
|
||||||
else
|
|
||||||
strbuf.setLength (0);
|
|
||||||
long now = System.currentTimeMillis ();
|
long now = System.currentTimeMillis ();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -150,7 +149,11 @@ public class XmlRpcServer {
|
||||||
String message = x.toString ();
|
String message = x.toString ();
|
||||||
// check if XmlRpcException was thrown so we can get an error code
|
// check if XmlRpcException was thrown so we can get an error code
|
||||||
int code = x instanceof XmlRpcException ? ((XmlRpcException) x).code : 0;
|
int code = x instanceof XmlRpcException ? ((XmlRpcException) x).code : 0;
|
||||||
|
try {
|
||||||
writeError (code, message, writer);
|
writeError (code, message, writer);
|
||||||
|
} catch (XmlRpcException xrx) {
|
||||||
|
// won't happen, we just sent a struct with an int and a string
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
result = writer.getBytes ();
|
result = writer.getBytes ();
|
||||||
} catch (UnsupportedEncodingException encx) {
|
} catch (UnsupportedEncodingException encx) {
|
||||||
|
@ -173,7 +176,7 @@ public class XmlRpcServer {
|
||||||
/**
|
/**
|
||||||
* Writes an XML-RPC response to the XML writer.
|
* Writes an XML-RPC response to the XML writer.
|
||||||
*/
|
*/
|
||||||
void writeResponse (Object param, XmlWriter writer) {
|
void writeResponse (Object param, XmlWriter writer) throws XmlRpcException {
|
||||||
writer.startElement ("methodResponse");
|
writer.startElement ("methodResponse");
|
||||||
// if (param == null) param = ""; // workaround for Frontier bug
|
// if (param == null) param = ""; // workaround for Frontier bug
|
||||||
writer.startElement ("params");
|
writer.startElement ("params");
|
||||||
|
@ -187,7 +190,7 @@ public class XmlRpcServer {
|
||||||
/**
|
/**
|
||||||
* Writes an XML-RPC error response to the XML writer.
|
* Writes an XML-RPC error response to the XML writer.
|
||||||
*/
|
*/
|
||||||
void writeError (int code, String message, XmlWriter writer) {
|
void writeError (int code, String message, XmlWriter writer) throws XmlRpcException {
|
||||||
// System.err.println ("error: "+message);
|
// System.err.println ("error: "+message);
|
||||||
Hashtable h = new Hashtable ();
|
Hashtable h = new Hashtable ();
|
||||||
h.put ("faultCode", new Integer (code));
|
h.put ("faultCode", new Integer (code));
|
||||||
|
|
Loading…
Add table
Reference in a new issue