Announcement Announcement Module
No announcement yet.
[SWF2] Putting data on request to be used in view Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • [SWF2] Putting data on request to be used in view

    In our current flow-based architecture we invoke prepare methods on the controller before each page in order to ensure the model/form bean is in the correct state prior to displaying the page. We also use the prepare method to place data on the request which may then either be displayed on the page, or used to control rendering on the page. This basically boiled down to calling getRequest().setAttribute(key, value) in the controller and <%=request.getAttribute(key)%> in the JSP.

    I am now trying to do the same in SWF2 and Facelets and have tried various approaches using RequestContext, RequestParameterMaps, NativeRequest, etc. along with #{requestScope.key}, #{param['key']}, etc. but haven't yet hit on the right combination.

    Can anyone help - I'm sure there is a simple answer..... but I can't find it!


  • #2
    Is there any reason why you aren't using more appropriate scopes, like viewScope? If you just need an attribute to control the display of something on the page (and if it should survive redirects), use viewScope. I would suggest you read up on the various scopes SWF offers, as you may find some of them more appropriate for your attributes than simply request or session scope.

    Once an attribute is in the appropriate scope (using set actions, evaluate actions, or scoped Spring beans), you can reference it on your page with #{key} or, if you really need it, #{viewScope.key} (or whichever scope is appropriate.


    • #3
      Thanks again

      Thanks Again InverseFalcon,

      I am defining an architecture which is as independent of the flow engine as possible in order to avoid tie-in (which we are suffering from at the moment, and don't want to repeat) or at least make migration as cheap as possible. So we have already, for example, abstracted out the business logic for each flow state into a plain java delegate object with a standard, flow-agnostic, interface.

      However, as this stuff would need to go into our Spring Web Flow adaptor layer anyway, it probably would be OK to use the viewScope, accessing it as #{xxxx} in the view. My only concern then is we would need to do the call from on-entry in the view-state rather from a separate action-state, but that concern is probably more down to what I am used to, but I do have concerns such as whether this means the on-entry will get called if there is an error and the page is redisplayed.

      I would still like to know how to put something in the request in the controller and retrieve it on the page, for information.

      Thanks again,



      • #4
        Sounds like we're using different approaches, here. I didn't realize you were putting attributes into scope from within your controller code. I'm assuming this controller is like a JSF backing bean, orchestrating the interaction of several model objects (which may be attributes in other scopes), right?

        The design I favor doesn't use an orchestrating controller. If I need to perform some operations using various attributes, I'll typically have a method on a model object which does what I need, and accepts the attributes as method parameters. I might place a returned object into scope in my evaluate or set action. In a sense, the flow definition itself is taking the place of a traditional custom controller. In any case, my model objects rarely need to be aware of SWF, since I'm rarely interacting with the scopes directly from them. The most intrusive thing I do is pass in a MessageContext, and use MessageBuilder, when I need to show some kind of generated message on the page. Even then, if it's possible to generate the message from outside my model, I can do this with a simple custom MessageCreator class used as a prototype-scoped Spring bean.

        Without knowing what it is you want to put in request/view scope, I can't offer very specific advice. If there's an error executing on-entry actions, then an exception will be thrown. It shouldn't render the page. It may trigger an on-exception transition (not sure about this). If you've got an exception handler defined on the flow, then it should catch it, in any case.

        As I recall, you still have requestScope in SWF, but I think this is actually a different thing than the native request object you're used to. SWF exposes various scopes, including requestScope, as special EL variables. If you had to, you could pass this to your method as a parameter, and add any attributes you need to it.

        As a side note, I do find requestScope useful for ferrying values to and from view-scope. For example, if I generate a value from some other state which needs to be used as a viewScoped attribute in a view-state, I can set the value in requestScope, and then move it to viewScope in the on-entry section of my view-state. Likewise, if a view-scoped attribute needs to be used in some kind of processing action-state after my view-state, I can ferry it along by moving it to requestScope. I will rarely use requestScoped attributes on my pages directly, however.


        • #5
          Hi InverseFalcon,

          You're assumptions about what I am doing are basically correct.

          I have a number of drivers which I am using to define the architecture, which are: re-use existing artefacts where possible, follow the Single Responsibility Pattern (SRP) and allow ease of migration. Our current apps use a web flow technology based on Struts, WebLogic Pageflows, the forerunner of Apache Beehive. Pageflows have a single controller class for a flow but as this class was a proprietory format, the business logic was extracted to a flow delegate with prepare and process methods for each page, called from prepare and process actions in the controller.These methods returned an object which contained a map of error messages, a map of items to be put into the request and a string indicating the transition. A base controller class would then process the returned objects converting the error message map into Struts ActionErrors and calling SaveErrors and extracting the items from the request map and putting them on the request before returning the transition string to cause a forward to the next page.

          As you say, the flow has now effectively replaced the controller and we are using MessageContext in place of ActionErrors etc. But at the moment I have basically taken the decision to have a 'controller adaptor' layer to do the job of forwarding to the flow delegate and processing the response, i.e. mapping the generic error and request maps to Spring Web flow artefacts. It may well be as I become more familiar with web flow that I decide we can do away with the adaptor layer.

          Your advice to use the viewScope worked, but I still don't understand why replacing viewScope with requestScope does not work. Is requestScope instantiated as soon as a request comes in?

          Thanks again,



          • #6
            When referenced in SWF, RequestScope refers to a MutableAttributeMap for holding request-scoped attributes (see RequestContext javadoc and its getRequestScope() method).

            You're likely using the actual HttpServletRequest object, which can be obtained in SWF through the getNativeRequest() method of the ExternalContext, which can be obtained through the RequestContext. I'm guessing there's some sort of mismatch in which one you're interacting with, and which one SWF is actively using.

            Before I was using SWF, I had a similar framework to yours, and either inherited from or worked within the context of a class which offered methods to get and set values from and to various scopes. That might be useful here with your controller adapter layer, and you can use that to interact with the appropriate object or scope.