Dave
Dave

Reputation: 8897

How to prevent Grails from rendering the default view?

I'm using Grails 1.2.1. I have this method in my controller …

class SocialMediaCacheProxyController {

    def index = {       
        def url = params.url
        if (params.dumpAll != null) {
            transportCacheService.processCacheDump(request.getRemoteAddr(), response)
        } else if (url != null) {
            doCacheTransport(request, response)
        }   // if
    }

Problem is, both execution paths write content to the response. However, I think Grails is trying to render a page at the end of the index method, because I repeatedly get the below error after invoking this method …

1339754 [http-8080-4] ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/socialmediaproxy].[default]  - Servlet.service() for servlet default threw exception
java.lang.IllegalStateException: response.getWriter() called after response.getOutputStream()
    at org.codehaus.groovy.grails.web.sitemesh.GrailsPageResponseWrapper$GrailsBuffer.getWriter(GrailsPageResponseWrapper.java:284)
    at org.codehaus.groovy.grails.web.sitemesh.GrailsPageResponseWrapper$3.activateDestination(GrailsPageResponseWrapper.java:125)

Any ideas how I can get Grails to stop rendering anything after my method is complete? Thanks, - Dave

Upvotes: 2

Views: 6098

Answers (5)

Sphe
Sphe

Reputation: 1

try this render (view: "/the name of the page", model: [text:'hi there')

NB if u want to render a template instead of "view" you put "template"

Upvotes: 0

Rob Hruska
Rob Hruska

Reputation: 120286

It looks like most of the controller code that works with the ModelAndView keeps an eye on whether or not the ServletResponse has been committed.

I would posit that you could call response.flushBuffer() at the end of your controller action. This will cause the response to be marked as committed, and the controller will not return a ModelAndView.

An alternative would be to call response.outputStream.flush(), which would also result in the response being committed. This is what I usually end up doing after manually working with the response (e.g. for file downloads).

Note: I'm not sure where this falls within the realm of "best practices" - usually you're supposed to rely on the container to handle the flushing of the servlet streams. It's possible that there will be inadvertent side-effects by doing this. You'll probably have to test it out and see what happens with your app and the container you run it in.

Upvotes: 2

Hans Westerbeek
Hans Westerbeek

Reputation: 5805

I think Grails maybe forwarding to index.gsp, because it does so by default when you don't return a value.

Therefore, i think you should return null at the end of the index-closure to signal grails that you have already written everything you wanted to the output stream.

Upvotes: 0

Ethan Shepherd
Ethan Shepherd

Reputation: 569

I think you're trying to do something counter to the design of an MVC application. Controllers exist to send you somewhere based on parameters. Maybe you could look at using a Service instead, through an AJAX call. Or, if your controller action is changing data that you want to show, you could just redirect back to the page that the call came from. Start here:

http://grails.org/doc/1.0.x/guide/6.%20The%20Web%20Layer.html

http://grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html

Upvotes: 0

Gregg
Gregg

Reputation: 35864

If you don't tell Grails what to render, it will render based on convention. In your case, it is looking for an index.gsp. Controllers must return something. That's the whole point. So you can either use the convention and create an index.gsp that gets returned, or you can manually implement the render() method.

http://grails.org/doc/latest/ref/Controllers/render.html

Upvotes: 2

Related Questions