Announcement Announcement Module
Collapse
No announcement yet.
How do you bind session attributes to object with webflow? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How do you bind session attributes to object with webflow?

    How do you bind session attributes to an object with webflow? FormAction automatically binds request attributes but how do you bind session attributes or for that matter attributes from any arbitrary scope?

  • #2
    I think you are confusing the HttpServletRequest with the WebFlow RequestContext. WebFlow binds parameters from the HttpServletRequest, not attributes fromt the RequestContext.

    Comment


    • #3
      I know

      I want to bind from HttpSession

      Comment


      • #4
        FormAction takes event parameters and binds them to a backing object in a configurable scope (either request or flow.) In a servlet environment, the Event is a HttpServletRequestEvent, so the parameters are actually request parameters...

        What are you trying to do again? Connect parameters in the request to a object in the session? In this case, I'd use a custom action to take the "context.getOriginatingEvent().getParameters() " and bind them to the session object, casting the Originating event to a HttpServletRequestEvent and accessing the HttpSession.

        Comment


        • #5
          No I want is...

          rather than accessing the session object through request.getSession I want to inject the dependencies which exist in session into the backing object. i.e rather than service locator I want IoC.

          Comment


          • #6
            UPDATED

            Hmmm....well, that's kind of tricky as you need the request to pull the object out of the session to be thread safe.

            My recommendation is to have a locator interface that decouples you from any specific object retrieval strategy:

            Code:
            public HttpSessionObjectAccessor implements FlowObjectAccessor {
                public Object getObject(String objectName, RequestContext context) {
                    HttpServletEvent event = (HttpServletEvent)context.getOriginatingEvent();
                    return event.getRequest().getSession().getAttribute(objectName);
                }
            }
            
            public interface FlowObjectAccessor {
                public Object getObject(String objectName, RequestContext context);
            }
            This is actually a pretty good pattern, worth consideration adding as a suport class.

            Inject a configured instance into your action code, and then invoke it on each request to get the session object.

            Keith

            Comment


            • #7
              How does that work when there are > 1 objects?

              How does that work when there are > 1 objects?

              Comment


              • #8
                We'll need to change the interface to take a object name parameter...

                Comment


                • #9
                  Doesn't seem to accomplish what I want...

                  Doesn't seem to accomplish what I want... i.e: still service locator vs Ioc.

                  Let me see if I understand.

                  1) Web flow is like struts in that instance variables that are specific to request and likely to change from user to user are bad because the action classes are actually singletons not instantiated per request. right?

                  2) Here is the example in practical guide

                  Code:
                  <bean id="person.Search.criteria.formAction"
                     class="org.springframework.web.flow.action.FormAction">
                      <property name="formObjectName" value="query"/>
                      <property name="formObjectClass" value="org.springframework.samples.phonebook.domain.PhoneBookQuery"/>
                      <property name="formObjectScopeAsString" value="flow"/>
                      <property name="validator">
                          <bean id="queryValidator" class="org.springframework.samples.phonebook.domain.PhoneBookQueryValidator"/>
                      </property>
                  </bean>
                  This code caused PhoneBookQuery to be created in flow scope if it didn't already exist and it's attributes to be set from requests.

                  Now what I want is as follows.
                  Attributes exist in session which apply to an object that may or may not exists in the scope I want. Similar to above I want the object of the specified class to be created if it doesn't exist in the scope I want and it's values to be populated from the session rather than request. Better yet rather than it explicitly being populated from request as above I would like something like:

                  Code:
                  <bean id="person.Search.criteria.formAction"
                     class="org.springframework.web.flow.action.FormAction">
                      <property name="populateFrom" value="request,session,flow"/>
                      <property name="formObjectName" value="query"/>
                      <property name="formObjectClass" value="org.springframework.samples.phonebook.domain.PhoneBookQuery"/>
                      <property name="formObjectScopeAsString" value="flow"/>
                      <property name="validator">
                          <bean id="queryValidator" class="org.springframework.samples.phonebook.domain.PhoneBookQueryValidator"/>
                      </property>
                  </bean>
                  See <property name="populateFrom" value="request,session"/>

                  That way it will try to populate from request first and then from session or in what ever order I specify with the first in the order taking precedent if it exists in both places.

                  Then

                  Code:
                  PhoneBookQuery query = &#40;PhoneBookQuery&#41;context.getFlowScope&#40;&#41;.getAttribute&#40;"query"&#41;;
                  as in your example is sufficient to retreive the created object. I don't see the benefit of the interface that you described.

                  Comment


                  • #10
                    Well, the benefit of what I proposed is it fully decouples your actions from the HttpSession. That's it, really.

                    Yes, actions are singletons, as documented in the Action interface...

                    I''m having a hard time following you. I'll try and give a read again in a bit.

                    Comment


                    • #11
                      Perhaps I see what you are trying to say....

                      Parameters vs Attributes... So in addition I guess I need a mechanism to populate from attributes not just parameters so

                      <property name="populateFrom" value="requestParam,request,session,flow"/>

                      with the default being requestParam

                      Comment


                      • #12
                        When you say populate, you mean "bind" right. You want to bind input in some attribute source to a backing form object? You want to be able to take into account multiple attribute sources in a configurable order?

                        I think I get it, but please, let's use our terminology or else confusion results.

                        One issue here is there is no 'session' construct known to the web flow system: only request and flow. I'm not sure if it makes sense to add first-class support for session attributes, attempting to mask the location of the session store for different environments. We'll have to see about that.

                        I agree with a "AttributeSourceChain" that will try to resolve a attribute in one or more ordered sources, like event/request/flow. Sounds useful - if we can get the spring data binder retrofitted to work with the attribute source interface, it shouldn't be a big deal.

                        Keith

                        Comment


                        • #13
                          Yes that's it...

                          Actuially it's fine not to have first-class support for session attributes. If I want to access a session attribute directly I can always put it into request scope or flow scope using the same method we described.

                          I'll give the actual example of what I am trying to accomplish.

                          in session there are 2 attributes (type:Integer and specialty:String)
                          I want to encapsulate those attributes in a Profile object that then I can access typesafely from my action. so in this case I would have a backing form object containing type and specialty. Workflow FormAction would automatically bind to my backing form object from session and I can chose to have this object in either request or flow scope so in my action I can simply call

                          Code:
                          Profile profile = &#40;Profile&#41;context.getRequestScope&#40;&#41;.getAttribute&#40;"profile"&#41;;
                          The only reason I would want to refer to my object in session scope is if the object is already there in which case your interface accomplishes this nicely. I don't like the interface method however because there could be different sources for the object (besides just session) and I didn't see how that would be addressed.

                          Comment


                          • #14
                            Actually I like the interface..

                            Basically what you are say in the implementation as to where the source is is up to me but in that case I should be able to inject the implementation for resolving each object


                            i.e: action itself implements

                            public Object getObject(String objectName, RequestContext context);

                            public void setObjectRetreivalImplementation(Hashmap implementations);

                            The implementation will look up in implementations hashmap and call method

                            public Object getObject(String objectName, RequestContext context);

                            which all implementations will have to implement.

                            So basically I just inject in implementations and everything should work...

                            Comment


                            • #15
                              I opened a JIRA for this:

                              I opened a JIRA for this:
                              http://opensource.atlassian.com/proj...browse/SPR-934

                              Comment

                              Working...
                              X