JAVA - É incorreto utilizar 2 ou mais beans (ManagedBean) em uma mesma página XHTML?

A questão é o seguinte, possuo uma página XHTML (publicacoes_PPA.xhtml) com seu Bean e seus respectivos métodos e nessa página possuo uma tabela que na qual possui um botão que abre um documento (pdf) em outra página, e para isso eu achei mais correto criar um outro bean para tal, assim eu simplesmente chamo o metodo responsavel por carregar o documento na página do PPA. Funciona tranquilamente e dessa forma eu posso aplicar em vários lugares do projeto sem mecher praticamente nada no código

Porém estou receioso quanto a isso e gostaria de saber a opinião de vocês. Está errado ou não?

SEGUE O TRECHO DO CÓDIGO XHTML USANDO 2 BEANS:

<h:form enctype="multipart/form-data">
        <p:dataTable 
            id="ppa" 
            scrollable="true"
            rowHover="true"
            lazy="true"
            paginatorPosition="top"
            paginator="true"
            rowsPerPageTemplate="#{publicacoes_PPABean.rowsPerPageTemplate}"
            rows="#{publicacoes_PPABean.registroPaginacao}"
            var="obj"
            value="#{publicacoes_PPABean.listaPlanoPlurianual}"
            resizableColumns="true"
            selectionMode="single" 
            selection="#{publicacoes_PPABean.ppaObjeto}"
            emptyMessage="#{publicacoes_PPABean.mensagemTabelaVazia}"
            rowKey="#{obj.periodo}">

            <p:column headerText="Período" style="width: 5%; text-align: center">
                <h:outputText value="#{obj.periodo}" title="#{obj.periodo}" />
            </p:column>

            <p:column headerText="Descrição" style="width: 60%">
                <h:outputText value="#{obj.texto}" title="#{obj.texto}" />
            </p:column>

            <p:column headerText="Ação" style="width: 10%; text-align: center" >
                <h:commandLink action="#{publicacoes_PPABean.download(obj.arquivo, obj.texto)}" immediate="true"  title="Fazer o download" >
                    <h:graphicImage  name="/images/download_24x24.png" /> 
                </h:commandLink>
          
                <p:separator class="v-separator" />
                
                <p:commandLink process="@this @form"
                               title="Visualizar arquivo"
                               action="#{visualizacaoArquivosBean.carregaVisualizacaoArquivo(obj.arquivo)}">
                    <h:graphicImage  name="/images/lupa_24x24.png" /> 
                </p:commandLink>
            </p:column>  

        </p:dataTable>
    </h:form>

Não.

Alguns programadores mais antigos me falaram uma vez que o correto é um bean para cada página, por isso estou um pouco receioso. Vc acha que isso procede ou não tem nada a ver?

Um bean para cada página era justificável quando você associava uma jsp a um bean (e sim, era um bean parecido com os pojos que você conhece).
Agora, desde o advento do facelets, isso passou a ser algo comum.
Tudo bem que quando utiliza-se facelets você acaba adicionando vários xhtml a um layout, mas, no final, é como se fosse um único e gigantesco xhtml.

Outra solução é utilizar a herança… Mas não sei até que ponto as classes que representam os teus beans.

Entendi. O engraçado é que um dos meus superiores ao ver isso, reprovou na hora, mesmo funcionando perfeitamente. Expliquei para ele que dessa forma não iria precisar ficar repetindo o mesmo método para todos os beans que tivessem páginas com a opção de visualizar documentos e que isso é uma pratica comum, mas ele não concordou, alegando que se, por exemplo, um outro programador alterasse o nome do método nesse bean, ele teria que sair caçando página por pagina para concertar isso… eu achei uma desculpa meio fraca, mas enfim. Obrigado.

Bom dia Augusto,

E essa abordagem:

@ManagedBean
@ViewScoped
class PublicacaoBean {
    
    @ManagedProperty("visualizacaoArquivosBean")
    private VisualizacaoArquivosBean visualizacaoArquivosBean;
    
    public String download(Object arquivo, Object texto) {
        // TAREFA
    }
    
    public String carregaVisualizacaoArquivo(Object arquivo) {
        visualizacaoArquivosBean.carregaVisualizacaoArquivo(obj.arquivo);
    }
    
}

Se outro programador mudar o nome do método não precisa ir buscar em arquivos xhtml =)

Não necessáriamente.

Suponha que você tenha uma tela onde precisa pegar o usuário logado que está armazenado em um beam de sessão.

Você irá injetar o beam de sessão no seu beam atual para poder acessá-lo.

Outro exemplo. Seu sistema tem uma lista empresas e toda logíca de negocio em um beam.

Você pode injetar esse beam em todas as telas que utilizam essas empresas.

E qual a probabilidade de se trocar nomes de métodos? O que eu vejo é criar novos métodos, alterar existentes, mas mudar o nome do método, da classe, mudar o banco de dados, difícil.
De qualquer maneira, é uma opção.

Pouco provável, mas se acontecer acredito que a opção que apresentei vai ajudar.

rs
Baita desculpa esfarrapada do gerente, qqer editor de texto atual resolveria isso, se esse fosse realmente o problema xP

Mas enfim …

Netbeans:
Botão direito “Localizar Uso”. Mostra todas as chamadas ao método.
Botão direito “Refatorar” > “Renomear”. Altera a chamada em todos os usos.

Desculpa esfarrapada é pouco. Porém manda quem pode obdece quem tem juizo.

ManagedBean injetando outro ManagedBean, #medo. Seria melhor OO do que fazer isso, na minha opiniao

Em todos esses anos nessa indústria vital, eu nunca vi. Mas isso é só a minha porca experiência.
Enfim, concordo com o @igor_ks.
Mas, não vejo problema algum em ter um xhtml interagindo com dois, três, dez managed beans.

O que mostrei foi a partir do cenario apresentado pelo Augusto_Soares8 onde o mesmo possui dois MB que já estão implementados.

Mas, qual seria seu medo? Quais pontos para não utilizar essa abordagem?

Compartilha =)

rs… medo é só modo de dizer. Mas nas boas práticas, a gente não injeta componentes da mesma camada.

Exemplo: dao chamando outro dao, service chamando outro service, e o mesmo pra managed bean chamando outro managed bean.

Cada camada, pensando em dao > service > managedbean, deve ser dependente apenas das camadas abaixo, assim corre menos risco de chamada cíclica, ou seja, um chama o outro e esse mesmo chama ele novamente (pressupondo outra boa pratica que uma camada abaixo NUNCA chama um componente da camada assim, exemplo service, chamando managed bean). Além do fato de poder garantir que eu removendo um componente da camada mais alta, não vai quebrar em nenhum outro lugar.

Se dois managed beans tem algo em comum, joga esse método para um nivel mais baixo, um service por exemplo e ambos chamam ele. É o mais correto que vejo.

2 curtidas

Ou utiliza o princípio da herança :smiley:

Isso, foi nisso mesmo que me referi quando disse que é preferível OO do que injetar outro managed bean :slight_smile:

Acontece que muitas vezes quando estamos desenvolvendo sem muito planejamento. Acabamos por criar beans sem imaginar que ele poderá ser reutilizado. Daí é mais facil injetar um beam no outro do que refazer o que está pronto.

1 curtida