Grails redirect looping error when rendering view

2019-08-21 12:28发布

问题:

I am using Grails 2.2.3 for an app to clear out Duplicate persons in our Database. When I attempt to access a controller action, I am receiving the following error:

Error Caused by: org.codehaus.groovy.grails.web.servlet.mvc.exceptions.CannotRedirectException: Cannot issue a redirect(..) here. A previous call to redirect(..) has already redirected the response.

It looks like an infinite redirect loop, because the Stacktrace in the console just goes bonkers as soon as I go to the duplicate() action. It keeps printing until I Ctrl+C out of the console. Also, there are multiple screens for working with a Duplicate and fixing it, which is why I am giving a way to store the "working" Duplicate.

The controller actions:

  • setWorkingDuplicate - set a duplicate to work with on each page (so a user doesn't have to keep typing it in).
  • duplicate - view a duplicate or, if there is no session.id, present the user with find duplicate form
  • getDuplicate (action only) - gets a duplicate and renders the duplicate page

The error is occurring when I go straight to the duplicate() page. If I set the working duplicate first, no redirect issues happen.

Here are the controller actions that are causing the issue.

def setWorkingDuplicate(Integer id) {
    if (id && Duplicate.get(id)) {
        session.id = id
        flash.message = "Working Duplicate set to ID ${id}"
        redirect action: 'getDuplicate', params: [id: session.id]
    }
}

def duplicate() {
    if (session.id) {
        redirect(action: 'getDuplicate', params: [id: session.id])
        return
    }
    render view: 'duplicate'
}

def getDuplicate(Integer id) {
    def duplicate = Duplicate.get(id)

    if (!duplicate) {
        flash.message = "Duplicate not found with ID ${id}."
        render(view: 'duplicate')
        return
    }

    render view: 'duplicate', model: [duplicate: duplicate]
}

Does anyone know what might be causing this?

Edit: it looks like somewhere down in the stack trace I am also receiving the following errors.

Error Caused by: java.lang.StackOverflowError

and

WARN: Exception: java.lang.reflect.InvocationTargetException

And in the stack trace, the following errors keep repeating over and over:

| Error     at edu.mssu.duplicates.InitialStepsController.render(InitialStepsController.groovy)
| Error     at edu.mssu.duplicates.InitialStepsController$render.callCurrent(Unknown Source)
| Error     at edu.mssu.duplicates.InitialStepsController.getDuplicate(InitialStepsController.groovy:69)
| Error     at edu.mssu.duplicates.InitialStepsController.getDuplicate(InitialStepsController.groovy)
| Error     at sun.reflect.GeneratedMethodAccessor382.invoke(Unknown Source)
| Error     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
| Error     at java.lang.reflect.Method.invoke(Method.java:601)
| Error     at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1259)
| Error     at org.apache.commons.beanutils.BeanMap.get(BeanMap.java:390)
| Error     at org.apache.commons.beanutils.BeanMap$12.next(BeanMap.java:565)
| Error     at org.apache.commons.collections.iterators.UnmodifiableIterator.next(UnmodifiableIterator.java:72)
| Error     at java.util.HashMap.putAll(HashMap.java:621)
| Error     at org.springframework.ui.ModelMap.addAllAttributes(ModelMap.java:117)
| Error     at org.springframework.web.servlet.ModelAndView.<init>(ModelAndView.java:97)
| Error     at org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod.renderView(RenderDynamicMethod.java:485)
| Error     at org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod.invoke(RenderDynamicMethod.java:187)
| Error     at org.codehaus.groovy.grails.plugins.web.api.ControllersApi.invokeRender(ControllersApi.java:258)
| Error     at org.codehaus.groovy.grails.plugins.web.api.ControllersApi.render(ControllersApi.java:246)

This is a (very stripped down) version of my Duplicate GSP. The GSP presents a way to quickly search/show/update a Duplicate and display that Duplicate, all in one page. Hence the search box and show form.

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
</head>
<body>
    <h1>Duplicate</h1>
        <g:form action="duplicate" method="POST">
            <label for="id">Duplicate ID</label> <g:textField name="id" value="${duplicate?.id}" />

            <g:submitButton name="btnRetrieveDuplicate" value="Retrieve Duplicate" />
        </g:form>

        <g:if test="${duplicate}">
            <g:form action="updateDuplicate" method="POST">
                //Form stuff

                <g:hiddenField name="id" value="${duplicate?.id}" />
            </g:form>
        </g:if>
</body>
</html>

回答1:

I've had some really strange issues before when naming controllers matched some other objects or started with 'get'

Try renaming:
def getDuplicate(Integer id) to something completely different like: def myDupe(Integer id)

Sorry I can't give you a better explanation, but I've done this a few times just to get things working.