Request X Session

19 respostas
dwduncan

Qual a real vantagem em se usar o escopo do request ao invés de session ? Sempre me disseram que é melhor usar request, parece até um dogma. No meu caso, como uso jsf + richfaces uso bastante o a4j:keepAlive para obter o efeito desejado. Confesso que no meu ponto de vista o keepAlive mantém o bean carregado na memória como se fosse o escopo fosse de seção. Em termos práticos não consegui visualizar a vantagem de não usar session, pelo contrário, tenho que quase mandatóriamente inserir o keepAlive em tudo que é página. Alguém saberia explicar qual seria a melhor abordagem ?

19 Respostas

rod

o componente a4j:keepAlive não mantém o managedbean na sessão.
O que ele faz é aumentar o tempo de vida de um managedbean configurado como request, deixando ele “vivo” por um tempo maior que uma requisição e menor que uma sessão.

No JSF2 foi adicionado essa feature e ela é chamada de View Scope.

R

É idealizado que se use a request por performance, a request morre após apresentar os dados na tela, evitando o lixo na memória…
se vc pensar em um sistema grande faz muita diferença (MUITA MESMO)…
Em session seu servidor de aplicação fica armazenando tudo que vc colocar ali, e não existe um “Garbage Collector” para sessão… Alguns servidores de aplicação chegam armazenar as session em banco de dados interno.

Em sistemas corporativos, quando vc coloca em produção um sistema que utiliza muita session, vc sobrecarrega o servidor de maneira que podia ter sido evitado em desenvolvimento…

é isso…

ps: Utilizei o a4j:keepAlive do RichFaces algumas vezes, realmente sem ele fica complicado trabalhar com o RichFaces, porque o Rich “faz várias submissões constantemente”… Ele é um “tipo de escopo” especial…

A

Olá amigo,

Estou com problemas para usar o keepAlive. Poderia postar um código de exemplo?

Grato.

dwduncan

Geralmente eu o utilizo dentro dos componentes mais apontados pelos “reRender”, claro, depende muito da estrutura de sua página mas de uma forma geral eu uso assim:

<a4j:outputPanel id="tabelaIndisponibilidade" ajaxRendered="true">

                            <a4j:keepAlive beanName="indisponibilidade" />
                            <rich:dataTable
                                styleClass = "centralizar"
                                id="listaindisponibilidades"
                                var="ind"
                                value="#{indisponibilidade.tabelaIndisponibilidades}"
                                rowKeyVar="row" >

                                <rich:column  sortBy="#{ind.id}">
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Protocolo" />
                                    </f:facet>
                                    <h:outputText value="#{ind.id}" />
                                </rich:column>

                                <rich:column width="200px"  sortBy="#{ind.cadastro}">
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Militar" />
                                    </f:facet>
                                    <h:outputText value="#{ind.cadastro}" />
                                </rich:column>

                                <rich:column>
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Início" />
                                    </f:facet>
                                    <h:outputText value="#{ind.inicio}">
                                        <f:convertDateTime type="date" dateStyle="short" locale="pt,BR" timeZone="America/Sao_Paulo" pattern="dd/MM/yyyy"/>
                                    </h:outputText>
                                </rich:column>

                                <rich:column>
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Término" />
                                    </f:facet>
                                    <h:outputText value="#{ind.termino}">
                                        <f:convertDateTime type="date" dateStyle="short" locale="pt,BR" timeZone="America/Sao_Paulo" pattern="dd/MM/yyyy"/>
                                    </h:outputText>
                                </rich:column>

                                <rich:column sortBy="#{ind.motivo}">
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Motivo" />
                                    </f:facet>
                                    <h:outputText value="#{ind.motivo}" />
                                </rich:column>

                                <rich:column>
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Conflito" />
                                    </f:facet>
                                    <h:graphicImage
                                        value="#{ind.urlConflitos}"
                                        onclick="if (#{ind.mensagensConflitos!=''}) alert('#{ind.mensagensConflitos}')"
                                        title="#{ind.mensagensConflitos}" style="border: 0px;" />
                                </rich:column>

                                <rich:column width="200px">
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Enviado por" />
                                    </f:facet>
                                    <h:outputText value="#{ind.enviadoPor}" />
                                </rich:column>

                                <rich:column sortBy="#{ind.dataHoraEnvioSQL}">
                                    <f:facet name="header">
                                        <h:outputText styleClass="headerText" value="Enviado em" />
                                    </f:facet>
                                    <h:outputText value="#{ind.dataHoraEnvio}">
                                        <f:convertDateTime type="date" dateStyle="short" locale="pt,BR" timeZone="America/Sao_Paulo" pattern="dd/MM/yyyy"/>
                                    </h:outputText>
                                </rich:column>

                                <h:column>
                                    <f:facet name="header">
                                        <h:outputText  value="Editar"/>
                                    </f:facet>
                                    <a4j:commandLink ajaxSingle="true" id="editarIndisponibilidade" value="Editar"
                                        oncomplete="#{rich:component('panelEdicaoIndisponibilidade')}.show()"
                                        reRender="modalIndisponibilidade">
                                        <f:setPropertyActionListener value="#{ind}"
                                                                     target="#{indisponibilidade.selecionada}" />
                                    </a4j:commandLink>
                                </h:column>

                            </rich:dataTable>
                        </a4j:outputPanel>

