Better session timeout handling for detail edit.

version2
tim holloway 3 months ago
parent d1930a1a66
commit 95ceb82eed
  1. 12
      pom.xml
  2. 11
      src/main/java/com/mousetech/gourmetj/CookieBean.java
  3. 16
      src/main/java/com/mousetech/gourmetj/JSFUtils.java
  4. 4
      src/main/java/com/mousetech/gourmetj/SpringPrimeFacesApplication.java
  5. 14
      src/main/java/com/mousetech/gourmetj/UserSession.java
  6. 78
      src/main/resources/META-INF/resources/detailEdit.xhtml

@ -122,12 +122,14 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- <dependency> <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<groupId>jakarta.servlet.jsp</groupId> <dependency>
<artifactId>jakarta.servlet.jsp-api</artifactId> <groupId>jakarta.servlet</groupId>
<version>2.3.3</version> <artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency>--> </dependency>
<!-- <dependency> <!-- <dependency>
<groupId>jakarta.servlet</groupId> <groupId>jakarta.servlet</groupId>
<artifactId>jstl</artifactId> <artifactId>jstl</artifactId>

@ -124,4 +124,15 @@ public class CookieBean {
public void setDisplayListSize(Integer value) { public void setDisplayListSize(Integer value) {
cookieMap.put(KEY_DISPLAY_ROWS, String.valueOf(value)); cookieMap.put(KEY_DISPLAY_ROWS, String.valueOf(value));
} }
public void sessionIdleListener() {
log.warn("Session Idle Listener fired.");
JSFUtils.addWarningMessage("Timeout approaching. Save your work!");
}
public void sessionTimeout() {
log.warn("Session Timeout Listener fired.");
JSFUtils.logout();
}
} }

@ -12,6 +12,7 @@ import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext; import jakarta.faces.context.FacesContext;
import jakarta.faces.context.Flash; import jakarta.faces.context.Flash;
import jakarta.servlet.http.Cookie; import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -148,5 +149,20 @@ public class JSFUtils {
getExternalContext().addResponseCookie(name, getExternalContext().addResponseCookie(name,
URLEncoder.encode(value, "UTF-8"), URLEncoder.encode(value, "UTF-8"),
properties); properties);
}
/**
* Destroy current session, logging user out.
*/
public static void logout() {
log.warn("Logging out session");
jakarta.servlet.http.HttpSession session =
(HttpSession) getExternalContext().getSession(false);
if ( session != null ) {
session.invalidate();
} else {
log.warn("Session did not exist.");
}
} }
} }

