0

I have a page where a <p:commandButton> is used to start a search. After the search is completed, it refreshes a <p:gmap> and a dataTable. At the same time, I create a text file containing the search details. I want to create a download button for this file at the end of the page.

However, generating the file take time. If the user click the button before the process is completed, he will receive HTTP 404 error. I am trying to enable the Download button only when the file is created, but I don't know how toggle the disabled attribute in the download button from true to false only when the file is completed. Is it possible?

I have tried the solution described here, but it did not work.

Web page

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="template.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:p="http://primefaces.org/ui"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:ui="http://java.sun.com/jsf/facelets">  


    <ui:define name="menuDireito"> 
        <f:view transient="true">
            <script src="https://maps.google.com/maps/api/js?sensor=false"></script>         
            <h:form id="form"> 
                <br></br>                                
                <p:selectOneMenu  immediate="true" value="#{circlesView.selectedCategory}"  converter="categoriaConverter" panelStyle="width:150px"  
                                  effect="fade" var="p" style="width:200px"  filter="true" filterMatchMode="startsWith">  
                    <f:selectItem itemLabel="Selecione o Estabelecimento" itemValue="" />  
                    <f:selectItems value="#{autoCompleteCategoria.categories}" var="category" itemLabel="#{category}" itemValue="#{category}"/>                                   

                    <p:column>  
                        #{p}  
                    </p:column>  

                </p:selectOneMenu>                                 

                <br></br><br></br>           
                <div style="text-align: left">Indique a área de busca:</div>
                <p:inputText id="range" value="#{circlesView.range}" /> 
                <p:watermark for="range" value="Ex: 1000" id="watermark" />

                <br></br><br></br>                   

                <div style="text-align: center">
                    <p:commandButton icon="fa fa-fw fa-search" style="width:150px !important; height: 30px !important;" ajax="false" process="@all" value="Pesquisar" action="#{circlesView.filteredQuery()}" update="dataTable" oncomplete="PF('dlg').show()" />             
                </div>

                <br></br><br></br> 

                <p:separator style="margin-bottom:10px"/>

                <p:gmap id="gmap" center="-23.5569834, -46.6362086" zoom="13" type="HYBRID" style="width:100%;height:400px" model="#{circlesView.circleModel}">                
                </p:gmap>

                <p:separator style="margin-bottom:10px"/>                                         

                <h3>Resultados</h3>  
                <p:dataTable id="basicDT" var="obj" value="#{circlesView.objs}">
                    <f:facet name="header">
                        Locais com infectados na vizinhança
                    </f:facet>
                    <p:column style="text-align: center" headerText="Nome">
                        <h:outputText value="#{obj.name}" />
                    </p:column>
                    <p:column style="text-align: center" headerText="# pessoas">
                        <h:outputText value="#{obj.score}" />
                    </p:column>               
                    <p:column style="text-align: center" headerText="Visualizar">
                        <p:commandButton update=":form:localDetail" oncomplete="PF('mapDialog').show()" icon="ui-icon-search" title="View">
                            <f:setPropertyActionListener value="#{obj}" target="#{circlesView.selectedObj}" />
                        </p:commandButton>                                       
                    </p:column>
                    <p:column style="text-align: center" headerText="Visualizar">
                        <p:commandButton update=":form:nDetail" oncomplete="PF('ndialog').show()" icon="ui-icon-search" title="View">
                            <f:setPropertyActionListener value="#{obj}" target="#{circlesView.selectedObj}" />
                        </p:commandButton>
                    </p:column>  
                </p:dataTable>  

                <p:dialog header="Local Position" widgetVar="mapDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false" width="625" height="400">

                    <p:outputPanel id="localDetail" style="text-align:center;">
                        <p:panelGrid  rendered="#{not empty circlesView.selectedObj}" >
                            <p:gmap id="gmap2" center="#{circlesView.selectedObj.coordPattern}" zoom="14" type="HYBRID" style="width:100%;height:400px" model="#{circlesView.selectedObj.mapModel}"/>
                        </p:panelGrid>         
                    </p:outputPanel>
                </p:dialog> 

                <p:dialog header="Neighborhood Info" widgetVar="nDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false">
                    <p:outputPanel id="nDetail" style="text-align:center;">
                        <p:panelGrid  columns="2" rendered="#{not empty dtSelectionView.selectedCar}" columnClasses="label,value">                

                            <h:outputText value="Id:" />
                            <h:outputText value="#{circlesView.selectedObj.id}" />

                            <h:outputText value="Dist" />
                            <h:outputText value="#{circlesView.selectedObj.distancia}" />
                        </p:panelGrid>
                    </p:outputPanel>
                </p:dialog>

            </h:form>
            <br></br>

            <h:form id="downloadForm">
                <p:commandButton action="#{circlesView.downloadAction()}" value="Download" ajax="false" icon="fa fa-fw fa-download" disabled="#{circlesView.disable}">
                    <p:fileDownload value="#{circlesView.file}" />
                </p:commandButton>                  
            </h:form>

        </f:view>
    </ui:define>        

