Minha dúvida não está relacionada ao JSTL, mas sim a maneira que o a página está acessando essa variável produtoList. Só para deixar claro, não tenho vivência com VRaptor. No controller está sendo passado para a página a variável lista, como no trecho de código a seguir:
package br.com.caelum.produtos.controller;
...
@Resource
public class ProdutoController {
    ...
    public List<Produto> lista() {
        //Se quiser mudar o nome do atributo é só includar no result com o nome diferente
        result.include("lista", dao.lista());
        return dao.lista();
    }
    ...
}
Mas na página o que está sendo utilizado é a variável produtoList:
        <c:forEach items="${produtoList}" var="p" varStatus="status">
            <tr id="produto${p.id}>">
                <td>${status.count}</td>
                <td>${p.nome}</td>
                <td>${p.preco}</td>
                <td>${p.descricao}</td>
                <td>${p.dataInicioVenda.time}</td>
                <td><a href="#" onclick="return removeProduto(${p.id})">Remover</a></td>
            </tr>
        </c:forEach>
Como o VRaptor faz essa mágica?