Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magic ui:repeat var

I have stumbled upon an, at least for me, unexpected behaviour. When using an ui:repeat, it seems I can access the var from outside.

Code - Page:

<f:metadata>
   <f:event type="preRenderView" listener="#{xTest.init()}" />
</f:metadata>

<h:form id="xTestForm">
   <h:panelGroup layout="block">
      Track: #{trk.name}
   </h:panelGroup>

   <table>
      <ui:repeat
         value="#{xTest.trackList}"
         var="trk">
         <tr>
            <td>#{trk.name}</td>
            <td>
               <p:commandLink
                  actionListener="#{xTest.setTrack(track)}"
                  value="test"
                  update=":xTestForm" />
            </td>
         </tr>
      </ui:repeat>
   </table>
</h:form>

Code - Bean

package beans;

import dao.DAOFactory;
import dao.track.TrackDAO;
import dto.Track;
import exceptions.DAOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import util.MessageUtil;

@ManagedBean
@ViewScoped
public class xTest implements Serializable {

    private DAOFactory daoFactory = Config.getInstance().getDAOFactory();
    private TrackDAO trackDAO;
    private Track track = new Track();
    private MessageUtil msg = new MessageUtil();
    private List<Track> trackList = new ArrayList();

    public xTest() {
        trackDAO = daoFactory.getTrackDAO(true);
    }

    public void init() {
        if (!FacesContext.getCurrentInstance().isPostback()) {
            try {
                trackList = trackDAO.listByAlbumid(241);
            } catch (SQLException | DAOException ex) {
                msg.setErrorMessage(ex);
            }
        }
    }

    public List<Track> getTrackList() {
        return trackList;
    }

    public void setTrack(Track track) {
        this.track = track;
    }
}

If I click a link in the list of tracks, the track name will be displayed in the panelGroup. How is this possible?

like image 964
nivis Avatar asked Feb 17 '23 19:02

nivis


2 Answers

This is a bug in Mojarra. Its UIRepeat component forgets to remove the iteration variable from the request scope by end of iteration during restore view phase. It doesn't work that way in for example MyFaces.

You shouldn't rely your business code on it. Note that <h:dataTable> doesn't have this problem, it properly removes the iteration variable from the request scope by end of iteration by ((UIData) component).setRowIndex(-1) in encodeEnd() method.

like image 96
BalusC Avatar answered Feb 27 '23 13:02

BalusC


8 years later someone reported this to PrimeFaces so I opened a Mojarra issue and a PR to fix the issue.

Mojarra Issue: https://github.com/eclipse-ee4j/mojarra/issues/4830

Mojarra PR: https://github.com/eclipse-ee4j/mojarra/pull/4831

like image 29
Melloware Avatar answered Feb 27 '23 13:02

Melloware