2012-10-25 30 views
2

我正在试图为所示的类似于datatable的primefaces数据列表实现延迟加载模型。执行LazyModel for primefaces datalist时出现异常

我的初始代码与正常的AJAX分页功能非常好。然而,当我尝试使用延迟加载模式,我得到以下页面加载时除外:

com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException 
SEVERE: Error Rendering View[/pages/index.xhtml] 
java.io.NotSerializableException: java.util.ArrayList$SubList 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) 
    at java.util.HashMap.writeObject(HashMap.java:1100) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:975) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174) 
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1362) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1170) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) 
    at java.util.HashMap.writeObject(HashMap.java:1100) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:975) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) 
    at com.sun.faces.renderkit.ClientSideStateHelper.doWriteState(ClientSideStateHelper.java:325) 
    at com.sun.faces.renderkit.ClientSideStateHelper.writeState(ClientSideStateHelper.java:173) 
    at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122) 
    at com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:166) 
    at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225) 
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:418) 
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131) 
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:722) 

这里是代码的index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:p="http://primefaces.org/ui"> 

<ui:composition template="/pages/templates/template.xhtml"> 
    <ui:define name="content"> 

     <h:form prependId="false" id="form"> 
     <p:dataList value="#{movies.lazyMovieModel}" var="movie" id="movies" paginator="true" rows="10" 
      paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}" 
      type="none" paginatorAlwaysVisible="false" lazy="true"> 

      <h:outputText value="#{movie.movieName}, #{movie.releaseYear}" style="margin-left:10px"> 
      </h:outputText> 
      <br/> 
     </p:dataList> 
     </h:form> 

    </ui:define> 
</ui:composition> 
</html> 

MovieListBean.java

import org.primefaces.model.LazyDataModel; 

import com.clixflix.enitities.Movie; 
import com.clixflix.jsf.extensions.LazyMovieDataModel; 

@ManagedBean(name = "movies") 
@ViewScoped 
public class MovieListBean extends BaseBean implements Serializable 
{ 
    private static final long serialVersionUID = -5719443344065177588L; 

    private LazyDataModel<Movie> lazyMovieModel; 

    @PostConstruct 
    public void initialize() { 
     lazyMovieModel = new LazyMovieDataModel(); 
    } 

    public LazyDataModel<Movie> getLazyMovieModel() 
    { 
     List<Movie> movieList = getServiceLocator().getMovieService().getMovieList(); 
     ((LazyMovieDataModel) lazyMovieModel).setMovieList(movieList); 
     return lazyMovieModel; 
    } 
} 

LazyMovieDataModel.java(Laz yModel实现)

public class LazyMovieDataModel extends LazyDataModel<Movie> 
{ 
    private static final long serialVersionUID = 8745562148994455749L; 

    private List<Movie> movieList; 

    public LazyMovieDataModel() { 
     this.movieList = Collections.emptyList(); 
    } 

    @Override 
    public List<Movie> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) { 
     // Sorting 
     if (null != sortField) { 
     LazySorter sorter = new LazySorter(sortField, sortOrder); 
     Collections.sort(movieList, sorter); 
     sorter = null; 
     } 

     // RowCount 
     int rowCount = movieList.size(); 
     this.setRowCount(rowCount); 

     // Pagination 
     if (rowCount > pageSize) { 
     return movieList.subList(first, (first + pageSize)); 
     } 
     else { 
     return movieList; 
     } 
    } 


    private class LazySorter implements Comparator<Movie> 
    { 
     private String sortField; 

     private SortOrder sortOrder; 

     LazySorter(String sortField, SortOrder sortOrder) { 
     this.sortField = sortField; 
     this.sortOrder = sortOrder; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     public int compare(Movie movie1, Movie movie2) { 
     Object value1 = null, value2 = null; 

     try { 
      value1 = Movie.class.getField(this.sortField).get(movie1); 
      value2 = Movie.class.getField(this.sortField).get(movie2); 

      int value = ((Comparable<Object>) value1).compareTo(value2); 
      return SortOrder.ASCENDING.equals(sortOrder) ? value : -1 * value; 
     } 
     catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { 
      e.printStackTrace(); 
      return 0; 
     } 
     } 
    } 

    public void setMovieList(List<Movie> movieList) { 
     this.movieList = movieList; 
    } 
} 

,我假设的例外是在这样一行:

return movieList.subList(first, (first + pageSize)); 

能请人指导我,什么我思念?

而且,我观察到的日志,当我使用lazymodel,数据库查询得到三次,但是当我使用正常AJAX分页,数据库查询只有一次:|


更新:我想通了,要查询3次为DB的原因。这是因为我在LazyModel的getter中调用了我的服务,而不是仅在load方法中。

我做的类以下变化:

LazyMovieDataModel.java

public class LazyMovieDataModel extends LazyDataModel<Movie> 
{ 
    private static final long serialVersionUID = 8745562148994455749L; 

    public LazyMovieDataModel() {} 

    @Override 
    public List<Movie> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) { 

     List<Movie> movieList = getServiceLocator().getMovieService().getMovieList(first, (first + pageSize)); 

     // RowCount 
     int rowCount = ((Number)getServiceLocator().getMovieService().getMovieCount()).intValue(); 
     this.setRowCount(rowCount); 
    } 
} 

LazyModel吸气剂MovieListBean.java

/* Removed PostConstruct init method */ 

public LazyDataModel<Movie> getLazyMovieModel() 
{ 
    return lazyMovieModel; 
} 

上述变化罚款工作初始页面加载。但是,当我点击下一页按钮(或任何分页按钮)时,我在加载方法中得到了一个N​​PE getServiceLocator()

serviceLocator是一个protected访问修改的受管属性,该属性继承自BaseBean并使用Spring注入。

为什么getter在后续调用中返回null的任何原因???

+0

是'Movie'序列化? – kolossus

+0

@kolossus:是... – Vrushank

+0

作为一种解决方法,您应该能够通过将'javax.faces.STATE_SAVING_METHOD'设置为'SERVER'来排除异常。 – kolossus

回答

0

ArrayList $ SubList是一个问题。返回的子列表不能实现可序列化。
尝试使用:

return new ArrayList(movieList.subList(first, (first + pageSize))); 
+0

毕竟,整个设计是有缺陷的。 OP不应该在getter方法中执行业务逻辑,也不要使用'List#sublist()'并且永远不要将其作为'LazyDataModel'的实例变量。业务服务方法应该根据提供的参数立即返回请求的记录,否则整个延迟加载的想法是毫无意义的。 – BalusC

相关问题