2
votes

I´m trying to show the progress of several batch processes using a progressbar for each one of them. The problem is that only one progressbar is been sent to server side (the last one). Here is the code...

I made a RequestScoped Named bean for the progress beacause I read that for multiple progressBar it is needed a bean instance for each one of the progressbars, but that do not resolve my problem.

I'm using Primefaces 6.1 with JSF 2.2.

Any ideas? Thanks!

<h:form id="formExecutions">        
        <p:dataGrid id="jobs" value="#{jobExecutorController.jobExecutions}" var="job" rows="5" paginator="true" emptyMessage="#{MessageResources['text.noRecordsFound']}"
        paginatorPosition="bottom" columns="1" layout="grid">
            <f:facet name="header">
                #{MessageResources['text.batchProcesses']}
            </f:facet>

                <p:outputPanel layout="block" >
                    <p:panelGrid  cellpadding="5" styleClass="vf-panelGrid">            
                        <p:row style="width:100%">  
                            <p:column>                  
                                <p:outputLabel for="executionId" value="#{MessageResources['text.executionId']}:" style="font-weight:bold"/>                    
                            </p:column>
                            <p:column>                              
                                <h:outputText id="executionId" value="#{job.executionId}" />
                            </p:column>
                            <p:column>                      
                                <p:outputLabel for="name" value="#{MessageResources['text.name']}:" style="font-weight:bold"/>
                            </p:column>
                            <p:column style="width:10%">                        
                                <h:outputText id="name" value="#{job.name}"/>
                            </p:column> 

                            <p:column  style="width:50%" rowspan="2">                           
                                <p:progressBar id="progressBar" widgetVar="progressBar" ajax="true" value="#{progressController.progress(job)}" labelTemplate="{value}%" styleClass="animated" style="height: 20px; line-height: 20px;" global="false" interval="3000">
                                    <p:ajax event="complete" listener="#{progressController.onCompleteJob(job)}" update="messageDisplay" process="@this"/>
                                    <p:ajax update="jobInfo"/>
                                </p:progressBar>                            
                            </p:column>                                 

                            <p:column  style="width:4%" />

                            <p:column rowspan="2" style="text-align:right">                                 
                                <p:commandButton id="restart" onclick="PF('confirmRestartJob').show()" styleClass="coloured-icons-batch restart-image-icon blink" 
                                    disabled="#{not job.enableRestartAbandon}" immediate="true" title="">
                                    <f:setPropertyActionListener value="#{job.executionId}" target="#{jobExecutorController.executionIdSelected}" />
                                    <f:setPropertyActionListener value="#{job.name}" target="#{jobExecutorController.executionNameSelected}" />
                                </p:commandButton>
                                <p:tooltip for="restart" value="#{MessageResources['text.restartJobExecution']}" position="top"></p:tooltip>                                    

                                <p:spacer width="10" />

                                <p:commandButton id="stop" onclick="PF('confirmStopJob').show()"  styleClass="coloured-icons-batch stop-image-icon blink" 
                                     disabled="#{not job.enableStop}" immediate="true" title="">
                                    <f:setPropertyActionListener value="#{job.executionId}" target="#{jobExecutorController.executionIdSelected}" />
                                    <f:setPropertyActionListener value="#{job.name}" target="#{jobExecutorController.executionNameSelected}" />                             
                                </p:commandButton>
                                <p:tooltip for="stop" value="#{MessageResources['text.stopJobExecution']}" position="top"></p:tooltip>

                                <p:spacer width="10" />

                                <p:commandButton id="abandon" onclick="PF('confirmAbandonJob').show()" styleClass="coloured-icons-batch abandon-image-icon blink" 
                                     disabled="#{not job.enableRestartAbandon}" immediate="true" title="">
                                    <f:setPropertyActionListener value="#{job.executionId}" target="#{jobExecutorController.executionIdSelected}" />
                                    <f:setPropertyActionListener value="#{job.name}" target="#{jobExecutorController.executionNameSelected}" />                             
                                </p:commandButton>
                                <p:tooltip for="abandon" value="#{MessageResources['text.abandonJobExecution']}" position="top"></p:tooltip>

                            </p:column>             
                        </p:row>        
                    </p:panelGrid>

                    <h:panelGroup id="jobInfo" >
                        <p:panelGrid columns="4" cellpadding="5" styleClass="vf-panelGrid">                     

                            <p:outputLabel for="creationDate" value="#{MessageResources['text.creationDate']}:" style="font-weight:bold"/>                          
                            <h:outputText id="creationDate" value="#{job.formattedDate(job.createdDate)}" />

                            <p:outputLabel for="startDate" value="#{MessageResources['text.dateStartProcess']}:" style="font-weight:bold"/>                         
                            <h:outputText id="startDate" value="#{job.formattedDate(job.startedDate)}" />

                            <p:outputLabel for="lastUpdate" value="#{MessageResources['text.lastUpdate']}:" style="font-weight:bold"/>                          
                            <h:outputText id="lastUpdate" value="#{job.formattedDate(job.lastUpdate)}" />

                            <p:outputLabel for="toProcess" value="#{MessageResources['text.itemsToProcess']}:" style="font-weight:bold"/>                           
                            <h:outputText id="toProcess" value="#{job.itemsToProcess}" />

                            <p:outputLabel for="endDate" value="#{MessageResources['text.ended']}:" style="font-weight:bold"/>                          
                            <h:outputText id="endDate" value="#{job.formattedDate(job.endedDate)}" />

                            <p:outputLabel for="processed" value="#{MessageResources['text.itemsProcessed']}:" style="font-weight:bold"/>                           
                            <h:outputText id="processed" value="#{job.itemsProcessed}" />

                            <p:outputLabel for="status" value="#{MessageResources['text.state']}:" style="font-weight:bold"/>                           
                            <h:outputText id="status" value="#{job.status}" />

                        </p:panelGrid>
                    </h:panelGroup>
                </p:outputPanel>

            <p:spacer width="5"/>   
            <p:separator />
            <p:spacer width="5"/>                                   
        </p:dataGrid>

My RequestScope backing bean...

@Named("progressController")
@RequestScoped
public class ProgressController
{    
    @EJB
    private EJBJobRepositoryLocal ejbJobRepository;

    public Long progress(DMJob jobExecution) throws VfCmsSqlException
    {
        if (jobExecution.getStatus().equals(BatchStatus.STARTED.name())) {
            jobExecution.setProgress(ejbJobRepository.getJobProgress(jobExecution.getExecutionId()));
        }

        PrimeUtil.get().update("formExecutions:jobInfo");

        return jobExecution.getProgress();
    }

    public void onCompleteJob(DMJob jobExecution)
    {
        Object[] parameters = {jobExecution.getName(), jobExecution.getExecutionId()};

        Messages.displayInfoMessage("text.jobComplete", parameters);
    }
}
1

1 Answers

5
votes

Ok. The problem is that the PrimeFaces().start() method is not been executed over all the components generated by JSF. So, what I did is a javascript function which is executed when the page is fully loaded. In my case the components that I needed to initialize are several progress bar. My components are inside a data scroller which is inside a form, that's why I concat those id's. The 'i' is the index of each of the rendered progress bar in the page.

<script type="text/javascript">
        $(window).load(function() {
            startProgress();
        });

        function startProgress(){
            var pid = document.getElementsByClassName('ui-progressbar');
            var pidLength = pid.length;
            for (var i = 0; i &lt; pidLength; i++) {
                var id = "formExecutions:scroller:".concat(i).concat(":progressBar");
                PrimeFaces.getWidgetById(id).start();
            }
        }
    </script>

And that was all!