Salih Erikci
Salih Erikci

Reputation: 5087

Binding JSF inputText to a HashMap doesn't work

I am trying to bind multiple inputText fields to a HashMap<Integer, String>. But it doesn't put any value into the HashMap.

Here is the JSF page.

<ui:repeat  value="#{questionBean.question.answerCollection}" var="answer">                
    <h:inputText  value="#{questionBean.newComments[answer.answerId]}"></h:inputText>
    <br/>
    <h:commandButton value="Add Comment">
                    <f:ajax event="click" listener="#{questionBean.makeComment(answer)}"></f:ajax>
    </h:commandButton>
</ui:repeat>

Here is related part of the backing bean.

private Map<Integer, String> newComments = new HashMap<Integer, String>();
...

public void makeComment(Answers answer) throws Exception {
    String username = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();

    Users user = userFacade.getUserByUsername(username);

    Comments comment = new Comments();

    for(Integer key: newComments.keySet()){
        throw new Exception("Answer ID IS :"+key);
        // It doesn't throw any exception in here.
        // The map is empty.
    }        

    String commentContent = newComments.get(answer.getAnswerId());
    if(commentContent == null){
        throw new Exception("Content Is NULL");
        // It throws exception here.
    }

    comment.setCommentContent(newComments.get(answer.getAnswerId()));
    comment.setDateCreated(new java.sql.Date(Calendar.getInstance().getTimeInMillis()));
    comment.setAnswerId(answer);
    comment.setUserId(user);
    commentFacade.create(comment);
}

What may be wrong in this code?

Upvotes: 0

Views: 1668

Answers (1)

BalusC
BalusC

Reputation: 1108642

The main mistake is that the <f:ajax> isn't being told to process the input field as well. Its execute event defaults to @this, which means "the current component". Thus with this construct, only the <h:commandButton> would be processed (i.e. its action would be decoded, queued and invoked).

So, fix it accordingly by explicitly telling it to process the entire form:

<f:ajax execute="@form" ... />

The next (potential) mistake is EL implementation dependent, but as of now all of them doesn't support generics. A Map<K, V> would simply be seen as Map without any implicit/automatic conversion of keys and values. In EL, numeric values are implicitly interpreted as Long. In your particular case, the Map would be filled with Long keys instead of Integer keys, potentially causing ClassCastException while iterating over it. If you fix the model accordingly to use Long instead of Integer, then this problem should be solved as well.

private Map newComments = new HashMap();


Unrelated to the concrete problem, using java.sql.* models in frontend side is a terribly bad idea. Use it in database side instead.

Upvotes: 2

Related Questions