O atributo principal é o beanName, é aí que vc informa nome de seu bean, como declarado no faces-config.

Obrigado pelas respostas, realmente trabalhamos com sistemas corporativos. Outra dúvida então. Existe vantagem um utilizar o “View Scope” ao invés do keepAlive ?

A

dwduncan,

Fiz como no seu exemplo, porém, quando eu clico no botao atualizar ou no datascroller os dados do dataModel somem. Eu tenho que clicar no botao exibir para que seja feita uma nova consulta e populado o dataModel.

Você sabe o que pode estar ocorrendo?

No MB eu somente implementei Serializable.

Vlw

Segue meu XML:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:rich="http://richfaces.org/rich">

<ui:composition template="/templates/principal.xhtml">
	<head>
		<meta http-equiv="content-Type" content="text/html; charset=utf-8"></meta>		
	</head>
	<body>
		<ui:define name="centro">						
				<f:subview id="subviewDepartamento">
					<rich:panel styleClass="panelPrincipal">
						<f:facet name="header"> <h:outputText value="Cadastro || Departamento" /> </f:facet>
						
						<rich:tabPanel styleClass="tabPanel" switchType="client" selectedTab="#{departamentoMB.selectedPanel}">
						
							<rich:tab label="Lista" id="tabLista" styleClass="background">	
								<a4j:outputPanel id="tabelaIndisponibilidade" ajaxRendered="true">     
					            <a4j:keepAlive beanName="departamentoMB" />
					            <h:form>
								<rich:toolBar>
									<a4j:commandButton action="#{departamentoMB.ler}" value="Localizar" reRender="departamentoLista"/>							
								</rich:toolBar>														
									<rich:dataTable value="#{departamentoMB.dmRegistros}" id="departamentoLista" rows="9" var="departamentos">
										 <a4j:support event="onkeyup" />
										<f:facet name="header">
											<rich:columnGroup>
												<rich:column>
													<h:outputText styleClass="headerText" value="Id" />
												</rich:column>
												<rich:column>
													<h:outputText value="Departamento" />
												</rich:column>
												<rich:column>
													<h:outputText value="Ação" />
												</rich:column>
											</rich:columnGroup>
										</f:facet>
										<rich:column width="70">
											<h:outputText value="#{departamentos.id}" />
										</rich:column>
										<rich:column width="660">
											<h:outputText value="#{departamentos.departamento}" />
										</rich:column>
										<rich:column width="50" align="center">
											<h:commandButton action="#{departamentoMB.atualizar}" title="Alterar" image="/imagens/ImagensUtilizadas/16x16/viewmag.png"/>
											<a4j:commandButton reRender="table" image="/imagens/ImagensUtilizadas/16x16/remove.png"
				                				   action="#{departamentoMB.marcaRemover}" title="Excluir" oncomplete="javascript:Richfaces.showModalPanel('panelModal');"/>                						      							      	
										</rich:column>
									</rich:dataTable>	
									<rich:datascroller align="left" for="departamentoLista" maxPages="20" id="ds1" />
									</h:form>
								</a4j:outputPanel>
							</rich:tab>
							
							<rich:tab label="Cadastro" id="tabDados" styleClass="background">
								<h:panelGrid columns="2">
									<h:outputText value="Departamento:" />
									<h:inputText value="#{departamentoMB.modelo.departamento}" />
								</h:panelGrid>
								<h:commandButton action="#{departamentoMB.inserir}" value="Incluir" />
								<h:commandButton action="#{departamentoMB.criar}" value="Salvar" />											
							</rich:tab>
							
						</rich:tabPanel>
						
					</rich:panel>						
				</f:subview>
      <rich:modalPanel id="panelModal" autosized="false" keepVisualState="false" width="350" height="200">
        	<f:facet name="header">
            	<h:outputText value="ATENÇÃO!"/>
            </f:facet>
            <f:facet name="controls">
            	<span style="cursor:pointer" onclick="javascript:Richfaces.hideModalPanel('panelModal')">X</span>
            </f:facet>
            <h:panelGroup layout="block" styleClass="scrolls">        
        	<h:form>
             	<br/><br/>
             	<h:outputText value="Você realmente deseja excluir esse registro?" style="color:Navy;text-align:center;font-size:medium;font-family:Arial;"/><br/>
             	<h:outputText value="Não será possível recuperá-lo posteriormente!" style="color:Navy;text-align:center;font-size:medium;font-family:Arial;"/><br/>
             	<br/>
             	<h:commandButton action="#{departamentoMB.excluir}" value="Excluir" />              
        	</h:form>
        	</h:panelGroup>
        </rich:modalPanel>        				
			
		</ui:define>
	</body>
