Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: 0.3
-
Fix Version/s: 0.4
-
Component/s: View technologies
-
Labels:None
-
Patch attached:Yes
-
Testcase included:yes
Description
The following is a cut/paste from the email on this topic:
-----------------------include begin-------------------
I've been tracking an issue I've had that occurs when Grails is the
target of an include (ok, what I really want is to implement the ability
for Grails views to invoke Grails controllers with views). What I've
discovered is that the include will result in an include of itself.
What I've found:
1) the RequestDispatcher.include() is called fine from the custom GSP
taglib I wrote.
2) this invokes my Grails controller okay
3) Grails will return the correct Spring View object.
4) the view is resolved okay in GrailsViewResolver.
5) the underlying returned view is used by Spring's DispatcherServlet to
call Spring's InternalResourceView.renderMergedOutputModel()
6) which calls RequestDispatcher.include() on the .gsp
7) which maps to GroovyPagesServlet, which uses getRequestURI() to
obtain the URL path.
8) This ends up calling the original .gsp file.
The reason why this doesn't work: step 7 isn't quite right. What I've
learned is that when a servlet is the target of an include, it's NOT
appropriate to use the standard Request.getRequest....() methods, as
they will return the original calling servlet's information. In this
scenario, it's required to check the special request attribute variables
"javax.servlet.include.*".
I found this from:
http://www.caucho.com/resin-3.0/webapp/faq.xtp
http://www.javaworld.com/javaworld/jw-03-2003/jw-0328-servlet-p2.html
and is in the Servlet 2.2 spec
http://java.sun.com/products/servlet/2.2/servlet-2.2-publicdraft.pdf
under section 8.2.1 ("included request parameters").
------------------------include end---------------------
Attached are requestinclude-testcase.zip, which contains:
RequestDispatcherTagLib.groovy , which defines <g:include1> which performs a RequestDispatcher.include()
DynamicApproachController.groovy, a sample controller used for this testcase
index.gsp , which invokes g:include1 to call the fails action on the controller
fails.gsp , a view for the fails action.
...and requestinclude-patch.zip, which contains modifications of:
GroovyPagesTemplateEngine.java
^- note that I also modified this file to not use getRequestURI();
I'm not sure why that was being used instead of getServletPath()?
ViewDelegatingScaffoldResponseHandler.java
DefaultGrailsScaffolder.java
These are the 3 major files I saw that lacked handling of include in a way that I could see causing an issue- of these, I regard GroovyPagesTemplateEngine as the most critical change. I'm not sure if you also would want to modify GrailsLayoutDecoratorMapper in a similar fashion; I'm not as familiar with SiteMesh so I didn't want to muck with that.
I didn't get around to creating a JUnit testcase for this yet. Let me know if that keeps it from being merged in. Without my changes, the code will enter into a massive set of nested includes that eventually go 'kaboom'.
I think we need a <g:import /> tag for GSPs, like JSTL's <c:import />, that can include the results of an external source (eg "http://bbc.co.uk") or internal to the servlet (eg, another controller action).