0

I have run into a strange problem/bug and couldn't find a working solution anywhere...

The situation is : I have a Spring Web Flow calling a view state which contains a dataTable showing a list of object with an "Edit" button next to each of them.

Here is what the SWF looks like:

<?xml version="1.0" encoding="UTF-8"?>    
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
    http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
parent="parent-flow" start-state="home">

<persistence-context />

<var name="myObject" class="com.domain.MyObject" />

<view-state id="home">
    <on-render>
        <evaluate expression="myObjectService.findAll()"
            result="viewScope.myObjectList" result-type="dataModel" />
    </on-render>
    <transition on="edit" to="editMO" />
    <transition on="search" to="home" />
</view-state>

<subflow-state id="editMO" subflow="myObject/addEdit">
    <input name="myObject" required="true" />
    <transition to="end" />
</subflow-state>

<end-state id="end"
    view="externalRedirect:servletRelative:/home" />

</flow>

Some explanation :

1) the "MyObject" class is a simple pojo with some attributes and an entity annotation for persistence.

2) the "myObjectService.findAll()" gives me back the list of all the stored "MyObject".

Now here is the view code (which use a template standard.xhtml) :

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    template="/WEB-INF/layouts/standard.xhtml">

    <ui:define name="title"></ui:define>

    <ui:define name="content">
        <h:form>
                <div>

                    <p:dataTable id="tbl" value="#{myObjectList}" var="item">
                        <f:facet name="header">Result list</f:facet>
                        <p:column>
                            <f:facet name="header">Name</f:facet>#{item.name}
                        </p:column>

                        <p:column>
                            <f:facet name="header">Description</f:facet>#{item.description}
                        </p:column>

                        <p:column>
                            <f:facet name="header">Whatever</f:facet>#{item.whatever}
                        </p:column>

                        <p:column>
                            <f:facet name="header">Actions</f:facet>
                            <p:commandButton value="Edit" action="edit" icon="ui-icon-edit">
                                <f:setPropertyActionListener value="#{item}"
                                    target="#{myObject}" />
                            </p:commandButton>
                        </p:column>
                    </p:dataTable>
                </div>
            </p:panel>
        </h:form>
    </ui:define>

</ui:composition>

When I click on one of the "Edit" button, the trace the tells me the view is re-rendering but the action/event "edit" is never ever triggered, detected nor catched anywhere (that I know of at least).

Funny thing is : if I move the call to the service (to load the object list) from the Flow to the dataTable "value" attribute inside the view like this :

<p:dataTable id="tbl" value="#{myObjectService.findAll()}"

Everything works perfectly fine! but then I get way to many calls on every render event (seen up to eleven...) which I obviously don't want.

I saw many posts on subjects close to my problem but none could solve it (tried to change the flow redirection attribute "redirect-in-same-state" to false, force lazy to off, change the scope of components and variables, force the scope of the service or backing bean, and so on...)

So since I'm running out of ideas anyway I thought i would give this a shot in here. Anybody has an idea?

Trouiller
  • 1
  • 3

2 Answers2

0

Well, the question was asked a long time ago, but I'm facing the same problem now. So here is what I found out.

The last SWF Booking-faces (Web Flow: 2.4.0.M1) sample has the same problem.

At the "main-flow.xml" it defines:

<view-state id="enterSearchCriteria">
    <on-render>
        <evaluate expression="bookingService.findBookings(currentUser?.name)" **result="viewScope.bookings"** result-type="dataModel" />
    </on-render>
    <transition on="search" to="reviewHotels"/>
    <transition on="cancelBooking">
        <evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
    </transition>
</view-state>

And at "enterSearchCriteria.xhtml" it declares a <p:dataTable> that iterates over the bookings. The dataTable has this column definition:

<p:column>
    <f:facet name="header">Action</f:facet>
    <p:commandButton id="cancel" value="Cancel" action="cancelBooking" update=":bookings"/>
</p:column>

When you click the Cancel button nothing happens. I can see by looking at the trace that the view is re-rendering but the method "bookingService.cancelBooking(bookings.selectedRow)" is never called.

But if I change the scope of the "bookings" variable to "conversationScope" it works:

<view-state id="enterSearchCriteria">
    <on-render>
        <evaluate expression="bookingService.findBookings(currentUser?.name)" **result="conversationScope.bookings"** result-type="dataModel" />
    </on-render>
    <transition on="search" to="reviewHotels"/>
    <transition on="cancelBooking">
        <evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
    </transition>
</view-state>

Is this a bug with viewScope/flowScope?

Baldo
  • 111
  • 5
0

Try adding the immediate="true" attribute to the commandButton. This gives the button priority over the validation and the action should be processed.

COBRA.cH
  • 149
  • 1
  • 11