</ui:composition>

</html>
dwduncan

seu código está assim:

&lt;rich:tab label="Lista" id="tabLista" styleClass="background"&gt;       
                                &lt;a4j:outputPanel id="tabelaIndisponibilidade" ajaxRendered="true"&gt;       
                                &lt;a4j:keepAlive beanName="departamentoMB" /&gt;   
                                &lt;h:form&gt;   
                                &lt;rich:toolBar&gt;   
                                    &lt;a4j:commandButton action="#{departamentoMB.ler}" value="Localizar" reRender="departamentoLista"/&gt;                               
                                &lt;/rich:toolBar&gt;                                                         
                                    &lt;rich:dataTable value="#{departamentoMB.dmRegistros}" id="departamentoLista" rows="9" var="departamentos"&gt;

tente assim, pois, me parece, da forma como está o keepAlive está fora do escopo de renderização:

&lt;rich:tab label="Lista" id="tabLista" styleClass="background"&gt;       
                                 
                                &lt;h:form&gt;   
                                &lt;rich:toolBar&gt;   
                                    &lt;a4j:commandButton action="#{departamentoMB.ler}" value="Localizar" reRender="departamentoLista"/&gt;                               
                                &lt;/rich:toolBar&gt; 
                                    &lt;a4j:outputPanel  id="departamentoLista"  ajaxRendered="true"&gt;       
                                    &lt;a4j:keepAlive beanName="departamentoMB" /&gt;                                                          
                                    &lt;rich:dataTable value="#{departamentoMB.dmRegistros}" rows="9" var="departamentos"&gt;

Fique atento aos detalhes, agora o keepAlive manterá seu bean “vivo” toda vez que algum reRender apontar para departamentoLista, e claro, não esqueça de realinhar adequadamente as tags de fechamento após esta alteração.

A

Olá amigo,

fiz as alterações, mas o problema continua.

Meu dataModel no MB está como transiente. seria por isso o problema? Mas se eu não coloca-lo assim aparece um erro ao compilar.

Segue meu XHTML alterado e meu MB:

Obrigado pela ajuda!

<rich:tab label="Lista" id="tabLista" styleClass="background">	
   <h:form>
	<rich:toolBar>
		<a4j:commandButton action="#{departamentoMB.ler}" value="Localizar"                                          
                             reRender="departamentoPanel"/>							

	</rich:toolBar>														

	<a4j:outputPanel id="departamentoPanel" ajaxRendered="true">     
            <a4j:keepAlive beanName="departamentoMB" />
   	    <rich:dataTable value="#{departamentoMB.dmRegistros}" rows="9" id="departamentoLista" var="departamentos">
	        <f:facet name="header">
		    <rich:columnGroup>
			<rich:column>
		 	    <h:outputText styleClass="headerText" value="Id" />
			</rich:column>
			<rich:column>
			    <h:outputText value="Departamento" />
			</rich:column>
			<rich:column>
			   <h:outputText value="Ação" />
			</rich:column>
		    </rich:columnGroup>
		 </f:facet>
		<rich:column width="70">
		   <h:outputText value="#{departamentos.id}" />
		</rich:column>
		<rich:column width="660">
		   <h:outputText value="#{departamentos.departamento}" />
		</rich:column>
		<rich:column width="50" align="center">
		   <a4j:commandButton action="#{departamentoMB.atualizar}" reRender="departamentoPanel"  title="Alterar" />
  		  <a4j:commandButton reRender="table" image="/imagens/ImagensUtilizadas/16x16/remove.png"
		         				 action="#{departamentoMB.marcaRemover}" title="Excluir"            oncomplete="javascript:Richfaces.showModalPanel('panelModal');"/>                						      			                       </rich:column>
	</rich:dataTable>	
	<rich:datascroller align="left" for="departamentoLista" reRender="departamentoPanel" maxPages="20" id="ds1" />
      </a4j:outputPanel>
   </h:form>								
