@Override
  protected View createFallbackView(String viewName) throws Exception {
    GrailsWebRequest webRequest = GrailsWebRequest.lookup();

    String[] viewNameParts = splitViewName(viewName);
    if (viewNameParts.length == 1) {
      viewName = WebUtils.addViewPrefix(viewName, webRequest.getControllerName());
      viewNameParts = splitViewName(viewName);
    }

    View v = scaffoldedViews.get(viewName);
    if (v == null) {
      GrailsDomainClass domainClass = scaffoldedDomains.get(viewNameParts[0]);
      if (domainClass != null) {
        String viewCode = null;
        try {
          viewCode = generateViewSource(viewNameParts[1], domainClass);
        } catch (Exception e) {
          log.error("Error generating scaffolded view [" + viewName + "]: " + e.getMessage(), e);
        }
        if (StringUtils.hasLength(viewCode)) {
          v = createScaffoldedView(viewName, viewCode);
          scaffoldedViews.put(viewName, v);
        }
      }
    }
    if (v != null) {
      return v;
    }
    return super.createFallbackView(viewName);
  }
  @Override
  protected View loadView(String viewName, Locale locale) throws Exception {
    final View resolvedView = super.loadView(viewName, locale);
    if (templateGenerator == null || resolvedView instanceof GroovyPageView) {
      return resolvedView;
    }

    GrailsWebRequest webRequest = WebUtils.retrieveGrailsWebRequest();
    List<String> controllerActions = scaffoldedActionMap.get(webRequest.getControllerName());
    if (controllerActions != null && controllerActions.contains(webRequest.getActionName())) {
      GrailsDomainClass domainClass = scaffoldedDomains.get(webRequest.getControllerName());
      if (domainClass != null) {
        String viewFileName;
        final int i = viewName.lastIndexOf('/');
        if (i > -1) {
          viewFileName = viewName.substring(i, viewName.length());
        } else {
          viewFileName = viewName;
        }
        final ViewKey viewKey = new ViewKey(webRequest.getControllerName(), viewFileName);
        View v = scaffoldedViews.get(viewKey);
        if (v == null) {
          String viewCode = null;
          try {
            viewCode = generateViewSource(webRequest, domainClass);
          } catch (Exception e) {
            GrailsUtil.deepSanitize(e);
            LOG.error("Error generating scaffolded view [" + viewName + "]: " + e.getMessage(), e);
            return resolvedView;
          }
          v = createScaffoldedView(viewName, viewCode);
          scaffoldedViews.put(viewKey, v);
        }
        if (v != null) {
          return v;
        }
      }
    }
    return resolvedView;
  }
  public Object invoke(Object target, String methodName, Object[] arguments) {
    if (arguments.length == 0)
      throw new MissingMethodException(METHOD_SIGNATURE, target.getClass(), arguments);

    Map argMap = arguments[0] instanceof Map ? (Map) arguments[0] : Collections.EMPTY_MAP;
    if (argMap.size() == 0) {
      throw new MissingMethodException(METHOD_SIGNATURE, target.getClass(), arguments);
    }

    GrailsWebRequest webRequest =
        (GrailsWebRequest) RequestContextHolder.currentRequestAttributes();

    HttpServletRequest request = webRequest.getCurrentRequest();
    HttpServletResponse response = webRequest.getCurrentResponse();

    if (request.getAttribute(GRAILS_REDIRECT_ISSUED) != null) {
      throw new CannotRedirectException(
          "Cannot issue a redirect(..) here. A previous call to redirect(..) has already redirected the response.");
    }
    if (response.isCommitted()) {
      throw new CannotRedirectException(
          "Cannot issue a redirect(..) here. The response has already been committed either by another redirect or by directly writing to the response.");
    }

    Object actionRef = argMap.get(ARGUMENT_ACTION);
    String controllerName = getControllerName(target, argMap);

    Object id = argMap.get(ARGUMENT_ID);
    String frag =
        argMap.get(ARGUMENT_FRAGMENT) != null ? argMap.get(ARGUMENT_FRAGMENT).toString() : null;
    Object uri = argMap.get(ARGUMENT_URI);
    String url = argMap.containsKey(ARGUMENT_URL) ? argMap.get(ARGUMENT_URL).toString() : null;
    Map params = (Map) argMap.get(ARGUMENT_PARAMS);
    if (params == null) params = new HashMap();
    Errors errors = (Errors) argMap.get(ARGUMENT_ERRORS);
    GroovyObject controller = (GroovyObject) target;

    // if there are errors add it to the list of errors
    Errors controllerErrors =
        (Errors) controller.getProperty(ControllerDynamicMethods.ERRORS_PROPERTY);
    if (controllerErrors != null) {
      controllerErrors.addAllErrors(errors);
    } else {
      controller.setProperty(ControllerDynamicMethods.ERRORS_PROPERTY, errors);
    }

    String actualUri;
    GrailsApplicationAttributes attrs = webRequest.getAttributes();

    if (uri != null) {
      actualUri = attrs.getApplicationUri(request) + uri.toString();
    } else if (url != null) {
      actualUri = url;
    } else {
      String actionName = establishActionName(actionRef, target, webRequest);
      controllerName = controllerName != null ? controllerName : webRequest.getControllerName();

      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "Dynamic method [redirect] looking up URL mapping for controller ["
                + controllerName
                + "] and action ["
                + actionName
                + "] and params ["
                + params
                + "] with ["
                + urlMappingsHolder
                + "]");
      }

      try {
        if (id != null) params.put(ARGUMENT_ID, id);

        UrlCreator urlMapping =
            urlMappingsHolder.getReverseMapping(controllerName, actionName, params);
        if (LOG.isDebugEnabled() && urlMapping == null) {
          LOG.debug("Dynamic method [redirect] no URL mapping found for params [" + params + "]");
        }

        actualUri =
            urlMapping.createURL(
                controllerName, actionName, params, request.getCharacterEncoding(), frag);

        if (LOG.isDebugEnabled()) {
          LOG.debug("Dynamic method [redirect] mapped to URL [" + actualUri + "]");
        }

      } finally {
        if (id != null) params.remove(ARGUMENT_ID);
      }
    }

    return redirectResponse(actualUri, request, response);
  }