Automatically generate a failure response if an invocation provider method

throws ServiceFailedException. The response for a service request named
<foo> would be <foo>Failed. The response has a single argument which is
the reason string provided by the ServiceFailedException. We were doing
this by hand all over the place, and now it will be handled automatically.
Yay!


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1268 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2002-04-17 18:20:04 +00:00
parent a11bff9cf8
commit 496732db3a
2 changed files with 49 additions and 5 deletions
@@ -1,14 +1,18 @@
//
// $Id: InvocationManager.java,v 1.10 2001/10/24 00:36:40 mdb Exp $
// $Id: InvocationManager.java,v 1.11 2002/04/17 18:20:04 mdb Exp $
package com.threerings.presents.server;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import com.samskivert.util.StringUtil;
import com.threerings.presents.Log;
import com.threerings.presents.dobj.*;
import com.threerings.presents.data.*;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationObject;
import com.threerings.presents.util.ClassUtil;
/**
@@ -132,14 +136,16 @@ public class InvocationManager
// prune the method arguments from the full message arguments
Object[] margs = new Object[args.length-1];
int cloid = event.getSourceOid();
margs[0] = PresentsServer.omgr.getObject(cloid);
ClientObject source = (ClientObject)
PresentsServer.omgr.getObject(cloid);
// make sure the client is still around
if (margs[0] == null) {
if (source == null) {
Log.warning("Client no longer around for invocation provider " +
"request [module=" + module +
", proc=" + procedure + ", cloid=" + cloid + "].");
return;
}
margs[0] = source;
System.arraycopy(args, 2, margs, 1, args.length-2);
// look up the method that will handle this procedure
@@ -155,6 +161,23 @@ public class InvocationManager
// and invoke it
try {
procmeth.invoke(provider, margs);
} catch (InvocationTargetException ite) {
Throwable te = ite.getTargetException();
if (te instanceof ServiceFailedException) {
// automatically generate a <foo>Failed response
provider.sendResponse(source, invid.intValue(),
procedure + FAILED_SUFFIX,
te.getMessage());
} else {
Log.warning("Invocation procedure failed " +
"[provider=" + provider +
", method=" + procmeth +
", args=" + StringUtil.toString(margs) + "].");
Log.logStackTrace(te);
}
} catch (Exception e) {
Log.warning("Error invoking invocation procedure " +
"[provider=" + provider +
@@ -167,4 +190,8 @@ public class InvocationManager
protected int _invoid;
protected HashMap _providers = new HashMap();
protected HashMap _methcache = new HashMap();
/** The text that is appended to the procedure name when automatically
* generating a failure response. */
protected static final String FAILED_SUFFIX = "Failed";
}
@@ -1,5 +1,5 @@
//
// $Id: InvocationProvider.java,v 1.6 2001/10/11 04:07:53 mdb Exp $
// $Id: InvocationProvider.java,v 1.7 2002/04/17 18:20:04 mdb Exp $
package com.threerings.presents.server;
@@ -53,6 +53,23 @@ import com.threerings.presents.dobj.MessageEvent;
* the reflection rules for automatic conversion of primitive types
* (supply an <code>Integer</code> object for <code>int</code> params,
* etc.).
*
* <p> Note that if an invocation service method throws a {@link
* ServiceFailedException}, the invocation manager will automatically
* issue a response to the client with the string <code>Failed</code>
* appended to the request method. For example, if the client issues a
* request for <code>Foo</code> which results in a call to
* <code>handleFooRequest</code>, which throws a service failed exception,
* the server will automatically issue a failure response named
* <code>FooFailed</code> with the single argument being the
* <code>reason</code> string provided to the constructor of the service
* failed exception. The caller would then implement:
*
* <pre>
* public void handleFooFailed (int invid, String reason)
* </pre>
*
* to handle the failure.
*/
public class InvocationProvider
{