3

I have a problem when the primefaces data table gets updated before the SQL statements for updating\removing entities from this table finish executing.

01:08:13,255 INFO [reg.data.model.LazyEventDataModelMod]  - Loading the lazy event data between 0 and 10 
01:08:13,256 DEBUG [org.hibernate.SQL]  - 
    select
        count(*) as col_0_0_ 
    from
        events event0_ limit ? 
01:08:13,394 DEBUG [org.hibernate.SQL]  - 
    delete 
    from
        events 
    where
        id=? 

The problem is that the entity manager doesn't return anything to indicate that it had successfully executed the delete\update query.

I use JSF 2, Weld 1.1.5.Final, Primefaces 3.0.1, Seam persistence/transaction/solder 3.0.1.Final.
The server is Tomcat 7.

Here is the code for the button that invokes the action on the controller bean:

<p:commandButton id="deleteButton" value="#{msg.delete}"
    icon="ui-icon-trash" update=":events_form :messages"
    actionListener="#{eventController.delete()}" />

<p:commandButton id="refreshButton" value="#{msg.refresh}"
    icon="ui-icon-refresh" update=":events_form :messages" />

The update doesn't happen after the first button is pressed, however the second one does update the table, both of them have identical ajax update sections.

Code of the delete() method:

public void delete() {
            if (getSelEvent() != null) {
                log.debug("deleting event " + getSelEvent().getId());

                dao.delete(getSelEvent());

    // Tried putting the code for reloading te data model here, but it is also executed before the sql statements...

            } else {
                log.warn("delete action cannot proceed, no event selected!");
            }

        }

deleteById() method in the dao:

public void delete(T entity) {
        if (em == null)
            init();
        log.debugf("removing %s instance", simpleName);

        entity = em.merge(entity);

// The problem lies here - em.remove() does not return any value to indicate success/failure, so the control is released before the SQL statements finish execution 

em.remove(entity);
}

data table:

<p:dataTable id="event_list" value="#{eventController.lazyModel}"
                var="event" rowKey="#{event.id}" paginator="true" rows="20"
                selection="#{eventController.selEvent}" selectionMode="single"
                onRowSelectUpdate="content,messages"
                onRowEditUpdate="content,messages"
                paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                rowsPerPageTemplate="10,25,50,100">

LazyDataModel class:

public class LazyEventDataModel extends LazyDataModel<Event> {

private static final long serialVersionUID = 2386224274507659474L;

private EventDAO dao;

private Logger log = Logger.getLogger(LazyEventDataModel.class);

private List<Event> data;

public LazyEventDataModel() {
    dao = new EventDAO();
}

@Override
public Event getRowData(String rowKey) {
    return dao.find(Long.parseLong(rowKey));
}

@Override
public Object getRowKey(Event event) {
    return event.getId();
}

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

    if (sortField == null || "".equals(sortField)) {
        sortField = "event_date";
        sortOrder = SortOrder.DESCENDING;
    }

    if (sortField.equals("date"))
        sortField = "event_date";

    // Get the paginated and sorted data
    data = dao.findPageObjects(Event.class, first, pageSize, sortField,
            sortOrder, filters);

    log.infof("Loading the lazy event data between " + first + " and "
            + (first + pageSize));

    // Set the row count
    this.setRowCount(Global.safeLongToInt(dao.count()));

    return data;
}
}

The only solution I can think of right now would be adding the timer after calling the dao.delete(getSelEvent()) and refreshing the data model after that timer.

Shajirr
  • 164
  • 3
  • 14

1 Answers1

0

The update attribute of your commandButton must include the datatable as well. Whatever is set in the update will happen once the ajax call is completed. Considering that you're not creating a separate thread to perform the database operations (which would make the ajax request finish almost instantly), do as follows.

One caveat, though: for some reason referencing the id of the datatable in the update attribute does not work. I normally just wrap it with a panelGroup and tell the button to update the panelGroup instead. Something like this:

<p:commandButton value="Delete" actionListener="#{someBean.delete}" update="panel">
</p:commandButton>
<h:panelGroup id="panel">
<p:dataTable id="event_list" value="#{eventController.lazyModel}"
                var="event" rowKey="#{event.id}" paginator="true" rows="20"
                selection="#{eventController.selEvent}" selectionMode="single"
                onRowSelectUpdate="content,messages"
                onRowEditUpdate="content,messages"
                paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                rowsPerPageTemplate="10,25,50,100">

...

</h:panelGroup>

Note that the primeFaces button components use ajax by default, so you don't need the jsf2 ajax tag at all.

Andre
  • 3,874
  • 3
  • 35
  • 50
  • Unfortunately, as I suspected, the problem lies in the ajax call being executed before the SQL statements. I'll rephrase my question and add the log. The info about referencing the table through additional component is useful though, usually I just update the whole form. – Shajirr Feb 16 '12 at 23:03