</ui:composition>

Bean

@ManagedBean(name = "circlesView")
@SessionScoped
public class PreferenceQuery implements Serializable {

    private MapModel circleModel;
    private String path;
    private String contentType;
    private boolean disable;
    Integer range;
    Properties properties;
    DefaultStatisticCenter statistics;
    Integer k = 20;
    List<ScoredObjectMarked> objs;
    ScoredObjectMarked selectedObj;
    String selectedCategory;
    private static final long serialVersionUID = 1L;

    public PreferenceQuery() {
        disable = true;
    }

    public List<ScoredObjectMarked> query() throws FileNotFoundException, UnsupportedEncodingException, IOException {

        disable = true;
        objs = new ArrayList<ScoredObjectMarked>();
        statistics = new DefaultStatisticCenter();

        try {
            properties = Settings.myLoadProperties(new File("D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\web\\search.properties"));
        } catch (IOException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        //Converte para radius
        double radius = (180 * range) / (6378137.0 * Math.PI);

        PreferenceFileTermManager fileTermManager = createPreferenceFileTermManager();

        PreferenceTreeTermManager treeTermManager = createPreferenceTreeTermManager();

        PreferenceIndex prefIndex = createPreferenceSpatialInvertedIndex(fileTermManager, treeTermManager, false);

        StarRTree rTree = null;
        try {
            rTree = createRtree(null);
        } catch (IOException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            prefIndex.open();
        } catch (SSEExeption ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ColumnFileException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        PreferenceSearch experiment = new PreferenceSearch(statistics,
                false,
                prefIndex.getTermVocabulary(),
                1,
                k,
                1,
                0.5 /*alfa*/,
                Double.parseDouble(properties.getProperty("dataset.spaceMaxValue")),
                0,
                selectedCategory,
                prefIndex, rTree,
                3,
                true,
                radius);

        try {
            experiment.open();
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        Iterator<SpatioTextualObject> result = null;
        try {
            result = experiment.search("patient", 20);
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        while (result.hasNext()) {
            ScoredObject p = (ScoredObject) result.next();
            ScoredObjectMarked p_model = new ScoredObjectMarked(p.getId(), p.getLatitude(), p.getLongitude(), range, p.getMessage());
            p_model.setScore(p.getScore());
            objs.add(p_model);
        }

        try {
            experiment.close();
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        circleModel = new DefaultMapModel();

        for (int a = 0; a < objs.size() && a < k; a++) {

            ScoredObject poi = objs.get(a);

            LatLng coords = new LatLng(poi.getLatitude(), poi.getLongitude());

            Circle circle = new Circle(coords, range);
            circle.setStrokeColor("#d93c3c");
            circle.setFillColor("#d93c3c");
            circle.setFillOpacity(0.5);

            circleModel.addOverlay(circle);
        }

        reportFeatures();
        disable = false;
        return objs;
    }

    public void downloadAction() {
        path = "D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\src\\java\\query\\fullReport.txt";
        contentType = FacesContext.getCurrentInstance().getExternalContext().getMimeType(path);
    }

    public StreamedContent getFile() throws FileNotFoundException {
        return new DefaultStreamedContent(new FileInputStream("D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\src\\java\\query\\fullReport.txt"), contentType, "Report.txt");
    }

    public void reportFeatures() throws FileNotFoundException, UnsupportedEncodingException, IOException {

        Writer output = new OutputStreamWriter(new FileOutputStream("D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\src\\java\\query\\fullReport.txt", false), "ISO-8859-1");

        for (ScoredObjectMarked poi : objs) {

            output.write("Pacientes próximos ao " + poi.getName() + "\n\n");

            SpatioItemCollection collection = poi.getNN();
            Iterator colIt = collection.iterator();

            while (colIt.hasNext()) {
                SpatioItem paciente = (SpatioItem) colIt.next();
                output.write("\t Paciente " + paciente.getId() + ": (" + paciente.getLatitude() + ", " + paciente.getLongitude() + ") "
                        + "Distância para o Hospital: " + paciente.getDistancia() + "\n");
            }
            output.write("\n");
            output.flush();
        }
        output.close();
    }

    public List<ScoredObjectMarked> filteredQuery() throws IOException, FileNotFoundException, ClassNotFoundException, SSEExeption, ColumnFileException {

        objs = new ArrayList<ScoredObjectMarked>();
        statistics = new DefaultStatisticCenter();

        try {
            properties = Settings.myLoadProperties(new File("D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\web\\search.properties"));
        } catch (IOException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        //Converte para radius
        double radius = (180 * range) / (6378137.0 * Math.PI);

        PreferenceFileTermManager fileTermManager = createPreferenceFileTermManager();

        PreferenceTreeTermManager treeTermManager = createPreferenceTreeTermManager();

        PreferenceIndex prefIndex = createPreferenceSpatialInvertedIndex(fileTermManager, treeTermManager, false);

        StarRTree rTree = createRtree(selectedCategory);

        prefIndex.open();

        PreferenceSearch experiment = new PreferenceSearch(statistics,
                false,
                prefIndex.getTermVocabulary(),
                1,
                k,
                1,
                0.5 /*alfa*/,
                Double.parseDouble(properties.getProperty("dataset.spaceMaxValue")),
                0,
                selectedCategory,
                prefIndex, rTree,
                3,
                true,
                radius);

        try {
            experiment.open();
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        Iterator<SpatioTextualObject> result = null;
        try {
            result = experiment.search("patient", k);
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        while (result.hasNext()) {
            ScoredObject p = (ScoredObject) result.next();
            ScoredObjectMarked p_model = new ScoredObjectMarked(p.getId(), p.getLatitude(), p.getLongitude(), range, p.getMessage());
            p_model.setScore(p.getScore());
            p_model.setNN(p.getNN());
            objs.add(p_model);
        }

        try {
            experiment.close();
        } catch (ExperimentException ex) {
            Logger.getLogger(PreferenceQuery.class.getName()).log(Level.SEVERE, null, ex);
        }

        circleModel = new DefaultMapModel();

        for (int a = 0; a < objs.size() && a < k; a++) {

            ScoredObject poi = objs.get(a);

            LatLng coords = new LatLng(poi.getLatitude(), poi.getLongitude());

            Circle circle = new Circle(coords, range);
            circle.setStrokeColor("#d93c3c");
            circle.setFillColor("#d93c3c");
            circle.setFillOpacity(0.5);

            circleModel.addOverlay(circle);
        }

        reportFeatures();
        disable = false;

        return objs;
    }

    public boolean getDisable() {
        return disable;
    }

    public void setDisable(boolean disable) {
        this.disable = disable;
    }

    public List<ScoredObjectMarked> getObjs() {
        return objs;
    }

    public void setObjs(List<ScoredObjectMarked> objs) {
        this.objs = objs;
    }

    public MapModel getCircleModel() {
        return circleModel;
    }

    public void onCircleSelect(OverlaySelectEvent event) {
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Circle Selected", null));
    }

    public Integer getRange() {
        return range;
    }

    public void setRange(Integer range) {
        this.range = range;
    }

    public ScoredObject getSelectedObj() {
        return selectedObj;
    }

    public void setSelectedObj(ScoredObjectMarked selectedObj) {
        this.selectedObj = selectedObj;
    }

    public String getSelectedCategory() {
        return selectedCategory;
    }

    public void setSelectedCategory(String selectedCategory) {
        this.selectedCategory = selectedCategory;
    }

    private StarRTree createRtree(String poi) throws FileNotFoundException, IOException, ClassNotFoundException {

        if (poi == null) {
            poi = "Sao Paulo";
            selectedCategory = "Sao Paulo";
        }

        Path path = Paths.get(properties.getProperty("experiment.folder") + "\\rtrees\\" + selectedCategory);
        Files.createDirectories(path);

        StarRTree rTree = new StarRTree(statistics, "", properties.getProperty("experiment.folder") + "\\rtrees\\" + selectedCategory + "\\rtree",
                Integer.parseInt(properties.getProperty("srtree.dimensions")),
                Integer.parseInt(properties.getProperty("srtree.cacheSize")),
                Integer.parseInt(properties.getProperty("disk.blockSize")),
                Integer.parseInt(properties.getProperty("srtree.minNodeCapacity")),
                Integer.parseInt(properties.getProperty("srtree.maxNodeCapacity")));

        System.out.println("POI: " + poi);
        LoadRTree.load(rTree, "D:\\Documents\\GitHub\\COVID-Geo-Monitoring\\web\\Categorias\\" + poi + ".txt");

        return rTree;
    }

    private PreferenceIndex createPreferenceSpatialInvertedIndex(PreferenceFileTermManager fileTermManager,
            PreferenceTreeTermManager treeTermManager, boolean constructionTime) {
        return new PreferenceIndex(statistics,
                properties.getProperty("experiment.folder"),
                Integer.parseInt(properties.getProperty("disk.blockSize")),
                100,
                fileTermManager, treeTermManager,
                constructionTime);
    }

    private PreferenceTreeTermManager createPreferenceTreeTermManager() {
        return new PreferenceTreeTermManager(statistics, properties.getProperty("experiment.folder"),
                Integer.parseInt(properties.getProperty("srtree.dimensions")),
                Integer.parseInt(properties.getProperty("srtree.cacheSize")),
                Integer.parseInt(properties.getProperty("disk.blockSize")),
                Integer.parseInt(properties.getProperty("srtree.minNodeCapacity")),
                Integer.parseInt(properties.getProperty("srtree.maxNodeCapacity")),
                100);
    }

    private PreferenceFileTermManager createPreferenceFileTermManager() {
        return new PreferenceFileTermManager(statistics,
                Integer.parseInt(properties.getProperty("disk.blockSize")),
                properties.getProperty("experiment.folder") + "/s2i",
                Integer.parseInt(properties.getProperty("srtree.cacheSize")));
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
João Almeida
  • 45
  • 1
  • 1
  • 8
  • Try to look at this [question](https://stackoverflow.com/questions/6482443/how-to-avoid-repeatedly-click-a-button-in-a-form), and enable the download button onComplete of the first button. – WoAiNii Oct 03 '20 at 09:05
  • I have added widgetVar="downButton" to the command button, then in the first command button I included onclick="PF('downButton').disable()" oncomplete="PF('downButton').enable()" as described in the link you provided but it did not work. I have tried with "downButton.enable()" too. Maybe it does not work because, in my case, there are two different buttons? – João Almeida Oct 03 '20 at 21:21
  • Does this answer your question? [How can server push asynchronous changes to a HTML page created by JSF?](https://stackoverflow.com/questions/3787514/how-can-server-push-asynchronous-changes-to-a-html-page-created-by-jsf) – Jasper de Vries Oct 04 '20 at 09:56
  • The sequence should be, download button initially disabled, press the create file button, on completion of it enable the download button and update it. Merge all the pieces and you should get it works, or use the asynchronous approach as @JasperdeVries suggest – WoAiNii Oct 04 '20 at 11:38
  • Thank you all for the responses. The approaches mentioned by you indeed toggle the button on/off. However, these approaches do not synchronize with the file availability. In fact, I am not sure if the "creating file" process is the real problem anymore. Netbeans shows "Deploying " after I click the create file button. If I click the download button during the Deploying Phase, I receive an error. The solutions you have described turn on the download button before this Deploying phase ends, leading to an error if the user clicks on it at the wrong time. – João Almeida Oct 05 '20 at 14:14

0 Answers0