Clear a Bean variable from the JSF page

Asked

Viewed 685 times

2

I have a page with some iteration loops inside my page JSF and then I’d like to know how I do to after each loop clear that attribute from the page.

To be clear, I know that when rendering a page sometimes a method is called a few times, so one 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 is done, but I would like to know if it has how to clear after loop execution ui:repeat

Follow my page code, this omitted most columns.

<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 houses the data is this:

private Map<Long, Map<Long, Map<Long, Map<Integer, List<Object>>>>> map;
  • Hi Macario, could you clarify what you mean by clean? It seems that you are building a list of Ids on top of the keys of a map. Would you like to clear the map?

  • @Anthonyaccioly I updated the code, as I said in the text, a lot of the times I will be accessing the methods on the page. And I would like every call of the methods on the page, to move to a list, as soon as I finish the loop on that list, to clear the list to get the new content, that has more to do with the performance on the page rendering issue JSF.

  • Hello Macario, from what I understand you want to wear one map.clear() After you built the list, would that solve the problem? Off the main subject, but couldn’t its four nested map structure be replaced by something more object-oriented? In Java it’s always strange to see something like this.

  • Face you got it wrong, it would be the following, imagine the following situation, you have a component that loads a list from the database data. Now imagine that when rendering this component, this method will be called for example 2 or 3 times, so it will be called 3 times in the bank, so I use the list not to overload, understood?

  • On the subject of object orientation, is that the object in question has these attributes but the way this table is built made me create this structure.

  • Opa Macario. I think what is making your question get confused is the design. It seems that your code is reversing the MVC, the view smart is calling various methods nested in the bean to build the data, now you want the view also notify the bean after the last <ui:repeat to clear the list idLojas. That’s it?

  • @Anthonyaccioly see the chat please

Show 3 more comments

1 answer

2


Summary of the conversation with the OP in chat

Original problem: Clear data

OP was storing all query data and various projections in a Managed Bean @SessionScoped. Memory consumption was beating at over 1.5GB, generating a Markup of over 130 MB for a single request. The render time was more than 10 minutes.

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

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

With this structure the data only lives long enough to be rendered, avoiding memory waste.

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;

That was the pure exit of a query after their application Resulttransformers.

As this structure was not easily navigated by the OP, he ended up creating several projections of the projection. This is the reason of the method buscarLojas, buscarFilial, etc. With five repeaters nested these methods were called several times, with great processing impact.

Thus, the issue of OP had more to do with design than anything else.

Organizing the data with Dtos it is possible to write simpler code for the view as well as remove the 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
}

Solves both problems. This transformation can be done in an intermediary layer of services or in a @PostConstruct of ProspotaBean. Thus a single transformation is made by request and the 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 solved with Paging.

Good Practices

While modern versions of JSF allow the use of several interesting tricks, it’s good to consider before using something that breaks the MVC standard, as well as good development practices:

  • Keep the layer of view dumb. As far as possible the role of the view should be to only display data, make calls to complex methods in the view is a bad Smell.
  • Choose the correct scope. The less state 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 model solves 99% of your problems.
  • Controllers (or in the case of JSF the glue layer in Managed Beans) should remain simple. Heavy controllers are symptoms of views doing more than they should and layer services / poorly designed model.
  • I have a question for the following, the system implements Spring for injection of dependencies. This is done in different files, the problem is that I have set in the file of filter, the class as session, and in the archive of view I put as request but when searching, it seems that the filter data class is lost. How to fix this?

  • 1

    Hi Macario. It is worth opening a new question. You should have a scope only for Filter (Session). The request class just injects the filter and redoes the query.

  • Done! Thank you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.