1

I'm trying to deal with the well known "issue" where the action method of a h:commandLink doesn't get invoked when placed inside a dataTable that gets its data from a request scoped bean. Due to project constraints, i'm limited to use JSF 2.0 and RichFaces 3.x (which partially supports it), so i can't rely on Tomahawk's solution (preserveDataModel).

After a day spent on searching and trial/error:

  • I've read that the "data model" that the dataTable feeds on needs to be stored in the session. How can I do that without making the whole bean a session scoped one? I tried with a static variable that holds the data, but doesnt work.
  • I've tried to use the a4j:keepAlive with my bean (that implements Serializable, if it matters), but failed to make it work.
  • Making the bean ViewScoped doesn't work either.

Any help regarding to this would be appreciated.

EDIT:

Here is what i'm trying to do:

In the page there is a combo displaying a number of options retrieved from the database. When the user selects one, a dataTable is filled with info related to the option selected. The data of the first column are rendered as command links. If the user clicks the link, it should invoke the specified method, but it doesn't get called.

mypage.xhtml

<h:form>
<!-- Placed a <a4j:keepAlive beanName="myBean"> in this line, but didn't work -->
<h:selectOneMenu value="#{myBean.selectedOption}">
    <f:selectItems value="#{myBean.optionsList}" var="option"
                   itemLabel="#{option.labelProperty}" itemValue="#{option.valueProperty}"/>
    <a4j:support event="onchange" action="#{myBean.getDataBasedOnSelectedOption}"
        reRender="table_panel" ajaxSingle="true"/>
</h:selectOneMenu>

<a4j:outputPanel id="table_panel" >
    <rich:dataTable id="table" value="#{myBean.data}" var="dataRow"
             rendered="#{not empty myBean.selectedOption}">
        <f:facet name="header">
            <rich:columnGroup>
                <rich:column>Some column header</rich:column>
            </rich:columnGroup>
        </f:facet>

        <rich:column>
                <a4j:commandLink  action="#{myBean.linkClickedAction}"
                    value="#{dataRow.someProperty}"/>
        </rich:column>
</a4j:outputPanel>

MyBean.java

@ManagedBean(name="myBean")
@RequestScoped //Tried with @ViewScoped but didn't work

private List<MyPOJO1> optionsList;
private List<MyPOJO2> data; //Made this variable static, but didn't work
private String selectedOption;

@PostConstruct
public void init()
{
    optionsList = getOptionsListFromDatabase();
}

public String getDataBasedOnSelectedOption()
{
    data = getRelevantDataFromDatabase(selectedOption);

    return null;
}

//This method doesn't get called
public String linkClickedAction()
{
    System.out.println("I'm here!");

    return null;
}

public List<MyPOJO1> getOptionsList()
{
   return optionsList;
}

public void getSelectedOption()
{
    return selectedOption;
}

public void setSelectedOption(String selectedOption)
{
    this.selectedOption = selectedOption;
}
etercap
  • 187
  • 3
  • 9
  • 2
    Using view scope or should definitively work. Could you post more details how you tried it? – chkal Dec 04 '10 at 06:36

1 Answers1

0

If a4j:keepAlive or @ViewScoped doesn't work, then the chance is big that the data loading logic for the datamodel is wrong. Likely you're loading it inside the getter based on some parameters instead of doing it in the action method, or constructor, or @PostConstruct of the bean. The getter will namely also be called during apply request values phase of the JSF lifecycle to determine the row on which the commandlink is pressed, so that JSF can determine which action needs to be invoked. If the getter doesn't return the datamodel with the expected row, then the action simply won't be invoked.

Fix it accordingly. The getter should only return the bean property or at highest only do lazy loading.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555