@Override public Object invokeMethod(String name, Object param) { try { if (controller == null) { controller = Request.current().controller; } String action = controller + "." + name; if (action.endsWith(".call")) { action = action.substring(0, action.length() - 5); } try { Map<String, Object> r = new HashMap<String, Object>(); Method actionMethod = (Method) ActionInvoker.getActionMethod(action)[1]; String[] names = (String[]) actionMethod.getDeclaringClass().getDeclaredField("$" + actionMethod.getName() + LocalVariablesNamesTracer.computeMethodHash(actionMethod.getParameterTypes())).get(null); if (param instanceof Object[]) { // too many parameters versus action, possibly a developer error. we must warn him. if (names.length < ((Object[]) param).length) { throw new NoRouteFoundException(action, null); } for (int i = 0; i < ((Object[]) param).length; i++) { if (((Object[]) param)[i] instanceof Router.ActionDefinition && ((Object[]) param)[i] != null) { Unbinder.unBind(r, ((Object[]) param)[i].toString(), i < names.length ? names[i] : ""); } else if (isSimpleParam(actionMethod.getParameterTypes()[i])) { if (((Object[]) param)[i] != null) { Unbinder.unBind(r, ((Object[]) param)[i].toString(), i < names.length ? names[i] : ""); } } else { Unbinder.unBind(r, ((Object[]) param)[i], i < names.length ? names[i] : ""); } } } Router.ActionDefinition def = Router.reverse(action, r); if (absolute) { def.absolute(); } if (template.template.name.endsWith(".html") || template.template.name.endsWith(".xml")) { def.url = def.url.replace("&", "&"); } return def; } catch (ActionNotFoundException e) { throw new NoRouteFoundException(action, null); } } catch (Exception e) { if (e instanceof PlayException) { throw (PlayException) e; } throw new UnexpectedException(e); } }