1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.orchestra.conversation.servlet;
20
21 import org.apache.myfaces.orchestra.conversation.ConversationManager;
22 import org.apache.myfaces.orchestra.conversation.ConversationWiperThread;
23
24 import javax.servlet.ServletContextEvent;
25 import javax.servlet.ServletContextListener;
26 import javax.servlet.http.HttpSessionAttributeListener;
27 import javax.servlet.http.HttpSessionBindingEvent;
28 import javax.servlet.http.HttpSessionListener;
29 import javax.servlet.http.HttpSessionEvent;
30
31 /***
32 * An http session listener which periodically scans every http session for
33 * conversations and conversation contexts that have exceeded their timeout.
34 * <p>
35 * If a web application wants to configure a conversation timeout that is
36 * shorter than the http session timeout, then this class must be specified
37 * as a listener in the web.xml file.
38 * <p>
39 * A conversation timeout is useful because the session timeout is refreshed
40 * every time a request is made. If a user starts a conversation that uses
41 * lots of memory, then abandons it and starts working elsewhere in the same
42 * webapp then the session will continue to live, and therefore so will that
43 * old "unused" conversation. Specifying a conversation timeout allows the
44 * memory for that conversation to be reclaimed in this situation.
45 * <p>
46 * This listener starts a single background thread that periodically wakes
47 * up and scans all http sessions to find ConversationContext objects, and
48 * checks their timeout together with the timeout for all Conversations in
49 * that context. If a conversation or context timeout has expired then it
50 * is removed.
51 * <p>
52 * This code is probably not safe for use with distributed sessions, ie
53 * a "clustered" web application setup.
54 * <p>
55 * See {@link org.apache.myfaces.orchestra.conversation.ConversationWiperThread}
56 * for more details.
57 */
58 public class ConversationManagerSessionListener
59 implements HttpSessionAttributeListener, ServletContextListener, HttpSessionListener
60 {
61 private final static long DEFAULT_CHECK_TIME = 5 * 60 * 1000;
62
63 private final static String CHECK_TIME = "org.apache.myfaces.orchestra.WIPER_THREAD_CHECK_TIME";
64
65 private ConversationWiperThread conversationWiperThread;
66
67 public void contextInitialized(ServletContextEvent event)
68 {
69 long checkTime = DEFAULT_CHECK_TIME;
70 String checkTimeString = event.getServletContext().getInitParameter(CHECK_TIME);
71 if (checkTimeString != null)
72 {
73 checkTime = Long.parseLong(checkTimeString);
74 }
75
76 conversationWiperThread = new ConversationWiperThread(checkTime);
77 conversationWiperThread.start();
78 }
79
80 public void contextDestroyed(ServletContextEvent event)
81 {
82 conversationWiperThread.interrupt();
83 conversationWiperThread = null;
84 }
85
86 public void attributeAdded(HttpSessionBindingEvent event)
87 {
88 if (event.getValue() instanceof ConversationManager)
89 {
90 conversationWiperThread.addConversationManager(
91 event.getSession().getId(),
92 (ConversationManager) event.getValue());
93 }
94 }
95
96 public void attributeRemoved(HttpSessionBindingEvent event)
97 {
98 if (event.getValue() instanceof ConversationManager)
99 {
100 conversationWiperThread.removeConversationManager(event.getSession().getId());
101 }
102 }
103
104 public void attributeReplaced(HttpSessionBindingEvent event)
105 {
106 if (event.getValue() instanceof ConversationManager)
107 {
108 conversationWiperThread.addConversationManager(
109 event.getSession().getId(),
110 (ConversationManager) event.getValue());
111 }
112 }
113
114 public void sessionCreated(HttpSessionEvent event)
115 {
116 }
117
118 public void sessionDestroyed(HttpSessionEvent event)
119 {
120
121 conversationWiperThread.removeConversationManager(event.getSession().getId());
122 }
123 }