views:

492

answers:

3

I have following code in jsf page, backed by jsf managed bean

<h:dataTable value="#{poolBean.pools}" var="item">
    <h:column>
        <f:facet name="header">
                <h:outputLabel value="Id"/>  
        </f:facet>
        <h:outputText value="#{item.id}"/>
    </h:column>
    <h:column>
        <f:facet name="header">
            <h:outputLabel value="Start Range"/>
        </f:facet>
        <h:inputText value="#{item.startRange}" required="true"/>               
    </h:column>
    <h:column>
        <f:facet name="header">
            <h:outputText value="End Range"/>
        </f:facet>
        <h:inputText value="#{item.endRange}" required="true"/>                            
    </h:column>
    <h:column>
        <f:facet name="header">
            <h:outputText value="Pool type"/>
        </f:facet>            
        <h:selectOneMenu value="#{item.poolType}" required="true">
            <f:selectItems value="#{poolBean.poolTypesMenu}"/>
        </h:selectOneMenu>
    </h:column>
    <h:column>
        <f:facet name="header"/>
        <h:commandButton id="ModifyPool" actionListener="#{poolBean.updatePool}" image="img/update.gif" title="Modify Pool">
            <f:attribute name="pool" value="#{item}"/>
        </h:commandButton>
    </h:column>
</h:dataTable>

This code fragment is dedicated to editing come collection of items. Each row of the table contains "edit" button that submits changed values of the row to the server. It has the item itself as an attribute. Submit is performed by calling actionListener method in the backing managed bean.

This code runs correctly on Glassfish v 2.1

But when the server was updated to Glassfish v 2.1.1, the attribute stopped to be passed correctly. Instead of passing edited item (when we change the values in table row, we are actually changing the underlying object fields), the source item is submitted to server, i.e. the item that was previously given to the page. All the changes that were made on the page are discarded.

I tried to update jsf version from 1.2_02 to 1.2_14 (we are using jsf RI), but it had no effect.

Perhaps anyone came across the same problem? Any help and suggestions will be appreciated.

A: 

Glassfish ships with bundled JSF. Glassfish v2.1.1 ships with Mojarra 1.2_13. You actually don't need to have your own JSF libs in the /WEB-INF/lib. I am not sure how this particular problem is caused, but to start, you need to ensure that you don't have JSF version collisions in the classpath.

That said, the preferred JSF 1.2 way of passing bean properties is using f:setPropertyActionListener.

<h:commandButton id="ModifyPool" actionListener="#{poolBean.updatePool}" image="img/update.gif" title="Modify Pool">
    <f:setPropertyActionListener target="#{poolBean.pool}" value="#{item}"/>
</h:commandButton>

Update: I recall something; this problem suggests that you still have a JSF 1.2 version older than 1.2_05 around in the classpath. Handling of component attributes has changed as per this version in favour of performance enhancements. In a nutshell, if you have a jsf-api.jar of older than 1.2_05 in your classpath, while there's a jsf-impl.jar of 1.2_05 or newer in your classpath, you will experience exactly this problem.

The solution is obvious: cleanup your classpath to get rid of the older JSF version. Paths covered by the webapp's default classpath are under each /WEB-INF/lib, Appserver/lib (which is in case of Glassfish somewhere in Appserver/domains/domainname/*) and the JRE/lib and JRE/lib/ext. Keep in mind that Glassfish's javaee.jar includes JSF libraries as well, so you really need to ensure that you don't have that JAR (or any other appserver-specific JAR file) in your /WEB-INF/lib or somewhere else.

BalusC
Thank you very much for your suggestion.I removed all jsf libraries from my application and downloaded clean version of Glassfish.In the server.log I can clearly see that my application is using bundled jsf libraries: Initializing Mojarra (1.2_13-b01-FCS) for context '/networkservice'|#]I also tried both ways of passing the object to managed bean: using f:attribute and f:setPropertyActionListener. Still I see unchanged object in the bean
Oleg Rybak
What do you mean with "unchanged"? What's the functional requirement?
BalusC
In each row of the table I have an object from collection. Each cell represents some property of this object. Each row contains submit button. By clicking on it I pass particular object to action listener and managed bean saves it.Before updating Glassfish server, any editing of the fields in data table resulted in change of the target object fields and action listener received changed (edited) object. But now the source objec (unedited) is passed to the bean
Oleg Rybak
A: 

You can add JBoss EL and write:

#{poolBean.updatePool(item)}

You don't need the whole Seam for that, works fine with JSF RI.

lexicore
A: 

Probably it has to do with the way JSF 1.2 implements actionListener. In JSF 1.1 and until recent implementations of JSF 1.2 (Richfaces, Trinidad etc) the order was setPropertyActionListener (or Attribute) -> actionListener -> action. In JSF 1.2 and now implemented in Richfaces and Trinidad (not sure about IceFaces) the order is actionListener -> setPropertyActionListener (or Attribute) -> action. I know it is disturbing and very annoying... Who thought of it? What did they have in mind? Anyway, try using an action instead of an actionListener and see if it works.

Giorgos Chasapis
`f:setPropertyActionListener` is not available in JSF 1.1. It's introduced in JSF 1.2.
BalusC