Clear a Bean variable from the JSF page

2

I have a page with some iteration loops inside my JSF page and here I would like to know how I can clean up this page attribute after each loop.

To be clearer, I know that when rendering a page sometimes a method is called a few times, then it creates a lista for example and fills it if it is empty.

public List<Long> buscarLojas() {
    if (NullUtil.isNull(this.idsLoja)) {
        this.idsLoja = new ArrayList<Long>(this.getPojo().getRelatorioExtratoLojista().keySet());
    }
    return idsLoja;
}

In the above code this is done, but I would like to know if you have to clean up after exiting the loop ui:repeat

Following my page code, most of the columns are omitted.

<ui:param name="lojas" value="#{bean.buscarLojas()}"/>
<ui:repeat var="loja" value="#{lojas}">
    <ui:param name="filiais" value="#{bean.buscarFilial(loja)}" />
    <ui:repeat var="filial" value="#{filiais}">
        <ui:param name="atendentes" value="#{bean.buscarAtendente(loja, filial)}" />
        <ui:repeat var="atendente" value="#{atendentes}">
            <ui:param name="propostasStatus" value="#{bean.buscarPropostaStatus(loja, filial, atendente)}" />
            <ui:repeat var="propostaStatus" value="#{propostasStatus}">
                <ui:param name="objetos" value="#{bean.buscarObjeto(loja, filial, atendente, propostaStatus)}" />
                <p:panelGrid
                    id="panelGridRelatorioExtratoLojista" 
                    styleClass="panelGridCenter gridNoBackground" 
                    style="width: 100%; white-space:nowrap;">
                    <f:facet name="header">
                        <p:row>
                            <p:column styleClass="columnLeft" colspan="12">
                                <p:outputLabel value="#{bean.criarTituloTabela(objetos[0][4], objetos[0][5], objetos[0][6], objetos[0][3])}"/>
                            </p:column>
                        </p:row>
                        <p:row>
                            <p:column>
                                <p:outputLabel value="Classificação"/>
                            </p:column>
                        </p:row>
                    </f:facet>
                    <ui:repeat var="objeto" value="#{objetos}">
                        <p:row>
                            <p:column>
                                <p:outputLabel value="#{objeto[7]}"/>
                            </p:column>
                    </ui:repeat>
                </p:panelGrid>
                <br/>
            </ui:repeat>
        </ui:repeat>
    </ui:repeat>
</ui:repeat>

The structure that holds the data is this:

private Map<Long, Map<Long, Map<Long, Map<Integer, List<Object>>>>> map;
    
asked by anonymous 08.12.2015 / 11:02

1 answer

2

Conversation summary with OP no chat

Original problem: Clear the data

The OP was storing all the query data and the various projections in a Managed Bean @SessionScoped . Memory consumption was hitting more than 1.5GB, generating a markup of more than 130 MB for a single request. The rendering time was more than 10 minutes.

The original requirement of the OP was that the filters were kept through requests, so I recommended the following solution:

  • FiltroPropostaBean - > Contains filter parameters stored in session (new Managed Bean)
  • PropostasBean - > Bean Request or ViewScoped that uses the data from the Filter bean to query.

With this structure the data only live long enough to be rendered, avoiding wasted memory.

Model and projections

The original PO code used a strategy with ResultTransformer to create a projection:

Map<Long, Map<Long, Map<Long, Map<Integer, List<Object>>>>> map;

This was the pure output of a query after applying their ResultTransformer .

Since this structure was not easily navigable by the OP, it eventually created several projection projections. This is why the method buscarLojas , buscarFilial , etc. With five repeaters nested these methods were called several times, with great processing impact.

So the PB issue had more to do with design than anything else.

By organizing your data with DTOs you can write simpler code for the view, as well as remove projection methods.

E.g, a single method that returns a List<GrupoPropostasDTO> .

class GrupoPropostaDTO {
    private Loja loja; 
    private Filial filial; 
    private Atendente atendente;
    private Loja<Proposta> propostas; 
    // Getters and setters
}

Solve both problems. This transformation can be done in an intermediary service layer or in @PostConstruct of ProspotaBean . So a single transformation is done by request and view does not break the MVC by calling methods to calculate projections.

Paging

Finally, even with DTOs the amount of data is still massive. This can be resolved with Paging .

Good Practices

While modern versions of JSF allow you to use various interesting artifacts, you should consider before using something that breaks the MVC standard as well as good development practices:

  • Keep the view layer stupid. As far as possible the role of the view should only be to display data, making calls to complex methods in the view is a bad smell .
  • Choose the correct scope. The less the better. Not everything can be done 100% Stateless, but the session scope should not be the default choice.
  • Design your model layer well. A good template solves 99% of your problems.
  • Controllers (or, in the case of JSF, the glue layer in the managed beans ) should remain simple. Heavy controllers are symptoms of views doing more than they should and poorly designed service layer / template.
08.12.2015 / 19:16