@ -10,18 +10,20 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar; import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry; import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@SpringBootApplication @SpringBootApplication
@ServletComponentScan
@EntityScan(value = { @EntityScan(value = {
"com.mousetech.gourmetj.persistence.model" }) "com.mousetech.gourmetj.persistence.model" })
public class SpringPrimeFacesApplication { public class SpringPrimeFacesApplication {
final String errorPage = "/error/error.html"; final String errorPage = "/error/error.html";
final String error404Page = "/error/error404.html"; final String error404Page = "/error/error404.html";
final String expiredPage = "/error/viewExpired.xhtml"; final String expiredPage = "/main.xhtml";
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(SpringPrimeFacesApplication.class, SpringApplication.run(SpringPrimeFacesApplication.class,

@ -164,20 +164,6 @@ public class UserSession implements Serializable {
*/ */
private List<Recipe> shoppingList = new ArrayList<Recipe>(); private List<Recipe> shoppingList = new ArrayList<Recipe>();
/**
* @return the sessionTimeoutInterval, msec
*/
public long getSessionTimeoutInterval() {
return 5000L; //sessionTimeoutInterval;
}
public void sessionIdleListener() {
log.warn("Session Idle Listener fired.");
JSFUtils.addWarningMessage("Timeout approaching. Save your work!");
// PrimeFaces.current()
// .executeScript("sessionExpiredConfirmation.show()");
}
public String logoutAction() { public String logoutAction() {
log.warn("Session Idle listener logout"); log.warn("Session Idle listener logout");
return goHome(); return goHome();

@ -15,13 +15,14 @@
<h:outputScript name="js/scrolltable.js" /> <h:outputScript name="js/scrolltable.js" />
<style> <style>
.deDescl { .deDescl {
width: 15em; width: 15em;
text-align: left; text-align: left;
} }
.deDescr { .deDescr {
text-align: left; text-align: left;
} }
.ingSel { .ingSel {
width: 3em; width: 3em;
text-align: center; text-align: center;
@ -54,7 +55,9 @@
<p:tab id="overviewTab" <p:tab id="overviewTab"
title="Description" title="Description"
> >
<p:panelGrid columns="2" columnClasses="deDescl, deDescr"> <p:panelGrid columns="2"
columnClasses="deDescl, deDescr"
>
<f:facet name="header">Description</f:facet> <f:facet name="header">Description</f:facet>
<p:outputLabel for="@next" <p:outputLabel for="@next"
value="Title" value="Title"
@ -149,13 +152,15 @@
rows="10" cols="45" rows="10" cols="45"
value="#{recipeDetailBean.recipe.description}" value="#{recipeDetailBean.recipe.description}"
/> />
</p:panelGrid> </p:panelGrid>
<p:panel id="picPanel"> <p:panel id="picPanel">
<img id="bigPix" <img id="bigPix"
src="/img/picture/?dt=#{recipeDetailBean.currentTime}" src="/img/picture/?dt=#{recipeDetailBean.currentTime}"
/> />
</p:panel> </p:panel>
<p:panelGrid id="picButtonPanel" columns="2"> <p:panelGrid id="picButtonPanel"
columns="2"
>
<p:fileUpload id="ctlUpload" <p:fileUpload id="ctlUpload"
label="Upload Image" label="Upload Image"
listener="#{recipeDetailBean.ajaxUploadImage}" listener="#{recipeDetailBean.ajaxUploadImage}"
@ -165,14 +170,14 @@
auto="true" auto="true"
sizeLimit="1000000" sizeLimit="1000000"
allowTypes="/(\.|\/)(gif|jpe?g|png|webp)$/" allowTypes="/(\.|\/)(gif|jpe?g|png|webp)$/"
/> />
<p:commandButton id="ctlDelImg" <p:commandButton id="ctlDelImg"
value="Delete Image" value="Delete Image"
action="#{recipeDetailBean.ajaxDeleteImage}" action="#{recipeDetailBean.ajaxDeleteImage}"
update="picPanel" update="picPanel"
immediate="true" immediate="true"
/> />
</p:panelGrid> </p:panelGrid>
</p:tab> </p:tab>
<p:tab id="ingredientsTab" <p:tab id="ingredientsTab"
title="Ingredients" title="Ingredients"
@ -396,23 +401,28 @@
action="recipeDetails.jsf" action="recipeDetails.jsf"
/> />
<p:commandButton id="doHome" value="Home" <p:commandButton id="doHome" value="Home"
icon="ui-icon-home" icon="ui-icon-home" ajax="false"
ajax="false" immediate="true" immediate="true" action="main.jsf"
action="main.jsf" />
/>
</h:form> </h:form>
</p:panel> </p:panel>
<!-- --> <!-- Note timeouts must be less than
<p:growl id="growl" showDetail="true" /> session timeout in application properties-->
<p:growl id="growl" showDetail="true" sticky="true" />
<h:form id="frmTimeout"> <h:form id="frmTimeout">
<p:idleMonitor <p:idleMonitor timeout="1500000">
timeout="#{userSession.sessionTimeoutInterval}" <p:ajax id="ajaxIdle" event="idle"
> listener="#{cookieBean.sessionIdleListener}"
<p:ajax id="ajaxIdle" event="idle" update="growl"
listener="#{userSession.sessionIdleListener}" />
update="growl" </p:idleMonitor>
/> <p:idleMonitor timeout="1900000">
</p:idleMonitor> <p:ajax id="ajaxIdle" event="idle"
listener="#{cookieBean.sessionTimeout}"
update="growl"
oncomplete="window.location='#{request.contextPath}/main.jsf'"
/>
</p:idleMonitor>
</h:form> </h:form>
<!-- --> <!-- -->
<p:dialog id="addGroupDlg" widgetVar="addGroupDlg"> <p:dialog id="addGroupDlg" widgetVar="addGroupDlg">
@ -444,7 +454,9 @@
<p:dialog id="editShopcatDlg" <p:dialog id="editShopcatDlg"
widgetVar="editShopcatDlg" widgetVar="editShopcatDlg"
> >
<ui:include src="/WEB-INF/layout/dialog/editShopcat.xhtml" /> <ui:include
src="/WEB-INF/layout/dialog/editShopcat.xhtml"
/>
</p:dialog> </p:dialog>
</ui:define> </ui:define>
</ui:composition> </ui:composition>

Loading…
Cancel
Save