5

In short, how can I get the full query string using EL in a webflow view jsp? This is what I am trying to do:

<span class="forgot-password">
  <a href="forgotPasswordRequest?<%=request.getQueryString() %>">
    <spring:message code="screen.welcome.link.forgotPassword" />
  </a>
</span>

Except I would like to use EL instead of the scriptlet <%=request.getQueryString() %>. It appears easy enough to get any individual parameter using ${param.someParameterName}, but I want the whole thing. More specifically I am using CAS as an SSO provider. In order to authenticate, an app would redirect its login to CAS with a query string containing the parameter service that is the URL to return to after successful authentication. Something like this:

?service=http%3A%2F%2Fmysite.com%3A9080%2Fwelcome

My CAS login page has a link for a forgotten password webflow. I need to propagate that service parameter to that other webflow. So I could do something like this:

<span class="forgot-password">
  <a href="forgotPasswordRequest?service=${param.service}">
    <spring:message code="screen.welcome.link.forgotPassword" />
  </a>
</span>

But then I lose all the URL escaping. Furthermore, if there are other parameters that I want to preserve in the future, they would be lost as well.

The scriptlet currently works, but its ugly and I don't like having code (since this is true java code) in my presentation even though it is trivial. EL is certainly a much more elegant solution.

I poked around all of the Special EL variables listed in the spring documentation, but was still unable to come up with a way to get the full queryString.

-------------------------------- UPDATE --------------------------------

Ok, so I am making some ground... Turns out that the ExternalContext interface has a getNativeRequest() which is the actual HttpServletRequest object. From there I can get the full query string thusly:

externalContext.getNativeRequest().getQueryString()

So now I assume that since there is a Special EL variable called externalContext, i would just do this:

${externalContext.nativeRequest.queryString}

right? Wrong! It turns out the externalContext variable is not available from the JSP page. Anyone know why? However, there is also flowRequestScope, which is available to the JSP and has a getExternalContext method, so now I can do this:

${flowRequestScope.externalContext.nativeRequest.queryString}

Cool, that works... But why is it necessary? Why are only some of the Special EL variables pushed to the JSP page, and why do some of them change (viewScope seems to have all of its values promoted up a level to root so viewScope.commandName is referenced as ${commandName} in the JSP EL)? I must be missing something fundamental in the way WebFlow works. Can someone point me in the right direction?

Lucas
  • 14,227
  • 9
  • 74
  • 124

1 Answers1

0

In webflow, essentially the scope map is for ease of differentiation for your controlling logic on the server. In straight up Spring MVC, that would be your controllers, but in webflow your flow more or less serves this purpose directly. Virtually everything you put in your scope map is rolled up into the request attributes for use on the JSP, except for request scope which is explicitly destroyed when the flow returns. That's why viewScope.commandName is available in the JSP - because it, like the other scopes, are rolled up into a large request attribute map which is then placed into the request for your JSPs to access.

The difference is that the lower-lived scopes are used first. Lower scopes always take precedence over longer-lived scopes, just like local variables in Java taking precedence over class-level variables of the same name. So you need to make sure to use unique parameter names just in case so there is no chance of collision.

If you really needed that value, it would be easiest to, in the flow, use a set tag to set that value in an appropriate scope so that you had it named easier, such as

<set name="viewScope.currentService" value="externalContext.nativeRequest.queryString" />

That way you have the EL variable "currentService" available in your view scope. You may want to use on-render or on-entry to store this value into your view. For this particular value, I'd probably use on-render since it's something that may be change based on how the view is rendered, but it might not matter either way.

MetroidFan2002
  • 29,217
  • 16
  • 62
  • 80
  • Is there any documentation anywhere (short of reading the source) that specifies how and which values are _rolled up_ into the request map? Do the values from `externalContext` also get _rolled up_ so that I could try something like `${nativeRequest.queryString}`? – Lucas Oct 30 '12 at 14:36