Wednesday, November 11, 2009

Something Fishy about JSTL Tags

I was using "Apache Standard Taglib Standard 1.1" for setting different resource bundle based on the user. I also added default resource bundle name in web.xml as below.

<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>com.passion4java.Localization</param-value>
</context-param>
I was using setBundle tag in my code so that it will set different bundle based on the user.

<fmt:setBundle basename="<%=partnerLevelBrandName%>"
scope="session"/>

I tried to set the scope in the setBundle tag, but in "Apache Standard Taglib Standard 1.1" it was throwing an exception saying that var argument need to be used when you are using the scope variable …

Error: passiontemplate1.jsp:31:1: The page failed validation from validator: "Illegal scope attribute without var in "fmt:setBundle" tag.".
Then I was running the code without scope variable, but the setBundle was not overriding the default build name (which is specified in the web.xml)

<fmt:setBundle basename="<%=passionLevelBrandName%>" />

When I was debugging the code of the JSTL Message Tag (org.apache.taglibs.standard.tag.rt.fmt.MessageTag), they are getting the bundle name from the pageContext .Below is the code which searches the bundle name.



Code Snipped from javax.servlet.jsp.jstl.core.Config



public static Object find(PageContext pc, String name){

    Object ret = get(pc, name, PageContext.PAGE_SCOPE);

    if (ret == null){

     ret = get(pc, name, PageContext.REQUEST_SCOPE);

     if (ret == null){

        if (pc.getSession() != null){

         // check session only if a session is present

         ret = get(pc, name, PageContext.SESSION_SCOPE);

        }

        if (ret == null){

         ret = get(pc, name, PageContext.APPLICATION_SCOPE);

         if (ret == null){

            ret = pc.getServletContext().getInitParameter(name);

         }

        }

     }

    } 
    return ret;
}
I have two questions which are running in my mind.
  • Why fmt:setBundle tag was not allowing to set the scope variable only?
  • As we defined the default resource bundle name in web.xml (which is application level), why the code was setting the bundle name in the pageContext?(it should set in the application scope).
  • And finally why they are started to search from pageContext à Application (I think it has to be reversed)?
Please let me know if you have any thoughts on this?

2 comments:

Auke said...

* What would you think that 'scope' would do in that case? The idea (AFAIK) of the var and scope is to store the *bundle* in the specified variable in the specified scope. Afterwards you can use it like this: <fmt:message bundle="${bundleVar}" key="some.key" />
* Are you sure the default name is set in the pageContext? that would seem weird to me.
* The idea is to search with the most narrow scope first. In general if you have a variable of some kind that is a certain value for most of the application you would set that in the broadest scope (application or so), if you then for one page need to override that value you can do that in the scope of your page. The search is therefore also from most narrow to most broad.

Auke

Mohammed Yousuff said...

Auke thanks for your comments and below is my response.

1. If you see the higher version of JSTL tags they allowed to set ONLY the scope in the setBundle tag, they reason is we don't need to add the bundle tag every time you use the message tag. That make code hard to maintain and less readable...That I want I mean it... :)

2 That’s right I also felt the same, because as we are setting the default name in web.xml it should set the value in the application context so that developer have a freedom to change if they need.

3. I complete with you in this comment... but only which worries is point no 2 which made me to post this ;)

Post a Comment

 

This content comes from a hidden element on this page.

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.
Click me, it will be preserved!

If you try to open a new ColorBox while it is already open, it will update itself with the new content.

Updating Content Example:
Click here to load new content