views:

40

answers:

2

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:

  1. My bean impelements Serializable, because SerializableDataModel which I extend implements Serializable
  2. 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 pageNo 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>
+2  A: 
  1. Your bean has to implement Serializable
  2. the <a4j:keepAlive> should be within a form
  3. Try adding <f:view> around
  4. 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 in readResolve. Serializing the whole hierarchy of injected beans, potentially with proxies might be cumbersome.
Bozho
I posted a code below.
Wojciech
@Wojciech see my update (p.3)
Bozho
As I sad before:p1 - SerializableDataModel implements Serializable and I extend it so my class implements Serializable top2 - it is in formp3 - doesn't change any thingp4 - no needI thing the problem is with bean proxy mode proxyMode = ScopedProxyMode.TARGET_CLASS.But I need this type for table model. Any suggestions?
Wojciech
Tried removing the proxy mode?
Bozho
yes. but then is another problem, because exprexion "bean.user" is not resolved on class Proxy49. Thats why I use proxy mode target class to have the orginal class.I use keep alive and bean without proxy mode for another web page anf it's working fine.But for this page I need with proxy mode = taget_class. Have you tried to do such thing?
Wojciech
I have used a lot spring+jsf, with proxied controllers (by myfaces orchestra) with no troubles, and keepAlive as well, so I'm trying to see something that's wrong, but apart from the above points, I cant't
Bozho
the problem is with tablemodel. For "normla" beans it's ok. But table model need to exdent SerializableTableModel or ExtendedTableModel. I use it for server side sorting and paging. When there is proxy richfaces mechanizm doesn't see that my class is of type SerializableTableModel or ExtendedTableModel. Thats why I use proxy mode target class. But with this proxy mode keepAlive doesn't work. The bean (tableModel) is initialized for all requests.
Wojciech
I don't get why such bean is not keept alive! :(
Wojciech
A: 

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.

Wojciech