</rich:tab>

Meu MB:

@SuppressWarnings("serial")
public class DepartamentoMB implements Serializable{
	Modelo modelo = new Departamento();
        protected transient DataModel dmRegistros;

	public void ler(){ 
    	try {
    	    EntityManagerFactory emf = EntityManagerProvider.getEntityManagerFactory();
    	    EntityManager em = emf.createEntityManager();
    		Query q = em.createQuery(sqlPesquisa + sqlOrdemPesquisa);
    		q.setMaxResults(maxRowsLer);
    		q.setHint("org.hibernate.cacheable", true);  
    		q.setHint("org.hibernate.cacheMode", CacheMode.NORMAL);
    	    List<Modelo> r = (ArrayList<Modelo>) q.getResultList();
    	    dmRegistros = new ListDataModel(r);

    	    em.close();
    	} catch (Exception e) {

    		e.printStackTrace();
    	}
}
dwduncan

Não posso afirmar categoricamente que o DataModel não pode ser transient, mas considerando que segundo a especificação da própria linguagem a qual diz que tudo marcado como transient ficará de fora da serialização acredito que este seja o problema, tente compilar sem o transient e post o erro, de qualquer forma não seria correto usar transient em algo sem o real propósito para o qual o transient foi feito.

A

Sem serializable aparece isso:

15:34:54,738 ERROR [viewhandler] Error Rendering View[/cadastro/departamento.xhtml]
java.io.NotSerializableException: javax.faces.model.ListDataModel
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at java.util.HashMap.writeObject(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor271.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeArray(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeArray(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeArray(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeArray(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeArray(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:269)
	at javax.faces.render.ResponseStateManager.writeState(ResponseStateManager.java:166)
	at org.ajax4jsf.application.AjaxStateManager.writeState(AjaxStateManager.java:294)
	at org.ajax4jsf.application.AjaxStateManager.writeState(AjaxStateManager.java:256)
	at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:620)
	at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
	at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
	at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
	at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
	at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
	at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
	at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
	at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Unknown Source)
dwduncan

Você implementou Serializable na sua classe Modelo ? DataModel “carrega” uma lista de objetos que precisam ser serializáveis.

dwduncan

Aqui está o promblema:

List&lt;Modelo&gt; r = (ArrayList&lt;Modelo&gt;) q.getResultList();   
            dmRegistros = new ListDataModel(r);

Modelo, tenho quase certeza não implementa Serializable!

A

A classe implementa!

Parece que o ListDataModel é que não pode ser serializado. Você utiliza o dataModel em suas listas?

A

Veja isso:

dwduncan

Com certeza ListDataModel é serializable, sim, eu uso ele de vez em quando. Dentro do Modelo existe alguma classe que não implemente Serializable ?

dwduncan

Mas isso é o próprio principio da linguagem, programe para interfaces. O que importa nesse caso não é o Tipo da variável e sim o Tipo do Objeto instanciado para esta variável.

dwduncan

Tente com um List, e veja se funciona.

A

Só para tirar essa duvida: criei uma classe MyListDataModel extendendo ListDataModel e a deixei como Serializable. O erro não ocorre mais!

Porém, o problema de clicar no botao atualizar e os dados sumirem continua, ou mesmo quando clico no scroller. :?

fabim

Vamos supor que vc tem uma pagina de pesquisa com 1000 acessos por minuto.

Vc tem CERTEZA que quer 1000x15 parametros (supondo que essa pagina de pesquisa tenha 15 filtros) carregados no seu servidor, até que os 1000 usuarios encerrem sua sessão? (o objeto session so morre depois disso)

Isso pra apenas 1 pagina de pesquisa.
Se os 1000 usuarios acessassem 10 paginas de pesquisas vc estaria na vala.

A

Olá fabim,

É isso mesmo que estou tentando evitar, colocando os MBs em escopo de request!

porém, estou com problemas para fazer o keepalive funcionar.

Criado 25 de maio de 2010
Ultima resposta 25 de mai. de 2010
Respostas 19
Participantes 5