Announcement Announcement Module
Collapse
No announcement yet.
Get Request Parameter in 2.0 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Get Request Parameter in 2.0

    I want to get the request parameter in the url of a new flow.

    for example:

    /booking.html?userId=3


    I have this in the flow.xml
    Code:
        <on-start>    
            <set name="requestScope.userId" value="requestParameters.userId" type="long" />   
        </on-start>
    Code:
    protected Object createFormObject(RequestContext context) throws Exception {
      Object obj = context.getRequestScope().get("userId");
      // obj is null ?? 
    
    }


    What is the best way to get that userId, so that I can lookup that user? From the RequestContext?
    Last edited by gparker; Mar 15th, 2008, 10:18 AM. Reason: more info

  • #2
    The best way is to map it into your flow using <input/> like this:

    Code:
    <input name="id" value="flowScope.id"/>
    With the default flow controller, all request parameters are exposed in the input map when a flow starts up by default.

    This way you decouple your flow from a external context request parameter map, and rely on mapping input attributes instead... this allows for better flow re-use.

    The reason your object is null in your code is you're trying to look up "eventId" but "userId" is your attribute's name. In general, I would not do such lookup in action glue code. Use EL expressions in the flow to pass the user id into your service/DAO to load the user object. In general, with SWF 2 custom actions should be the exception not the rule.

    Keith

    Comment


    • #3
      I had a typo. The string values ("userId") are the same and it is still null.

      Comment


      • #4
        But, like in the example:
        Code:
        	<bean id="bookingActions" class="org.springframework.webflow.action.FormAction">
        		<property name="formObjectClass" value="org.springframework.webflow.samples.booking.Booking" />
        		<property name="propertyEditorRegistrar">
        			<bean class="org.springframework.webflow.samples.booking.PropertyEditors" />
        		</property>
        		<property name="validator">
        			<bean class="org.springframework.webflow.samples.booking.BookingValidator" />
        		</property>
        	</bean>
        If I needed to lookup objects and set them on the formObjectClass what would be the best way to do that?

        Need somthing like this:
        Code:
          booking.setUser(user);
        That's why I overrode the createFormObject(RequestContext context) method in my FormAction. Trying to lookup the user.

        Comment


        • #5
          I would create a helper service method that creates my form object when the flow starts and within that method sets the user.

          Like this:
          Code:
          	<on-start>
          		<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
          	</on-start>
          Code:
              @Transactional(readOnly = true)
              public Booking createBooking(Long hotelId, String username) {
          	Hotel hotel = em.find(Hotel.class, hotelId);
          	User user = findUser(username);
          	return new Booking(hotel, user);
              }
          Keith

          Comment


          • #6
            I think I'm starting to understand to how to best use SWF 2.0.

            I tried what you suggested but now I get this:

            Code:
            Exception thrown in state 'null' of flow 'registration'; nested exception is org.springframework.binding.convert.ConversionException: No converter registered to convert from sourceClass 'class [Ljava.lang.String;' to target class 'class java.lang.Long'
            
            RequestURI=/registration.html
            Caused by:
            
            org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'null' of flow 'registration'; nested exception is org.springframework.binding.convert.ConversionException: No converter registered to convert from sourceClass 'class [Ljava.lang.String;' to target class 'class java.lang.Long'
            	at org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:529)
            	at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:239)
            	at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:112)
            	at org.springframework.webflow.mvc.FlowController.handleRequestInternal(FlowController.java:80)
            	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
            	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
            	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
            	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
            	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:523)
            	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:453)
            
            
            .......
            
            Caused by: org.springframework.binding.convert.ConversionException: No converter registered to convert from sourceClass 'class [Ljava.lang.String;' to target class 'class java.lang.Long'
            	at org.springframework.binding.convert.support.GenericConversionService.getConversionExecutor(GenericConversionService.java:150)
            	at org.springframework.binding.convert.support.GenericConversionService.getConversionExecutor(GenericConversionService.java:148)
            	at org.springframework.binding.convert.support.RuntimeBindingConversionExecutor.execute(RuntimeBindingConversionExecutor.java:56)

            Comment


            • #7
              Hmmm, your source parameter is being returned as a String[] array instead of a String. Are you submitting the parameter twice?

              Keith

              Comment


              • #8
                I don't think so. If I don't put eventId, it doesn't exist.

                /booking.html?wrongId=1

                I get this:
                Code:
                Exception thrown executing org.springframework.webflow.action.EvaluateAction@1c818c4 in state 'null' of flow 'registration' -- action execution attributes were 'map[[empty]]'; nested exception is org.springframework.binding.expression.EvaluationException: [EvaluationAttempt@14cab63 expression = registrationService.createRegistration(eventId), context = [RequestControlContextImpl@881734 externalContext = org.springframework.webflow.context.servlet.ServletExternalContext@932892, requestScope = map[[empty]], attributes = map[[empty]], flowExecution = [FlowExecutionImpl@250179 flow = 'registration', flowSessions = list[[FlowSessionImpl@183c7a0 flow = 'registration', state = [null], scope = map['entityManager' -> org.hibernate.ejb.EntityManagerImpl@a70122]]], flashScope = map[[empty]]]]] failed - make sure the expression is evaluatable in the context provided; nested exception is ognl.NoSuchPropertyException: org.springframework.webflow.engine.impl.RequestControlContextImpl.eventId
                
                RequestURI=/rw/registration.html
                Caused by:
                
                org.springframework.webflow.engine.ActionExecutionException: Exception thrown executing org.springframework.webflow.action.EvaluateAction@1c818c4 in state 'null' of flow 'registration' -- action execution attributes were 'map[[empty]]'; nested exception is org.springframework.binding.expression.EvaluationException: [EvaluationAttempt@14cab63 expression = registrationService.createRegistration(eventId), context = [RequestControlContextImpl@881734 externalContext = org.springframework.webflow.context.servlet.ServletExternalContext@932892, requestScope = map[[empty]], attributes = map[[empty]], flowExecution = [FlowExecutionImpl@250179 flow = 'registration', flowSessions = list[[FlowSessionImpl@183c7a0 flow = 'registration', state = [null], scope = map['entityManager' -> org.hibernate.ejb.EntityManagerImpl@a70122]]], flashScope = map[[empty]]]]] failed - make sure the expression is evaluatable in the context provided; nested exception is ognl.NoSuchPropertyException: org.springframework.webflow.engine.impl.RequestControlContextImpl.eventId
                	at org.springframework.webflow.engine.ActionExecutor.execute(ActionExecutor.java:52)
                	at org.springframework.webflow.engine.ActionList.execute(ActionList.java:153)
                	at org.springframework.webflow.engine.Flow.start(Flow.java:516)
                	at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:335)
                	at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:235)
                	at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:112)
                
                ....
                
                Caused by: ognl.NoSuchPropertyException: org.springframework.webflow.engine.impl.RequestControlContextImpl.eventId
                	at ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:122)
                	at org.springframework.webflow.expression.WebFlowOgnlExpressionParser$RequestContextPropertyAccessor.getProperty(WebFlowOgnlExpressionParser.java:135)
                	at ognl.OgnlRuntime.getProperty(OgnlRuntime.java:1657)
                	at ognl.ASTProperty.getValueBody(ASTProperty.java:92)
                	at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170)
                Then it doesn't exist. If I put it, it is an Array.

                Comment


                • #9
                  I got it to work with this:
                  Code:
                      <on-start>    
                        <set name="requestScope.id" value="requestParameters.eventId" type="long" /> 
                        <evaluate expression="registrationService.createRegistration(id)" result="flowScope.registration" />
                      </on-start>
                  I could never get it to work with <input name="eventId"...>
                  Code:
                  <input name="eventId" value="flowScope.eventId" type="long"/>
                  <on-start>    
                        <evaluate expression="registrationService.createRegistration(eventId)" result="flowScope.registration" />
                  </on-start>
                  That is only one of the ways I tried it with <input..>. No matter what I tried, the id was either not found or an array. The url is the exact same for both requests.

                  Comment


                  • #10
                    Hmm... well, the requestParameters map is just backed by the underlying Http ServletRequest parameter map. I suggest you do some debugging - what is the content of the underlying HttpServletRequest Parameter map? There has to be as reason why its coming in as a string array... I would then check your jsp to make sure userId is not being submitted twice (e.g. as a action url query param and form hidden parameter).

                    Keith

                    Comment


                    • #11
                      Problem appears to be in FlowController.

                      protected MutableAttributeMap defaultFlowExecutionInputMap(HttpServletRequest request) {
                      return new LocalAttributeMap(request.getParameterMap());
                      }

                      Unlike HttpServletRequestParameterMap, LocalAttributeMap doesn't do the conversion of 1 element arrays into plain values. The arrays are getting propagated all the way through to the EL evaluation.

                      Comment


                      • #12
                        Thanks - nice catch. We'll address the issue this week for RC1.

                        Keith

                        Comment

                        Working...
                        X