Sei que o tema Session in View é muito comum e “teoricamente” resolvido.
Mas gostaria que compartilhássemos nossas estratégias e PQ utilizou.
Quando utilizava Struts usava o interceptadores para fazer isso e resolvia o meu problema plenamente.
Com JSF já tentei utilizar o extender a classe Filter do servelt. Entretanto ele abria uma sessão em toda requisição (ate para ler um .jpg por exemplo) o que, no meu ponto de vista, era muito custoso.
Atualmente utilizo phase-listener. Declaro no faces.config.xml a estrutura abaixo
<lifecycle>
<phase-listener>HibernatePhaseListener</phase-listener>
</lifecycle>
e implemento ela abaixo
public class HibernatePhaseListener implements PhaseListener {
private Logger logger = Logger.getLogger(HibernatePhaseListener.class.getCanonicalName());
@Override
public void afterPhase(PhaseEvent phaseEvent) {
try {
HttpServletResponse response = (HttpServletResponse) phaseEvent.getFacesContext().getExternalContext().getResponse();
if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE
|| (phaseEvent.getPhaseId() == PhaseId.INVOKE_APPLICATION && response.getContentType() != null)) {
if (HibernateUtil.transactionIsActive()) {
HibernateUtil.commitTransaction();
}
}
} catch (Exception e) {
HibernateUtil.rollbackTransaction();
final FacesContext fc = FacesContext.getCurrentInstance();
final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
final NavigationHandler nav = fc.getApplication().getNavigationHandler();
if (HibernateUtil.transactionIsActive())
HibernateUtil.commitTransaction();
logger.log(Level.FATAL, "Critical Exception!", e);
requestMap.put("stackTrace", stack2string(e));
requestMap.put("exceptionMessage", "Cause: " + e.getCause() + "<br/>LocalizedMessage: " + e.getLocalizedMessage()
+ "<br/>Message: " + e.getMessage());
String erroPage = "/pages/erro/erro.xhtml";
if (PropertiesLoader.getValor("conf.erroPage") != null)
erroPage = PropertiesLoader.getValor("conf.erroPage");
nav.handleNavigation(fc, null, erroPage);
fc.renderResponse();
} finally {
if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE)
HibernateUtil.closeSession();
}
}
@Override
public void beforePhase(PhaseEvent phaseEvent) {
if (phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW) {
if (!HibernateUtil.transactionIsActive()) {
HibernateUtil.beginTransaction();
}
}
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
private static String stack2string(Throwable t) {
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
return sw.toString();
} catch (Exception e2) {
return "bad stack2string";
}
}
}
Mas eu acho que ainda é aberta algumas vezes sem necessidade (tipo: alguma requisição qualquer que não seja um método java)
Qual a solução que vocês utilizam ?