Search code examples
jsfrichfacescdi

How to pass a row object to the backing bean using JSF 2 and RichFaces?


I am using RichFaces's ordering list to display a table custom Command objects to the user. The user uses a form to create new commands which are then added to the list. Here is the orderingList implementation:

app.xhtml

<rich:orderingList id="oList" value="#{commandBean.newBatch}" var="com"
listHeight="300" listWidth="350" converter="commandConverter">

<f:facet name="header">
    <h:outputText value="New Batch Details" />
</f:facet>
<rich:column width="180">
    <f:facet name="header">
        <h:outputText value="Command Type" />
    </f:facet>
    <h:outputText value="#{com.commandType}"></h:outputText>
</rich:column>
<rich:column>
    <f:facet name="header">
        <h:outputText value="Parameters" />
    </f:facet>
    <h:outputText value="#{com.parameters}"></h:outputText>
</rich:column>
<rich:column>
    <h:commandButton value="Remove #{com.id} : #{com.seqNo}"
        action="#{commandBean.remove(com.id,com.seqNo)}" 
        onclick="alert('id:#{com.id} seqNo:#{com.seqNo}');"/>
</rich:column>

My troubles began when I tried to implement a remove button which would send a command's ID and seqNo to the backing bean (cb) to be removed from the list. Here is the backing bean:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class CommandBean implements Serializable{

private static final long serialVersionUID = 1L;

private CommandType type;
private String parameters;

private List<Command> newBatch = new ArrayList<Command>();

private Set<Command> commandSet = new HashSet<Command>();

private String msg = "not removed";

public CommandType[] getCommandTypes() {
    return CommandType.values();
}

public void addCommand(CommandType type, String parameters) {
    newBatch.add(new Command(type, parameters));
}

CommandType getType() {
    return type;
}

void setType(CommandType type) {
    this.type = type;
}

String getParameters() {
    return parameters;
}

void setParameters(String parameters) {
    this.parameters = parameters;
}

public List<Command> getNewBatch() {
    return newBatch;
}

public void setNewBatch(List<Command> newBatch) {
    this.newBatch = newBatch;
}

public Set<Command> getCommandSet() {
    return commandSet;
}

public void setCommandSet(Set<Command> commandSet) {
    this.commandSet = commandSet;
}

String getMsg() {
    return msg;
}

public void remove(Integer id, Integer seqNo) {
    for(Command c : newBatch) {
        if(c.getId() == id && c.getSeqNo() == seqNo) {
            newBatch.remove(c);
            msg = "removed " + c;
            return;
        }
    }
    msg = String.format("%d : %d", id,seqNo);
}
}

When the Command (com)'s id and seqNo are passed via #{cb.remove(com.id,com.seqNo)} they are both 0. I also read somewhere that null values are transformed to 0's, so that would explain it. I also tried to pass the Command object directly via #{cb.remove(com)} but the Command was null when bean tried to process it.

I'm betting there is something off with the scoping, but I am too new to JSF to figure it out...

UPDATE

I have eliminated the conflicting @Named tag and have updated the html to reflect the new name of the bean, namely commandBean. Still having issues though.


Solution

  • you can pass the two values as request parameters:

    <h:commandButton ... >
        <f:param name="id" value="#{com.id}"/>
        <f:param name="seqNo" value="#{com.seqNo}"/>
    </h:commandButton>
    

    and get retrieve them in managed bean like this:

    HttpServletRequest request = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest());
    System.out.println(request.getParameter("id"));
    System.out.println(request.getParameter("seqNo"));