@Override
  public void init(FilterConfig fc) {
    super.init(fc);
    this.filterConfig = fc;
    containerTweaks = new ContainerTweaks();
    Config config = new Config(fc);
    // DefaultFactory defaultFactory = new DefaultFactory(config);
    Grails5535Factory defaultFactory =
        new Grails5535Factory(config); // TODO revert once Sitemesh bug is fixed
    fc.getServletContext().setAttribute(FACTORY_SERVLET_CONTEXT_ATTRIBUTE, defaultFactory);
    defaultFactory.refresh();
    FactoryHolder.setFactory(defaultFactory);

    contentProcessor = new PageParser2ContentProcessor(defaultFactory);
    decoratorMapper = defaultFactory.getDecoratorMapper();

    applicationContext =
        WebApplicationContextUtils.getRequiredWebApplicationContext(fc.getServletContext());
    layoutViewResolver = WebUtils.lookupViewResolver(applicationContext);

    final GrailsApplication grailsApplication =
        GrailsWebUtil.lookupApplication(fc.getServletContext());
    String encoding = (String) grailsApplication.getFlatConfig().get(CONFIG_OPTION_GSP_ENCODING);
    if (encoding != null) {
      defaultEncoding = encoding;
    }

    Map<String, PersistenceContextInterceptor> interceptors =
        applicationContext.getBeansOfType(PersistenceContextInterceptor.class);
    if (!interceptors.isEmpty()) {
      persistenceInterceptor = interceptors.values().iterator().next();
    }
  }
  @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);
  }
  private View createGrailsView(String viewName) throws Exception {
    // try GSP if res is null

    GrailsWebRequest webRequest = WebUtils.retrieveGrailsWebRequest();

    HttpServletRequest request = webRequest.getCurrentRequest();
    GroovyObject controller = webRequest.getAttributes().getController(request);

    if (grailsApplication == null) {

      grailsApplication =
          getApplicationContext()
              .getBean(GrailsApplication.APPLICATION_ID, GrailsApplication.class);
    }

    ResourceLoader loader = establishResourceLoader(grailsApplication);

    String format =
        request.getAttribute(GrailsApplicationAttributes.CONTENT_FORMAT) != null
            ? request.getAttribute(GrailsApplicationAttributes.CONTENT_FORMAT).toString()
            : null;
    String gspView = localPrefix + viewName + DOT + format + GSP_SUFFIX;
    Resource res = null;

    if (format != null) {
      res = loader.getResource(gspView);
      if (!res.exists()) {
        View v = lookupBinaryPluginView(webRequest, controller, gspView);
        if (v != null) {
          return v;
        }
        gspView = resolveViewForController(controller, grailsApplication, viewName, loader);
        res = loader.getResource(gspView);
      }
    }

    if (res == null || !res.exists()) {
      gspView = localPrefix + viewName + GSP_SUFFIX;
      res = loader.getResource(gspView);
      if (!res.exists()) {
        View v = lookupBinaryPluginView(webRequest, controller, gspView);
        if (v != null) {
          return v;
        }
        gspView = resolveViewForController(controller, grailsApplication, viewName, loader);
        res = loader.getResource(gspView);
      }
    }

    if (res.exists()) {
      return createGroovyPageView(webRequest, gspView);
    }

    AbstractUrlBasedView view = buildView(viewName);
    view.setApplicationContext(getApplicationContext());
    view.afterPropertiesSet();
    return view;
  }
  /**
   * Converts this parameter map into a query String. Note that this will flatten nested keys
   * separating them with the . character and URL encode the result
   *
   * @return A query String starting with the ? character
   */
  public String toQueryString() {

    String encoding = request.getCharacterEncoding();
    try {
      return WebUtils.toQueryString(this, encoding);
    } catch (UnsupportedEncodingException e) {
      throw new ControllerExecutionException(
          "Unable to convert parameter map [" + this + "] to a query string: " + e.getMessage(), e);
    }
  }
  protected void logRequestDetails(
      HttpServletRequest request, ContentCacheParameters cacheParameters, String message) {
    if (!log.isDebugEnabled()) {
      return;
    }

    log.debug("{}...", message);
    log.debug("    method = {}", request.getMethod());
    log.debug("    requestURI = {}", request.getRequestURI());
    log.debug("    forwardURI = {}", WebUtils.getForwardURI(request));
    if (WebUtils.isIncludeRequest(request)) {
      log.debug(
          "    includeURI = {}", request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE));
    }
    log.debug("    controller = {}", cacheParameters.getControllerName());
    log.debug("    action = {}", cacheParameters.getActionName());
    RequestMimeTypesApi requestMimeTypesApi = getBean("requestMimeTypesApi");
    log.debug("    format = {}", requestMimeTypesApi.getFormat(request));
    log.debug("    params = {}", cacheParameters.getParams());
  }
  protected PageInfo buildPage(
      HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    // Invoke the next entity in the chain
    SerializableByteArrayOutputStream out = new SerializableByteArrayOutputStream();
    GenericResponseWrapper wrapper = new GenericResponseWrapper(response, out);
    Map<String, Serializable> cacheableRequestAttributes = new HashMap<String, Serializable>();

    // TODO: split the special include handling out into a separate method
    HttpServletResponse originalResponse = null;
    boolean isInclude = WebUtils.isIncludeRequest(request);
    if (isInclude) {
      originalResponse = WrappedResponseHolder.getWrappedResponse();
      WrappedResponseHolder.setWrappedResponse(wrapper);
    }
    try {
      List<String> attributesBefore = toList(request.getAttributeNames());
      chain.doFilter(request, wrapper);
      List<String> attributesAfter = toList(request.getAttributeNames());
      attributesAfter.removeAll(attributesBefore);
      for (String attrName : attributesAfter) {
        Object value = request.getAttribute(attrName);
        if (value instanceof Serializable) {
          cacheableRequestAttributes.put(attrName, (Serializable) value);
        }
      }
    } finally {
      if (isInclude) {
        WrappedResponseHolder.setWrappedResponse(originalResponse);
      }
    }
    wrapper.flush();

    long timeToLiveSeconds =
        Integer
            .MAX_VALUE; // TODO
                        // cacheManager.getEhcache(context.cacheName).cacheConfiguration.timeToLiveSeconds;

    String contentType = wrapper.getContentType();
    if (!StringUtils.hasLength(contentType)) {
      contentType = response.getContentType();
    }

    return new PageInfo(
        wrapper.getStatus(),
        contentType,
        out.toByteArray(),
        false,
        timeToLiveSeconds,
        wrapper.getAllHeaders(),
        wrapper.getCookies(),
        cacheableRequestAttributes);
  }
  /**
   * Writes the response from a PageInfo object.
   *
   * <p>Headers are set last so that there is an opportunity to override
   *
   * <p>1 - only set status, contentType, cookies, etc. if this is the "main" request and not an
   * include. 2 - send a status code 304 if appropriate.
   *
   * @param request
   * @param response
   * @param pageInfo
   * @throws IOException
   */
  protected void writeResponse(
      final HttpServletRequest request, final HttpServletResponse response, final PageInfo pageInfo)
      throws IOException {

    if (!WebUtils.isIncludeRequest(request)) {
      int statusCode = determineResponseStatus(request, pageInfo);
      response.setStatus(statusCode);
      setContentType(response, pageInfo);
      setCookies(pageInfo, response);
      setHeaders(pageInfo, response);
    }
    writeResponse(response, pageInfo);
  }
  @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;
  }
 protected String getCachedUri(HttpServletRequest request) {
   if (WebUtils.isIncludeRequest(request)) {
     return (String) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
   }
   return request.getRequestURI();
 }
  /* (non-Javadoc)
   * @see org.springframework.web.servlet.DispatcherServlet#doDispatch(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
   */
  protected void doDispatch(final HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    int interceptorIndex = -1;
    final LocaleResolver localeResolver =
        (LocaleResolver) request.getAttribute(LOCALE_RESOLVER_ATTRIBUTE);

    // Expose current LocaleResolver and request as LocaleContext.
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContextHolder.setLocaleContext(
        new LocaleContext() {
          public Locale getLocale() {

            return localeResolver.resolveLocale(request);
          }
        });

    // If the request is an include we need to try to use the original wrapped sitemesh
    // response, otherwise layouts won't work properly
    if (WebUtils.isIncludeRequest(request)) {
      response = useWrappedOrOriginalResponse(response);
    }

    GrailsWebRequest requestAttributes = null;
    GrailsWebRequest previousRequestAttributes = null;
    Exception handlerException = null;
    try {
      ModelAndView mv = null;
      try {
        Object exceptionAttribute = request.getAttribute(EXCEPTION_ATTRIBUTE);
        // only process multipart requests if an exception hasn't occured
        if (exceptionAttribute == null) processedRequest = checkMultipart(request);
        // Expose current RequestAttributes to current thread.
        previousRequestAttributes =
            (GrailsWebRequest) RequestContextHolder.currentRequestAttributes();
        requestAttributes = new GrailsWebRequest(processedRequest, response, getServletContext());
        copyParamsFromPreviousRequest(previousRequestAttributes, requestAttributes);

        // Update the current web request.
        WebUtils.storeGrailsWebRequest(requestAttributes);

        if (logger.isDebugEnabled()) {
          logger.debug("Bound request context to thread: " + request);
          logger.debug("Using response object: " + response.getClass());
        }

        // Determine handler for the current request.
        mappedHandler = getHandler(processedRequest, false);
        if (mappedHandler == null || mappedHandler.getHandler() == null) {
          noHandlerFound(processedRequest, response);
          return;
        }

        // Apply preHandle methods of registered interceptors.
        if (mappedHandler.getInterceptors() != null) {
          for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
            HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
            if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
              triggerAfterCompletion(
                  mappedHandler, interceptorIndex, processedRequest, response, null);
              return;
            }
            interceptorIndex = i;
          }
        }

        // Actually invoke the handler.
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        // Apply postHandle methods of registered interceptors.
        if (mappedHandler.getInterceptors() != null) {
          for (int i = mappedHandler.getInterceptors().length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
            interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
          }
        }
      } catch (ModelAndViewDefiningException ex) {
        GrailsUtil.deepSanitize(ex);
        handlerException = ex;
        if (logger.isDebugEnabled()) logger.debug("ModelAndViewDefiningException encountered", ex);
        mv = ex.getModelAndView();
      } catch (Exception ex) {
        GrailsUtil.deepSanitize(ex);
        handlerException = ex;
        Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
        mv = processHandlerException(request, response, handler, ex);
      }

      // Did the handler return a view to render?
      if (mv != null && !mv.wasCleared()) {
        // If an exception occurs in here, like a bad closing tag,
        // we have nothing to render.

        try {
          render(mv, processedRequest, response);
        } catch (Exception e) {
          mv = super.processHandlerException(processedRequest, response, mappedHandler, e);
          handlerException = e;
          render(mv, processedRequest, response);
        }
      } else {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Null ModelAndView returned to DispatcherServlet with name '"
                  + getServletName()
                  + "': assuming HandlerAdapter completed request handling");
        }
      }

      // Trigger after-completion for successful outcome.
      triggerAfterCompletion(
          mappedHandler, interceptorIndex, processedRequest, response, handlerException);
    } catch (Exception ex) {
      // Trigger after-completion for thrown exception.
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
      throw ex;
    } catch (Error err) {
      ServletException ex = new NestedServletException("Handler processing failed", err);
      // Trigger after-completion for thrown exception.
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
      throw ex;
    } finally {
      // Clean up any resources used by a multipart request.
      if (processedRequest instanceof MultipartHttpServletRequest && processedRequest != request) {
        if (multipartResolver != null)
          this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest);
      }
      request.removeAttribute(MultipartHttpServletRequest.class.getName());

      // Reset thread-bound holders
      if (requestAttributes != null) {
        requestAttributes.requestCompleted();
        WebUtils.storeGrailsWebRequest(previousRequestAttributes);
      }

      LocaleContextHolder.setLocaleContext(previousLocaleContext);

      if (logger.isDebugEnabled()) {
        logger.debug("Cleared thread-bound request context: " + request);
      }
    }
  }
  /* (non-Javadoc)
   * @see org.springframework.web.servlet.DispatcherServlet#doDispatch(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
   */
  @Override
  protected void doDispatch(final HttpServletRequest request, HttpServletResponse response)
      throws Exception {

    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, localeResolver);

    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    int interceptorIndex = -1;

    // Expose current LocaleResolver and request as LocaleContext.
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContextHolder.setLocaleContext(
        new LocaleContext() {
          public Locale getLocale() {
            return localeResolver.resolveLocale(request);
          }
        });

    // If the request is an include we need to try to use the original wrapped sitemesh
    // response, otherwise layouts won't work properly
    if (WebUtils.isIncludeRequest(request)) {
      response = useWrappedOrOriginalResponse(response);
    }

    GrailsWebRequest requestAttributes = null;
    RequestAttributes previousRequestAttributes = null;
    Exception handlerException = null;
    boolean isAsyncRequest =
        processedRequest.getAttribute("javax.servlet.async.request_uri") != null;
    try {
      ModelAndView mv;
      boolean errorView = false;
      try {
        Object exceptionAttribute = request.getAttribute(EXCEPTION_ATTRIBUTE);
        // only process multipart requests if an exception hasn't occured
        if (exceptionAttribute == null) {
          processedRequest = checkMultipart(request);
        }
        // Expose current RequestAttributes to current thread.
        previousRequestAttributes = RequestContextHolder.currentRequestAttributes();
        requestAttributes = new GrailsWebRequest(processedRequest, response, getServletContext());
        copyParamsFromPreviousRequest(previousRequestAttributes, requestAttributes);

        // Update the current web request.
        WebUtils.storeGrailsWebRequest(requestAttributes);

        if (logger.isDebugEnabled()) {
          logger.debug("Bound request context to thread: " + request);
          logger.debug("Using response object: " + response.getClass());
        }

        // Determine handler for the current request.
        mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null || mappedHandler.getHandler() == null) {
          noHandlerFound(processedRequest, response);
          return;
        }

        // Apply preHandle methods of registered interceptors.
        if (mappedHandler.getInterceptors() != null) {
          for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
            HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
            if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
              triggerAfterCompletion(
                  mappedHandler, interceptorIndex, processedRequest, response, null);
              return;
            }
            interceptorIndex = i;
          }
        }

        // if this is an async request that has been resumed, then don't execute the action again
        // instead try get the model and view and continue

        if (isAsyncRequest) {
          Object modelAndViewO =
              processedRequest.getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW);
          if (modelAndViewO != null) {
            mv = (ModelAndView) modelAndViewO;
          } else {
            mv = null;
          }

        } else {
          // Actually invoke the handler.
          HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
          mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
          // if an async request was started simply return
          if (processedRequest.getAttribute(GrailsApplicationAttributes.ASYNC_STARTED) != null) {
            processedRequest.setAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, mv);
            return;
          }

          // Do we need view name translation?
          if ((ha instanceof AnnotationMethodHandlerAdapter
                  || ha instanceof RequestMappingHandlerAdapter)
              && mv != null
              && !mv.hasView()) {
            mv.setViewName(getDefaultViewName(request));
          }
        }

        // Apply postHandle methods of registered interceptors.
        if (mappedHandler.getInterceptors() != null) {
          for (int i = mappedHandler.getInterceptors().length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
            interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
          }
        }
      } catch (ModelAndViewDefiningException ex) {
        handlerException = ex;
        if (logger.isDebugEnabled()) {
          logger.debug("ModelAndViewDefiningException encountered", ex);
        }
        mv = ex.getModelAndView();
      } catch (Exception ex) {
        handlerException = ex;
        Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
        mv = processHandlerException(request, response, handler, ex);
        errorView = (mv != null);
      }

      // Did the handler return a view to render?
      if (mv != null && !mv.wasCleared()) {
        // If an exception occurs in here, like a bad closing tag,
        // we have nothing to render.

        try {
          render(mv, processedRequest, response);
          if (isAsyncRequest && (response instanceof GrailsContentBufferingResponse)) {
            GroovyPageLayoutFinder groovyPageLayoutFinder =
                getWebApplicationContext()
                    .getBean("groovyPageLayoutFinder", GroovyPageLayoutFinder.class);
            GrailsContentBufferingResponse bufferingResponse =
                (GrailsContentBufferingResponse) response;
            HttpServletResponse targetResponse = bufferingResponse.getTargetResponse();
            Content content = bufferingResponse.getContent();
            if (content != null) {
              Decorator decorator = groovyPageLayoutFinder.findLayout(request, content);
              SiteMeshWebAppContext webAppContext =
                  new SiteMeshWebAppContext(request, targetResponse, getServletContext());
              if (decorator != null) {
                if (decorator instanceof com.opensymphony.sitemesh.Decorator) {
                  ((com.opensymphony.sitemesh.Decorator) decorator).render(content, webAppContext);
                } else {
                  new OldDecorator2NewDecorator(decorator).render(content, webAppContext);
                }
              } else {
                content.writeOriginal(targetResponse.getWriter());
              }
            }
          }
          if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
          }
        } catch (Exception e) {
          // Only render the error view if we're not already trying to render it.
          // This prevents a recursion if the error page itself has errors.
          if (request.getAttribute(GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE) == null) {
            request.setAttribute(
                GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE, Boolean.TRUE);

            mv = super.processHandlerException(processedRequest, response, mappedHandler, e);
            handlerException = e;
            if (mv != null) render(mv, processedRequest, response);
          } else {
            request.removeAttribute(GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE);
            logger.warn("Recursive rendering of error view detected.", e);

            try {
              response.setContentType("text/plain");
              response.getWriter().write("Internal server error");
              response.flushBuffer();
            } catch (Exception e2) {
              logger.error("Internal server error - problem rendering error view", e2);
            }

            requestAttributes.setRenderView(false);
            return;
          }
        }
      } else {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Null ModelAndView returned to DispatcherServlet with name '"
                  + getServletName()
                  + "': assuming HandlerAdapter completed request handling");
        }
      }

      // Trigger after-completion for successful outcome.
      triggerAfterCompletion(
          mappedHandler, interceptorIndex, processedRequest, response, handlerException);
    } catch (Exception ex) {
      // Trigger after-completion for thrown exception.
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
      throw ex;
    } catch (Error err) {
      ServletException ex = new NestedServletException("Handler processing failed", err);
      // Trigger after-completion for thrown exception.
      triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
      throw ex;
    } finally {
      // Clean up any resources used by a multipart request.
      if (processedRequest instanceof MultipartHttpServletRequest) {
        if (multipartResolver != null) {
          multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest);
        }
      }
      request.removeAttribute(MultipartHttpServletRequest.class.getName());

      // Reset thread-bound holders
      if (requestAttributes != null) {
        requestAttributes.requestCompleted();
        if (previousRequestAttributes instanceof GrailsWebRequest) {
          WebUtils.storeGrailsWebRequest((GrailsWebRequest) previousRequestAttributes);
        } else {
          RequestContextHolder.setRequestAttributes(previousRequestAttributes);
        }
      }

      LocaleContextHolder.setLocaleContext(previousLocaleContext);

      if (logger.isDebugEnabled()) {
        logger.debug("Cleared thread-bound request context: " + request);
      }
    }
  }
 @Override
 protected void initStrategies(ApplicationContext context) {
   super.initStrategies(context);
   initLocaleResolver(context);
   layoutViewResolver = WebUtils.lookupViewResolver(context);
 }