diff --git a/src/java/com/threerings/presents/server/InvocationManager.java b/src/java/com/threerings/presents/server/InvocationManager.java index 91d634cd8..478b8e8cf 100644 --- a/src/java/com/threerings/presents/server/InvocationManager.java +++ b/src/java/com/threerings/presents/server/InvocationManager.java @@ -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 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"; } diff --git a/src/java/com/threerings/presents/server/InvocationProvider.java b/src/java/com/threerings/presents/server/InvocationProvider.java index 4c6cf0cf8..dcbc7e736 100644 --- a/src/java/com/threerings/presents/server/InvocationProvider.java +++ b/src/java/com/threerings/presents/server/InvocationProvider.java @@ -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 Integer object for int params, * etc.). + * + *

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 Failed + * appended to the request method. For example, if the client issues a + * request for Foo which results in a call to + * handleFooRequest, which throws a service failed exception, + * the server will automatically issue a failure response named + * FooFailed with the single argument being the + * reason string provided to the constructor of the service + * failed exception. The caller would then implement: + * + *

+ * public void handleFooFailed (int invid, String reason)
+ * 
+ * + * to handle the failure. */ public class InvocationProvider {