tags:

views:

350

answers:

2

We're using this JSP template solution almost verbatim at work:

http://java.sun.com/developer/technicalArticles/javaserverpages/jsp_templates/

When it gets JSP pages to be included, it uses pageContext.include, which leaves us with one problem, and that is that we have a lot of scriplet code that gets initialized in the JSP itself (tag soup). My thought was to modify the template tag with an additional attribute that is a package path reference to a class with an init or execute method. That execute would get called first, and would add page context attributes before including the JSP. We would then use JSTL to access those attributes. However, I was told this wouldn't work because of how pageContext.include works, and the inability to pass through attributes scoped to the page. Is that true, and are there workarounds? I'm so-so on knowing all my scoping rules.

A: 

You can pass an attribute scoped to the request:

<c:set var="myAttribute" value="myValue" scope="request" />

or

<% request.setAttribute("myAttribute", "myValue"); %>

And then on your included page:

<c:out value="${myAttribute}" />
MontyBongo
+2  A: 

Correct, the problem is that the PageContext is literally that, a Page Context. When you run the include, that resource (assuming it's a JSP) get's its own PageContext, and that is lost upon return.

JSP has 4 scopes: Application, Session, Request, and Page. Each of those has its own lifecycle, which should be self explanatory.

The use of the Request scope here is the right idea.

If you look at the template code that you linked to, that's exactly what the Insert tag is doing. In this case, it's putting Hashtables on to a Stack that is maintained in the Request.

Then it uses the "put" and "get" tags to put/get items on and off that current "stack".

A simple thing that you can do is before the PageContext.include, invoke your "execute" method as appropriate. Have that method simply return a Map of name/value pairs. Then you can take that Map and populate the existing (or soon to be existing) Hashtable on the Stack.

Basically your Init class is logic that's similar to calling a lot of the "put" tags.

Other than that your template tags work the same.

Or you can merge the results straight in to the Request, for use by the JSTL. Or you can keep the "stack" nature, pushing your own "context" in to the Request.

Will Hartung
Thank you for the excellent explanation.
hal10001