2

I am trying to follow the code for Spring Webflow from 'Spring in Action'. However, when I tried to run the application, I got the following error:

org.springframework.webflow.engine.FlowInputMappingException: Errors occurred during input mapping on startup of the 'pizza' flow; errors = [[RequiredError@13cb4078 mapping = order -> flowScope.order, code = 'required', error = true, errorCause = [null], originalValue = [null], mappedValue = [null]]]

I believe the line that instantiates the order object in the following flow xml is responsible for the exception:

<var name="order" class="com.mycompany.pizza.domain.Order" />
    <subflow-state id="customer" subflow="customer-flow">
        <input name="order" value="order"/>
        <transition on="customerReady" to="buildOrder" />
    </subflow-state>

My subflow xml looks like this:

<view-state id="welcome">
    <transition on="phoneEntered" to="lookupCustomer" />
</view-state>

<action-state id="lookupCustomer">
    <evaluate result="order.customer"
        expression="pizzaFlowActions.lookupCustomer(requestParameters.phoneNumber)" />
    <transition to="registrationForm"
        on-exception="com.mycompany.pizza.service.CustomerNotFoundException" />
    <transition to="customerReady" />
</action-state>

Hope there's someone who could point me at the right direction. Thanks!

Terry
  • 41
  • 1
  • 5

1 Answers1

0

The error is saying you are REQUIRED to pass a NOT NULL input param/obj "order" to your subflow and you are passing a null value in the order input. So if it is not provided it will throw the exception you see. At the top of your subflow should look something like this:

<input name="order" required="true" type="com.mycompany.pizza.domain.Order"/>

That being said, generally I think when passing pojos between flows/subflows it is good practice to be very explicit and fill out the 'type' attribute in both input tags on the caller of the subflow and the subflow itself and to fill out the scope prefix for the value attribute (e.g flowScope.order)

Moreover, I think your problem is that the <var> tag is NOT initializing your Order pojo that is why it is null it is the equiv of:

Order order = null;

You should explicitly set flowScope.order via a new operator or a factory-method call using the 'set' tag inside an 'on-start' tag in beginning of your parent flow. Something like this:

<on-start>
       <set name="flowScope.order" value="new com.mycompany.pizza.domain.Order()"/>
        <!-- for development purposes... assuming you are using log4j grab the logger and check that order is in fact NOT null -->
        <evaluate expression="T(org.apache.log4j.Logger).getLogger('someLogger').info(flowScope.order)"/>
</on-start>

and then (still inside your parent flow) change your subflow call to look like this:

<subflow-state id="customer" subflow="customer-flow">
    <input name="order" value="flowScope.order" type="com.mycompany.pizza.domain.Order"/>
    <transition on="customerReady" to="buildOrder" />
</subflow-state>

and... Make sure you also fill out the type attribute inside the input tag of your subflow.xml for order like so:

<input name="order" required="true" type="com.mycompany.pizza.domain.Order"/>
Selwyn
  • 3,118
  • 1
  • 26
  • 33
  • That didn't work for me. I am also having trouble implementing the logger as I was unable to see any log output on my end. For the logger, what I have done is just to add the expression in my flow.xml and include the dependencies. Are there any additional steps? – Terry Jun 26 '15 at 05:01
  • @Terry you need to configure log4j before you can use it. Do you have a log4j.xml or log4j.properties file in the 'src/main/resources' folder of your project? – Selwyn Jun 26 '15 at 06:38
  • I was able to implement logging. I have checked that I am able to log DEBUG and INFO logs. However, the INFO logs did not show me any hints of any object being instantiated. Should I replace 'someLogger' with any other things? – Terry Jun 27 '15 at 16:10
  • @Terry the 'someLogger' is just for your own naming purposes. The evaluate statement in my answer should print the obj reference Id (or the implementation of a toString() overrided method on the Order class) but the most important thing is the output of that is NOT 'null' because that is your problem you are passing a null Order into your subflow – Selwyn Jun 27 '15 at 16:47
  • If the object is null, does the log show? I tried the following line in `` `` but it does not log as well. The log file does show other INFO logs – Terry Jun 27 '15 at 19:56
  • @Terry I see the issue. You need to explicitly add your logger 'someLogger' into your log4j config. Now depending if you used .properties or .xml version of log4j config it will be slightly different. I personally use log4j.xml so it would look like this: also see http://stackoverflow.com/questions/6358836/log4j-how-to-configure-simplest-possible-file-logging (note: 'someLogger' is just a dummy string... usually you would use application's package path + class executing the code or a meaningful name like 'webflow') – Selwyn Jun 27 '15 at 23:19
  • I used the expression `T(org.apache.log4j.Logger).getRootLogger().info(flowScope.order)` but was not able to see anything in the log file. The last few lines of the log shows: `Refreshing Flow ApplicationContext [pizza]: startup date [Mon Jun 29 14:59:09 EDT 2015]; parent: WebApplicationContext for namespace 'spring-dispatcher-servlet' Replacing scope 'request' from [org.springframework.web.context.request.RequestScope@2acbaaf4] to [org.springframework.web.context.request.RequestScope@7c88243f] JSR-330 'javax.inject.Inject' annotation found and supported for autowiring ` – Terry Jun 29 '15 at 19:03
  • please see the following screenshot. http://prntscr.com/7mttv8 are you sure you are hitting the correct flow? is the 'pizza' the flow the one with the getRootLogger().info statements? if you have getRootLogger().info statements in the 'on-start' tag it will always execute every time you enter that flow. If you don't see it then you're most likely entering another flow. – Selwyn Jun 29 '15 at 19:47
  • and your log4j config should look something like this. http://prntscr.com/7mtzbo make sure you are outputting to the console not just a file. – Selwyn Jun 29 '15 at 19:57
  • I did some debugging and found out that the object was instantiated and got logged during the subflow, not the primary flow. Also, I would need to remove the 'required' attribute from the input tag. Some things just don't look right. I might re-do this project over the weekend to see if I still hit the same problem. – Terry Jul 01 '15 at 03:44