Commit 7ec39503013e8dc400c0abe8bddd80e9eb455292
1 parent
ddf1a667
Exists in
master
Inclusão do capítulo de Paginação no Guia de Referencia do Demoiselle.
Showing
2 changed files
with
283 additions
and
174 deletions
Show diff stats
documentation/reference/pt-BR/master.xml
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 | <xi:include href="logger.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> |
42 | 42 | <xi:include href="templates.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> |
43 | 43 | <xi:include href="security.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> |
44 | - <!-- <xi:include href="paginacao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> --> | |
44 | + <xi:include href="paginacao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | |
45 | 45 | <xi:include href="properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> |
46 | 46 | </part> |
47 | 47 | <!-- parte 2 --> | ... | ... |
documentation/reference/pt-BR/paginacao.xml
... | ... | @@ -3,179 +3,288 @@ |
3 | 3 | "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []> |
4 | 4 | <chapter id="paginacao"> |
5 | 5 | |
6 | - <title>Paginação</title> | |
6 | + <title>Paginação</title> | |
7 | 7 | |
8 | - <para> | |
9 | - Neste capítulo serão considerados os seguintes assuntos: | |
10 | - <itemizedlist> | |
11 | - <listitem>motivação para o uso de um mecanismo padronizado para <emphasis>paginação</emphasis>;</listitem> | |
12 | - <listitem>funcionamento e uso da estrutura <literal>Pagination</literal> e do contexto de paginação (<literal>PaginationContext</literal>).</listitem> | |
13 | - </itemizedlist> | |
14 | - </para> | |
15 | - | |
16 | - <section> | |
17 | - <title>Introdução ao mecanismo</title> | |
18 | - <para> | |
19 | - A apresentação de conjuntos de registros de médio a grande porte em formato de tabelas em aplicações Web geralmente requer um | |
20 | - <emphasis>mecanismo de paginação</emphasis>, o qual permite ao cliente ver apenas um pedaço do resultado final, podendo este | |
21 | - navegar para frente e para trás através dos registros. A menos que o conjunto de registros seja garantidamente pequeno, qualquer | |
22 | - aplicação do tipo Web com funcionalidades de busca precisa ser dotada de paginação. | |
23 | - </para> | |
24 | - <para> | |
25 | - O mecanismo de paginação para as aplicações fornecido pelo <emphasis>Demoiselle Framework</emphasis> consiste em um algoritmo de | |
26 | - direcionado ao banco de dados (i.e., Database-Driven Pagination). Essa abordagem, apesar de requerer instruções SQL específicas | |
27 | - para obter porções determinadas de registros, é a mais utilizada por ser mais eficiente e produzir menos redundância dos dados. | |
28 | - </para> | |
29 | - <para> | |
30 | - É fornecido em tempo de execução um <emphasis>contexto de paginação</emphasis>, o qual tem escopo de sessão e armazena a informação | |
31 | - de paginação de cada entidade (i.e., bean) que necessite de tal mecanismo. Esse contexto é compartilhado entre as diversas camadas | |
32 | - da aplicação, especificamente entre as camadas de visão e persistência. Dessa maneira, a paginação dos dados é transparente para a | |
33 | - camada intermediária (i.e., negócio) e não interfere na modelagem das classes de um projeto. | |
34 | - </para> | |
35 | - </section> | |
36 | - | |
37 | - <section> | |
38 | - <title>Códigos de suporte</title> | |
39 | - <!-- | |
40 | - <para> | |
41 | - // TODO: explicar Pagination e PaginationContext | |
42 | - </para> | |
43 | - --> | |
44 | - <para> | |
45 | - Veremos na seção seguinte como implementar a paginação em uma aplicação Java. | |
46 | - | |
47 | - - Farão parte do código de suporte para paginação: | |
48 | - * a classe Pagination: usada para manipular a paginação dos dados resultantes, contendo os campos currentPage (página atual, selecionada na camada de visão), pageSize (tamanho da página, a quantidade de registros que ela comportará) e totalResults (a quantidade de resultados existentes na base de dados); | |
49 | - * a classe PaginationContext: contexto usado para armazenar e fornecer estruturas do tipo Pagination; | |
50 | - * a classe PaginationConfig: armazenador de configurações referentes à paginação. | |
51 | - | |
52 | -- Códigos internos de suporte no Core: | |
53 | - | |
54 | - <programlisting role="JAVA"><![CDATA[ | |
55 | - | |
56 | -public class Pagination { | |
57 | - | |
58 | - private int currentPage; | |
59 | - private int pageSize; | |
60 | - | |
61 | - private Long totalResults; | |
62 | - private Integer totalPages; | |
63 | - | |
64 | - // ... | |
65 | -} | |
66 | - | |
67 | -@SessionScoped | |
68 | -public class PaginationContext { | |
69 | - | |
70 | - private final Map<Class<?>, Pagination> map; | |
71 | - | |
72 | - public Pagination getPagination(Class<?> clazz) { ... } | |
73 | - | |
74 | - public Pagination get -->Pagination(Class<?> clazz, boolean create) { ... } | |
75 | - | |
76 | -} | |
77 | - | |
78 | -@Configuration | |
79 | -public class PaginationConfig { | |
80 | - | |
81 | - @Key("default_page_size") | |
82 | - private int defaultPageSize = 10; | |
83 | - | |
84 | - @Key("max_page_links") | |
85 | - private int maxPageLinks = 5; | |
86 | - | |
87 | -} | |
88 | - | |
89 | - - Códigos internos de suporte em JPA: | |
90 | - | |
91 | -public class JPACrud<T, I> implements Crud<T, I> { | |
92 | - | |
93 | - @Inject | |
94 | - private PaginationContext paginationContext; | |
95 | - | |
96 | - // ... | |
97 | - | |
98 | - public List<T> findAll() { | |
99 | - | |
100 | - final String jpql = "select this from " + getBeanClass().getSimpleName() + " this"; | |
101 | - final Query query = getEntityManager().createQuery(jpql); | |
102 | - | |
103 | - final Pagination pagination = paginationContext.getPagination(getBeanClass()); | |
104 | - if (pagination != null) { | |
105 | - if (pagination.getTotalPages() == null) { | |
106 | - pagination.setTotalResults(this.countAll()); | |
107 | - } | |
108 | - query.setFirstResult(pagination.getFirstResult()); | |
109 | - query.setMaxResults(pagination.getPageSize()); | |
110 | - } | |
111 | - | |
112 | - // ... | |
113 | - } | |
114 | - | |
115 | -} | |
116 | - | |
117 | - - Códigos internos de suporte em JSF: | |
118 | - | |
119 | -public abstract class AbstractListPageBean<T, I> extends AbstractPage implements ListPageBean<T, I> { | |
120 | - | |
121 | - @Inject | |
122 | - private PaginationContext paginationContext; | |
123 | - | |
124 | - @Inject | |
125 | - private PaginationConfig paginationConfig; | |
126 | - | |
127 | - // ... | |
128 | - | |
129 | - public Pagination getPagination() { | |
130 | - return paginationContext.getPagination(getBeanClass(), true); | |
131 | - } | |
132 | - | |
133 | - public int getPageSize() { | |
134 | - return paginationConfig.getDefaultPageSize(); | |
135 | - } | |
136 | - | |
137 | - public int getMaxPageLinks() { | |
138 | - return paginationConfig.getMaxPageLinks(); | |
139 | - } | |
140 | - | |
141 | -} | |
142 | - | |
143 | -frameworkdemoiselle.pagination.default_page_size=50 | |
144 | -frameworkdemoiselle.pagination.max_page_links=10 | |
145 | - | |
146 | -]]></programlisting> | |
147 | - </para> | |
148 | - </section> | |
8 | + <para> | |
9 | + Neste capítulo serão considerados os seguintes assuntos: | |
10 | + <itemizedlist> | |
11 | + <listitem><para>Motivação para o uso de um mecanismo padronizado para <emphasis>paginação</emphasis>;</para></listitem> | |
12 | + <listitem><para>Funcionamento e uso da estrutura <literal>Pagination</literal> e do contexto de paginação | |
13 | + (<literal>PaginationContext</literal>).</para></listitem> | |
14 | + </itemizedlist> | |
15 | + </para> | |
16 | + | |
17 | + <section> | |
18 | + <title>Introdução ao mecanismo</title> | |
19 | + <para> | |
20 | + A apresentação de conjuntos de registros de médio a grande porte em formato de tabelas em aplicações Web geralmente requer um | |
21 | + <emphasis>mecanismo de paginação</emphasis>, o qual permite ao cliente ver apenas um pedaço do resultado final, podendo este | |
22 | + navegar para frente e para trás através dos registros. A menos que o conjunto de registros seja garantidamente pequeno, qualquer | |
23 | + aplicação do tipo Web com funcionalidades de busca precisa ser dotada de paginação. | |
24 | + </para> | |
25 | + <para> | |
26 | + O mecanismo de paginação para as aplicações fornecido pelo <emphasis>Demoiselle Framework</emphasis> consiste em um algoritmo | |
27 | + direcionado ao banco de dados (i.e., Database-Driven Pagination). Essa abordagem, apesar de requerer instruções SQL específicas | |
28 | + para obter porções determinadas de registros, é a mais utilizada por ser mais eficiente e produzir menos redundância de dados, | |
29 | + diminuindo assim tráfego de rede, consumo de memória e reduzindo o tempo de resposta. | |
30 | + </para> | |
31 | + <para> | |
32 | + É fornecido em tempo de execução um <emphasis>contexto de paginação</emphasis>, o qual tem escopo de sessão e armazena a informação | |
33 | + de paginação de cada entidade (i.e., bean) que necessite de tal mecanismo. Esse contexto é compartilhado entre as diversas camadas | |
34 | + da aplicação, especificamente entre as camadas de visão e persistência. Dessa maneira, a paginação dos dados é transparente para a | |
35 | + camada intermediária (i.e., negócio) e não interfere na modelagem das classes de um projeto. | |
36 | + </para> | |
37 | + </section> | |
38 | + | |
39 | + <section> | |
40 | + <title>Códigos de suporte</title> | |
41 | + <!-- | |
42 | + <para> | |
43 | + // TODO: explicar Pagination e PaginationContext | |
44 | + </para> | |
45 | + --> | |
46 | + <para> | |
47 | + O <emphasis>mecanismo de paginação</emphasis> do <emphasis>Demoiselle Framework</emphasis> permite que os parâmetros para a consulta | |
48 | + no banco sejam configurados de forma bastante prática. Por outro lado, a consulta paginada ao banco já é feita pela extensão | |
49 | + <literal>demoiselle-jpa</literal>. Dessa forma, basta ajustar os parametros da paginação, e pedir as consultas normalmente. | |
50 | + O resultado da consulta é então passado para algum componente de iteração de dados com suporte ao mecanismo conhecido como <emphasis>Lazy | |
51 | + Load</emphasis> (ou <emphasis>Lazy Loading</emphasis>). | |
52 | + </para> | |
53 | + <para> | |
54 | + Farão parte do código de suporte para paginação: | |
55 | + <itemizedlist> | |
56 | + <listitem> | |
57 | + <para> | |
58 | + A classe <literal>Pagination</literal>: usada para manipular a paginação dos dados resultantes, contendo os campos <literal>currentPage</literal> | |
59 | + (página atual, selecionada na camada de visão), <literal>pageSize</literal> (tamanho da página, a quantidade de registros que ela comportará) | |
60 | + e <literal>totalResults</literal> (a quantidade de resultados existentes na base de dados); | |
61 | + </para> | |
62 | + </listitem> | |
63 | + <listitem> | |
64 | + <para> | |
65 | + A classe <literal>PaginationContext</literal>: contexto usado para armazenar e fornecer estruturas do tipo <literal>Pagination</literal>; | |
66 | + </para> | |
67 | + </listitem> | |
68 | + <listitem> | |
69 | + <para> | |
70 | + A classe <literal>PaginationConfig</literal>: armazenador de configurações referentes à paginação. | |
71 | + </para> | |
72 | + </listitem> | |
73 | + </itemizedlist> | |
74 | + </para> | |
75 | + | |
76 | + <para>Códigos internos de suporte no Core:</para> | |
77 | + | |
78 | + <programlisting role="JAVA"><![CDATA[ | |
79 | + public class Pagination { | |
80 | + | |
81 | + private int currentPage; | |
82 | + private int pageSize; | |
83 | + | |
84 | + private Long totalResults; | |
85 | + private Integer totalPages; | |
86 | + | |
87 | + // ... | |
88 | + } | |
89 | + | |
90 | + @SessionScoped | |
91 | + public class PaginationContext { | |
92 | + | |
93 | + private final Map<Class<?>, Pagination> map; | |
94 | + | |
95 | + public Pagination getPagination(Class<?> clazz) { ... } | |
96 | + | |
97 | + public Pagination get -->Pagination(Class<?> clazz, boolean create) { ... } | |
98 | + | |
99 | + } | |
100 | + | |
101 | + @Configuration | |
102 | + public class PaginationConfig { | |
103 | + | |
104 | + @Key("default_page_size") | |
105 | + private int defaultPageSize = 10; | |
106 | + | |
107 | + @Key("max_page_links") | |
108 | + private int maxPageLinks = 5; | |
109 | + | |
110 | + } | |
111 | + ]]></programlisting> | |
112 | + | |
113 | + <para>Códigos internos de suporte em JPA:</para> | |
114 | + | |
115 | + <programlisting role="JAVA"><![CDATA[ | |
116 | + public class JPACrud<T, I> implements Crud<T, I> { | |
117 | + | |
118 | + @Inject | |
119 | + private PaginationContext paginationContext; | |
120 | + | |
121 | + // ... | |
122 | + | |
123 | + public List<T> findAll() { | |
124 | + | |
125 | + final String jpql = "select this from " + getBeanClass().getSimpleName() + " this"; | |
126 | + final Query query = getEntityManager().createQuery(jpql); | |
127 | + | |
128 | + final Pagination pagination = paginationContext.getPagination(getBeanClass()); | |
129 | + if (pagination != null) { | |
130 | + if (pagination.getTotalPages() == null) { | |
131 | + pagination.setTotalResults(this.countAll()); | |
132 | + } | |
133 | + query.setFirstResult(pagination.getFirstResult()); | |
134 | + query.setMaxResults(pagination.getPageSize()); | |
135 | + } | |
136 | + | |
137 | + // ... | |
138 | + } | |
139 | + | |
140 | + } | |
141 | + ]]></programlisting> | |
142 | + | |
143 | + <para>Códigos internos de suporte em JSF:</para> | |
144 | + | |
145 | + <programlisting role="JAVA"><![CDATA[ | |
146 | + public abstract class AbstractListPageBean<T, I> extends AbstractPage | |
147 | + implements ListPageBean<T, I> { | |
148 | + | |
149 | + @Inject | |
150 | + private PaginationContext paginationContext; | |
151 | + | |
152 | + @Inject | |
153 | + private PaginationConfig paginationConfig; | |
154 | + | |
155 | + // ... | |
156 | + | |
157 | + public Pagination getPagination() { | |
158 | + return paginationContext.getPagination(getBeanClass(), true); | |
159 | + } | |
160 | + | |
161 | + public int getPageSize() { | |
162 | + return paginationConfig.getDefaultPageSize(); | |
163 | + } | |
164 | + | |
165 | + public int getMaxPageLinks() { | |
166 | + return paginationConfig.getMaxPageLinks(); | |
167 | + } | |
168 | + | |
169 | + } | |
170 | + ]]></programlisting> | |
171 | + </section> | |
149 | 172 | |
150 | - <section> | |
151 | - <title>Implementação na aplicação</title> | |
152 | - <para> | |
153 | - Eis um exemplo de implementação de paginação em uma aplicação: | |
154 | - </para> | |
155 | - <programlisting role="JAVA"><![CDATA[ | |
156 | - @Inject | |
157 | - private PaginationContext paginationContext; | |
158 | -]]></programlisting> | |
159 | - <programlisting role="JAVA"><![CDATA[ | |
160 | - Pagination pagination = paginationContext.getPagination(Audit.class); | |
161 | -]]></programlisting> | |
162 | - <tip> | |
163 | - <para> | |
164 | - O método <literal>getPagination()</literal> do contexto <literal>PaginationContext</literal> é sobrecarregado, podendo aceitar | |
165 | - os seguintes argumentos: <literal>Class</literal> ou <literal>Class</literal> e <literal>boolean</literal>. | |
166 | - </para> | |
167 | - </tip> | |
168 | - <note> | |
169 | - <para> | |
170 | - A JPA 2.0, através da Query API, suporta controle de paginação independente de fornecedor de banco de dados. | |
171 | - Para controlar a paginação, a interface <literal>Query</literal> define os métodos <literal>setFirstResult()</literal> e | |
172 | - <literal>setMaxResults()</literal> para especificar o primeiro resultado a ser recebido e o número máximo de resultados a | |
173 | - serem retornados em relação àquele ponto. Internamente, são usadas instruções específicas do SGBD (ex: LIMIT e OFFSET no | |
174 | - PostgreSQL). | |
175 | - </para> | |
176 | - </note> | |
173 | + <section> | |
174 | + <title>Implementação na aplicação</title> | |
175 | + <para> | |
176 | + Veremos nessa seção como implementar a paginação em uma aplicação Java. Para esse exmplo tomamos como base a aplicação de Bookmarks | |
177 | + fornecida pelo arquétipo <emphasis>JSF com JPA</emphasis> do <emphasis>Demoiselle Framework</emphasis> (para maiores detalhes | |
178 | + ver <link linkend="estrutura">Arquétipos</link>). Iremos utilizar o componente <literal>DataTable</literal> do <emphasis>PrimeFaces</emphasis>, | |
179 | + que oferece o mecanismo de <emphasis>Lazy Loading</emphasis> conhecido como <literal>LazyDataModel</literal>, muito útil para paginação | |
180 | + e classificação de dados. | |
181 | + </para> | |
182 | + <para> | |
183 | + Primeiro é preciso configurar um objeto <literal>LazyDataModel</literal> no construtor do <emphasis>Managed Bean</emphasis> | |
184 | + (<emphasis>BookmarkList</emphasis> nesse exemplo): instancia-lo e sobrescrever o método abstrado <literal>load</literal>, que recebe | |
185 | + vários argumentos. Esses argumentos são recuperados na página <literal>jsf</literal> que carrega a instância do objeto <literal>LazyDataModel</literal>. | |
186 | + </para> | |
187 | + <para> | |
188 | + Dentro do método <literal>load</literal> iremos pegar do contexto de paginação uma instância da implementação da interface <literal>Pagination</literal> | |
189 | + e ajustar alguns dos seus parâmetros para: indicar a partir de qual item a paginação deve iniciar, e o tamanho (quantidade de itens) de cada página. | |
190 | + Esses dados são usados no método <literal>findAll()</literal>, da classe <literal>JPACrud</literal> (extensão JPA), que utiliza o contexto de | |
191 | + paginação para pegar os parametros e fazer a consulta no banco buscando apenas os itens que estão dentro da pagina que o parametro | |
192 | + <literal>first</literal> indicar. O resultado é passado para a instancia do <literal>LazyDataModel</literal>, que é responsável por exibir | |
193 | + os dados de forma apropriada. | |
194 | + </para> | |
195 | + <para> | |
196 | + À classe <emphasis>BookmarkList</emphasis> devem ser adicionados os seguintes trechos de código: | |
197 | + </para> | |
198 | + | |
199 | + <programlisting role="JAVA"><![CDATA[ | |
200 | + // ... | |
201 | + import java.util.Map; | |
202 | + import br.gov.frameworkdemoiselle.pagination.Pagination; | |
203 | + | |
204 | + // ... | |
205 | + private LazyDataModel<Bookmark> lazyModel; | |
206 | + | |
207 | + public BookmarkListMB() { | |
208 | + lazyModel = new LazyDataModel<Bookmark>() { | |
209 | + | |
210 | + @Override | |
211 | + public List<Bookmark> load (int first, int pageSize, String sortField, | |
212 | + SortOrder sortOrder, Map<String, String> filters){ | |
213 | + | |
214 | + Pagination pagination = getPagination(); | |
215 | + pagination.setPageSize(pageSize); | |
216 | + pagination.setFirstResult(first); | |
217 | + | |
218 | + List<Bookmark> itemsList = bc.findAll(); | |
219 | + | |
220 | + lazyModel.setRowCount(pagination.getTotalResults()); | |
221 | + | |
222 | + return itemsList; | |
223 | + } | |
224 | + }; | |
225 | + } | |
226 | + | |
227 | + // ... | |
228 | + | |
229 | + public LazyDataModel<Bookmark> getLazyModel() { | |
230 | + return lazyModel; | |
231 | + } | |
232 | + | |
233 | + // ... | |
234 | + ]]></programlisting> | |
235 | + | |
236 | + <para> | |
237 | + No arquivo <literal>messages.properties</literal> adicione as linhas: | |
238 | + </para> | |
239 | + | |
240 | + <programlisting role="JAVA"><![CDATA[ | |
241 | + page.first=0 | |
242 | + page.rows=4 | |
243 | + page.max.links=3 | |
244 | + ]]></programlisting> | |
245 | + | |
246 | + <para> | |
247 | + Na página JSF <literal>bookmark_list.xhtml</literal>, substitua a linha: | |
248 | + </para> | |
249 | + | |
250 | + <programlisting role="JAVA"><![CDATA[ | |
251 | + <p:dataTable id="list" var="bean" value="#{bookmarkListMB.resultList}"> | |
252 | + ]]></programlisting> | |
253 | + | |
254 | + <para> | |
255 | + por: | |
256 | + </para> | |
257 | + | |
258 | + <programlisting role="JAVA"><![CDATA[ | |
259 | + <p:dataTable id="list" var="bean" | |
260 | + value="#{bookmarkListMB.lazyModel}" lazy="true" paginator="true" | |
261 | + first="#{messages['page.first']}" rows="#{messages['page.rows']}" | |
262 | + pageLinks="#{messages['page.max.links']}"> | |
263 | + ]]></programlisting> | |
264 | + | |
265 | + <para> | |
266 | + Com essas alterações simples, a aplicação Bookmarks passa a utilizar o mecanismo de paginação oferecido pelo <emphasis>Demoiselle Framework</emphasis>. | |
267 | + </para> | |
268 | + | |
269 | + <tip> | |
270 | + <para> | |
271 | + O método <literal>getPagination()</literal> do contexto <literal>PaginationContext</literal> é sobrecarregado, podendo aceitar | |
272 | + os seguintes argumentos: <literal>Class</literal> ou <literal>Class</literal> e <literal>boolean</literal>. | |
273 | + </para> | |
274 | + </tip> | |
275 | + <note> | |
276 | + <para> | |
277 | + A JPA 2.0, através da Query API, suporta controle de paginação independente de fornecedor de banco de dados. | |
278 | + Para controlar a paginação, a interface <literal>Query</literal> define os métodos <literal>setFirstResult()</literal> e | |
279 | + <literal>setMaxResults()</literal> para especificar o primeiro resultado a ser recebido e o número máximo de resultados a | |
280 | + serem retornados em relação àquele ponto. Internamente, são usadas instruções específicas do SGBD (ex: LIMIT e OFFSET no | |
281 | + PostgreSQL). | |
282 | + </para> | |
283 | + </note> | |
177 | 284 | </section> |
178 | 285 | |
286 | +</chapter> | |
287 | + | |
179 | 288 | <!--<section> |
180 | 289 | <title>Um exemplo usando PrimeFaces</title> |
181 | 290 | <para> |
... | ... | @@ -238,7 +347,7 @@ public class AuditMB extends AbstractListPageBean<Audit, Long> { |
238 | 347 | rows="#{auditMB.pageSize}" pageLinks="#{auditMB.maxPageLinks}">]]></programlisting> |
239 | 348 | </section> |
240 | 349 | --> |
241 | - | |
350 | +<!-- | |
242 | 351 | <section> |
243 | 352 | <title>Referências</title> |
244 | 353 | <itemizedlist> |
... | ... | @@ -246,8 +355,8 @@ public class AuditMB extends AbstractListPageBean<Audit, Long> { |
246 | 355 | <listitem>Implementing Search Result Pagination in a Web Application (http://www.developer.com/java/other/article.php/3696226/)</listitem> |
247 | 356 | <listitem>A Pagination Technique Using Spring (http://www.developer.com/java/web/article.php/10935_3830886_1/)</listitem> |
248 | 357 | <listitem>Spring JDBC Pagination Tutorial (http://www.codefutures.com/tutorials/spring-pagination/)</listitem> |
249 | - <!-- <listitem>PrimeFaces DataTable - Lazy Loading (http://www.primefaces.org/showcase/ui/datatableLazy.jsf)</listitem> --> | |
358 | + <listitem>PrimeFaces DataTable - Lazy Loading (http://www.primefaces.org/showcase/ui/datatableLazy.jsf)</listitem> | |
250 | 359 | </itemizedlist> |
251 | 360 | </section> |
252 | - | |
253 | -</chapter> | |
361 | + --> | |
362 | + | ... | ... |