I try to use Richfaces DataTable with DataTableModel to have server side paging and sorting.
My tebaleModel is a spring bean with scope "request" and " proxyMode = ScopedProxyMode.TARGET_CLASS".
On the page is a keepAlive tag for tebaleModel bean.
When I click next the bean is initialized but it should be restored.
Can anybody help. I can provide the code if my question is not clear.
Update:
- My bean impelements Serializable, because SerializableDataModel which I extend implements Serializable
- is within a form
In another managedBean I have type if bean proxy and keepAlive works just fine. I don't use this for DataTableModel becasue it doesnt't work with this pattern.
Maybe if you see the code you notice what I done wrong.
Here is my code
ManagedBean:
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserTableDataModel extends SerializableDataModel implements Modifiable {
/**
*
*/
private static final long serialVersionUID = -4188575485838003516L;
@Autowired
private UserManager userManager;
private Long currentPk;
private Map<Long, User> wrappedData;
private List<Long> wrappedKeys;
private int pageSize;
private int pageNo;
private int pages;
private SortInfo sortInfo;
private List<SelectItem> pagesList;
@PostConstruct
public void init() {
wrappedKeys = null;
wrappedData = new HashMap<Long, User>();
pageSize = 1;
pageNo = 1;
pages = userManager.getUserCount() / pageSize;
pagesList = new ArrayList<SelectItem>();
for (int i = 1; i < pages + 1; i++) {
pagesList.add(new SelectItem(i));
}
}
@PreDestroy
public void clen(){
System.out.println("ddd");
}
/**
* Getter for pagesList.
*
* @return the pagesList
*/
public List<SelectItem> getPagesList() {
return pagesList;
}
@Override
public void update() {
}
@Override
public Object getRowKey() {
return this.currentPk;
}
@Override
public void setRowKey(Object key) {
this.currentPk = (Long) key;
}
@Override
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
int firstRow = ((SequenceRange) range).getFirstRow();
int numberOfRows = ((SequenceRange) range).getRows();
int pageNumber = firstRow / pageSize;
setPageNo(pageNumber + 1);
wrappedKeys = new ArrayList<Long>();
for (User item : userManager.getUsers(new PresentationInfo(new PageInfo(pageSize, pageNumber), sortInfo))) {
wrappedKeys.add(item.getId());
wrappedData.put(item.getId(), item);
visitor.process(context, item.getId(), argument);
}
}
@Override
public int getRowCount() {
return userManager.getUserCount();
}
@Override
public User getRowData() {
if (currentPk == null) {
return null;
} else {
User ret = wrappedData.get(currentPk);
if (ret == null) {
try {
ret = userManager.getUser(currentPk);
} catch (UserManagerBusinessException e) {
e.printStackTrace();
} catch (ValidationException e) {
e.printStackTrace();
}
wrappedData.put(currentPk, ret);
return ret;
} else {
return ret;
}
}
}
@Override
public int getRowIndex() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getWrappedData() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isRowAvailable() {
// TODO Auto-generated method stub
return true;
}
@Override
public void setRowIndex(int rowIndex) {
// TODO Auto-generated method stub
}
@Override
public void setWrappedData(Object data) {
// TODO Auto-generated method stub
}
public SerializableDataModel getSerializableModel(Range range) {
SerializableDataModel model = null;
if (wrappedKeys != null) {
model = this;
}
return model;
}
/**
* Getter for pageSize.
*
* @return the pageSize
*/
public int getPageSize() {
return pageSize;
}
/**
* Setter for pageSize.
*
* @param pageSize the pageSize to set
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
/**
* Getter for pageNo.
*
* @return the pageNo
*/
public int getPageNo() {
return pageNo;
}
/**
* Setter for pageNo.
*
* @param pageNo the pag开发者_JS百科eNo to set
*/
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
/**
* Getter for pages.
*
* @return the pages
*/
public int getPages() {
return pages;
}
@Override
public void modify(List<FilterField> filterFields, List<SortField2> sortFields) {
if (sortFields != null && !sortFields.isEmpty()) {
sortInfo = new SortInfo();
for (SortField2 sf : sortFields) {
Ordering order = sf.getOrdering();
String exp = sf.getExpression().getExpressionString();
String fieldName = exp.substring(exp.indexOf('.') + 1, exp.indexOf('}'));
if (Ordering.ASCENDING.equals(order)) {
sortInfo.addSortFieldAscending(fieldName);
} else {
sortInfo.addSortFieldDescending(fieldName);
}
}
}
}
}
web page userTable.xhtml:
<ui:composition 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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="/templates/mainTemplate.xhtml">
<ui:param name="bean" value="${userTableDataModel}" />
<ui:define name="mainPage">
<h:form id="${commonBean.mainFormName}">
<a4j:keepAlive beanName="userTableDataModel" />
<h:panelGrid columns="1" columnClasses="top , top">
<rich:dataTable id="table" value="#{bean}" var="user" width="580px"
rows="#{bean.pageSize}" sortMode="multi" selectionMode="single">
<f:facet name="header">
<h:outputText value="${userMsg.users}" />
</f:facet>
<rich:column sortable="true" label="${userMsg.firstName}"
sortBy="#{user.firstName}">
<f:facet name="header">
<h:outputText value="${userMsg.firstName}" />
</f:facet>
<h:outputText value="#{user.firstName}" />
</rich:column>
<rich:column label="${userMsg.lastName}" sortable="true"
sortBy="#{user.lastName}">
<f:facet name="header">
<h:outputText value="${userMsg.lastName}" />
</f:facet>
<h:outputText value="#{user.lastName}" />
</rich:column>
<rich:column sortable="true" sortBy="#{user.login}"
label="${userMsg.login}">
<f:facet name="header">
<h:outputText value="${userMsg.login}" />
</f:facet>
<h:outputText value="#{user.login}" />
</rich:column>
<f:facet name="footer">
<rich:datascroller maxPages="#{bean.pages}" fastControls="hide"
page="#{bean.pageNo}" pagesVar="pages" id="ds">
<f:facet name="first">
<h:outputText value="First" styleClass="scrollerCell" />
</f:facet>
<f:facet name="first_disabled">
<h:outputText value="First" styleClass="scrollerCell" />
</f:facet>
<f:facet name="last">
<h:outputText value="Last" styleClass="scrollerCell" />
</f:facet>
<f:facet name="last_disabled">
<h:outputText value="Last" styleClass="scrollerCell" />
</f:facet>
<f:facet name="previous">
<h:outputText value="Previous" styleClass="scrollerCell" />
</f:facet>
<f:facet name="previous_disabled">
<h:outputText value="Previous" styleClass="scrollerCell" />
</f:facet>
<f:facet name="next">
<h:outputText value="Next" styleClass="scrollerCell" />
</f:facet>
<f:facet name="next_disabled">
<h:outputText value="Next" styleClass="scrollerCell" />
</f:facet>
<f:facet name="pages">
<h:panelGroup>
<h:outputText value="Page " />
<h:selectOneMenu value="#{bean.pageNo}"
onchange="#{rich:component('ds')}.switchToPage(this.value)">
<f:selectItems value="#{bean.pagesList}" />
</h:selectOneMenu>
<h:outputText value=" of #{pages}" />
</h:panelGroup>
</f:facet>
</rich:datascroller>
</f:facet>
</rich:dataTable>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
- Your bean has to implement
Serializable
- the
<a4j:keepAlive>
should be within a form - Try adding
<f:view>
around - As a sidenote, you'd better make all your spring dependencies (the classes injected into the managed bean)
transient
, and then restore them from the spring context inreadResolve
. Serializing the whole hierarchy of injected beans, potentially with proxies might be cumbersome.
The work around is to do the interface which is implemented by the model and provided a method to return model itselft. Then everything is working fine.
精彩评论