Many data-iteration components are out there, and so many of them are pretty advanced, but in some cases you would just need the pure and clear <table> with its known <tr> and <td>.

You can achieve that with many ways in JSF, in this post I wrote it using <a4j:repeat>.

Your table will look like the next:

    <table id="records">
        <th>
            <h:outputText value="First Column Header" />
        </th>
        <th>
            <h:outputText value="Second Column Header" />
        </th>
        <a4j:repeat id="recordsRepeat" value="#{DataCountryBean.list}" var="record" >
            <tr>
                <td>
                    <h:outputText value="#{record.value1}" />
                </td>
                <td>
                    <h:outputText value="#{record.value2}" />
                </td>
            </tr>
        </a4j:repeat>
    </table>

This is the most simple table, many improvements can be added.

- The zebra-records effect can be done by modifying the <tr> inside <a4j:repeat>:

<a4j:repeat id="recordsRepeat" value="#{BackingBean.list}" var="record" rowKeyVar="index">
    <tr class="#{(index % 2 == 0) ? 'odd_row' : 'even_row'}">
    ....

Of course you should have two classes in your CSS style file for the Odd rows and even rows as I coded up with 'odd_row' and 'even_row' respectively.

- “No Data” sentence when the list is empty or null:

</th>
    <a4j:outputPanel rendered="#{empty BackingBean.list}" layout="none">
        <tr>
            <td colspan="2" align="center">
                <h:outputText value="No Data Found" />
            </td>
        </tr>
    </a4j:outputPanel>
    <a4j:repeat id="recordsRepeat" value="#{BackingBean.list}" var="record" rowKeyVar="index" rendered="#{not empty BackingBean.list}">
         <tr class="#{(index % 2 == 0) ? 'odd_row' : 'even_row'}">
             <td>
                .....

The layout="none" is required here.

- When you want to apply changes on the <table> records, reRendering the <a4j:repeat id="recordsRepeat"> will do nothing.
To achieve that add an <a4j:outputPanel> around your <table> and reRender that panel.

<a4j:outputPanel id="recordsTable">
    <table id="records">
        <th>
            ....

- Finally to add pagination to your records, you can use <rich:datascroller>:
First you add the rows attribute to your <a4j:repeat> which takes an integer value

<a4j:repeat id="recordsRepeat" value="#{BackingBean.list}" var="record" rows="10" rowKeyVar="index">
....

then

<a4j:outputPanel id="recordsScroller">
    <rich:datascroller for="recordsRepeat" renderIfSinglePage="false" reRender="recordsTable" />
<a4j:outputPanel>

Notice you reRender the recordsTable.
Also make sure you always reRender the scroll-er when reRendering the recordsTable, because your records count can change, and so you wouldn’t want your scroll-er to give false pages count, and to make that reRendering successful I added the <a4j:outputPanel> around <rich:datascroller>.

This tutorial was tested using JSF 1.2, Richfaces 3.3.3