Commit 02b5874da1b080651ecfb6999845812934499d2f
1 parent
0c349ba8
Exists in
master
[FWK-232] Correção para problema de beans com escopo @ViewScoped sendo
imediatamente destruído ao trocar de visão, causando nova construção do bean caso a visão antiga seja acessada após uma nova visão ser criada.
Showing
13 changed files
with
558 additions
and
110 deletions
Show diff stats
archetype/html-rest/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml
@@ -15,6 +15,12 @@ | @@ -15,6 +15,12 @@ | ||
15 | <listener> | 15 | <listener> |
16 | <listener-class>br.gov.frameworkdemoiselle.util.ServletListener</listener-class> | 16 | <listener-class>br.gov.frameworkdemoiselle.util.ServletListener</listener-class> |
17 | </listener> | 17 | </listener> |
18 | + <listener> | ||
19 | + <listener-class>br.gov.frameworkdemoiselle.util.SessionListener</listener-class> | ||
20 | + </listener> | ||
21 | + <listener> | ||
22 | + <listener-class>br.gov.frameworkdemoiselle.util.RequestListener</listener-class> | ||
23 | + </listener> | ||
18 | <filter> | 24 | <filter> |
19 | <filter-name>Demoiselle Servlet Filter</filter-name> | 25 | <filter-name>Demoiselle Servlet Filter</filter-name> |
20 | <filter-class>br.gov.frameworkdemoiselle.util.ServletFilter</filter-class> | 26 | <filter-class>br.gov.frameworkdemoiselle.util.ServletFilter</filter-class> |
archetype/jsf-jpa/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml
@@ -21,6 +21,9 @@ | @@ -21,6 +21,9 @@ | ||
21 | <listener> | 21 | <listener> |
22 | <listener-class>br.gov.frameworkdemoiselle.util.SessionListener</listener-class> | 22 | <listener-class>br.gov.frameworkdemoiselle.util.SessionListener</listener-class> |
23 | </listener> | 23 | </listener> |
24 | + <listener> | ||
25 | + <listener-class>br.gov.frameworkdemoiselle.util.RequestListener</listener-class> | ||
26 | + </listener> | ||
24 | <filter> | 27 | <filter> |
25 | <filter-name>Demoiselle Servlet Filter</filter-name> | 28 | <filter-name>Demoiselle Servlet Filter</filter-name> |
26 | <filter-class>br.gov.frameworkdemoiselle.util.ServletFilter</filter-class> | 29 | <filter-class>br.gov.frameworkdemoiselle.util.ServletFilter</filter-class> |
impl/extension/jsf/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/JsfBootstrap.java
@@ -48,14 +48,11 @@ import br.gov.frameworkdemoiselle.util.Beans; | @@ -48,14 +48,11 @@ import br.gov.frameworkdemoiselle.util.Beans; | ||
48 | 48 | ||
49 | public class JsfBootstrap implements Extension { | 49 | public class JsfBootstrap implements Extension { |
50 | 50 | ||
51 | - //private List<CustomContext> customContexts = new ArrayList<CustomContext>(); | ||
52 | - | ||
53 | - //private AfterBeanDiscovery afterBeanDiscoveryEvent; | ||
54 | - | ||
55 | private FacesViewContextImpl context; | 51 | private FacesViewContextImpl context; |
52 | + | ||
56 | private boolean contextActivatedHere; | 53 | private boolean contextActivatedHere; |
57 | - | ||
58 | - public void createCustomContext(@Observes AfterBeanDiscovery event){ | 54 | + |
55 | + public void createCustomContext(@Observes AfterBeanDiscovery event) { | ||
59 | context = new FacesViewContextImpl(); | 56 | context = new FacesViewContextImpl(); |
60 | event.addContext(context); | 57 | event.addContext(context); |
61 | } | 58 | } |
@@ -63,19 +60,18 @@ public class JsfBootstrap implements Extension { | @@ -63,19 +60,18 @@ public class JsfBootstrap implements Extension { | ||
63 | public void addContexts(@Observes final AfterDeploymentValidation event) { | 60 | public void addContexts(@Observes final AfterDeploymentValidation event) { |
64 | CustomContextProducer producer = Beans.getReference(CustomContextProducer.class); | 61 | CustomContextProducer producer = Beans.getReference(CustomContextProducer.class); |
65 | producer.addRegisteredContext(context); | 62 | producer.addRegisteredContext(context); |
66 | - | ||
67 | - //Ativa o ViewContext | ||
68 | - if (!context.isActive()){ | 63 | + |
64 | + // Ativa o ViewContext | ||
65 | + if (!context.isActive()) { | ||
69 | contextActivatedHere = context.activate(); | 66 | contextActivatedHere = context.activate(); |
70 | - } | ||
71 | - else{ | 67 | + } else { |
72 | contextActivatedHere = false; | 68 | contextActivatedHere = false; |
73 | } | 69 | } |
74 | } | 70 | } |
75 | 71 | ||
76 | public void removeContexts(@Observes AfterShutdownProccess event) { | 72 | public void removeContexts(@Observes AfterShutdownProccess event) { |
77 | - //Desativa o ViewContext | ||
78 | - if (contextActivatedHere){ | 73 | + // Desativa o ViewContext |
74 | + if (contextActivatedHere) { | ||
79 | context.deactivate(); | 75 | context.deactivate(); |
80 | } | 76 | } |
81 | } | 77 | } |
impl/extension/jsf/src/main/java/br/gov/frameworkdemoiselle/internal/context/FacesViewBeanStore.java
1 | package br.gov.frameworkdemoiselle.internal.context; | 1 | package br.gov.frameworkdemoiselle.internal.context; |
2 | 2 | ||
3 | import java.io.Serializable; | 3 | import java.io.Serializable; |
4 | +import java.util.Iterator; | ||
5 | +import java.util.Map.Entry; | ||
6 | +import java.util.concurrent.ConcurrentHashMap; | ||
4 | 7 | ||
5 | import javax.enterprise.context.spi.Contextual; | 8 | import javax.enterprise.context.spi.Contextual; |
6 | import javax.enterprise.context.spi.CreationalContext; | 9 | import javax.enterprise.context.spi.CreationalContext; |
7 | -import javax.enterprise.inject.Alternative; | 10 | + |
11 | +import br.gov.frameworkdemoiselle.context.ViewContext; | ||
12 | +import br.gov.frameworkdemoiselle.util.ResourceBundle; | ||
8 | 13 | ||
9 | /** | 14 | /** |
10 | - * Store that keeps view scoped beans. It associates all view scoped beans with a view ID. | ||
11 | - * When the ID changes (meaning the view changed) all old view scoped beans are destroyed | ||
12 | - * before new beans for the new view are created and stored. | 15 | + * Store that keeps view scoped beans. It associates all view scoped beans with a view ID. When the ID changes (meaning |
16 | + * the view changed) all old view scoped beans are destroyed before new beans for the new view are created and stored. | ||
13 | * | 17 | * |
14 | * @author SERPRO | 18 | * @author SERPRO |
15 | - * | ||
16 | */ | 19 | */ |
17 | -@Alternative | ||
18 | public class FacesViewBeanStore implements Serializable { | 20 | public class FacesViewBeanStore implements Serializable { |
19 | 21 | ||
20 | private static final long serialVersionUID = -8265458933971929432L; | 22 | private static final long serialVersionUID = -8265458933971929432L; |
21 | 23 | ||
22 | - private Long lastViewId = null; | 24 | + private final ConcurrentHashMap<Long, FacesViewData> viewStore = new ConcurrentHashMap<Long, FacesViewBeanStore.FacesViewData>(); |
25 | + | ||
26 | + private long maxInactiveTimeInSeconds; | ||
23 | 27 | ||
24 | - private BeanStore store; | 28 | + public FacesViewBeanStore(long maxInactiveTimeInSeconds) { |
29 | + this.maxInactiveTimeInSeconds = maxInactiveTimeInSeconds; | ||
30 | + } | ||
25 | 31 | ||
26 | - synchronized BeanStore getStore(Long viewId, AbstractCustomContext context) { | ||
27 | - if (lastViewId == null || !lastViewId.equals(viewId)) { | ||
28 | - clear(context); | ||
29 | - lastViewId = viewId; | ||
30 | - store = AbstractCustomContext.createStore(); | 32 | + /** |
33 | + * Gets the store that contains the view scoped beans for that view ID. If no store exists (new view) one is | ||
34 | + * created. | ||
35 | + * | ||
36 | + * @param viewId | ||
37 | + * ID of the current view | ||
38 | + * @param context | ||
39 | + * Reference to the {@link ViewContext} class managing the view scope | ||
40 | + * @return The {@link BeanStore} that stores view scoped beans for this view ID | ||
41 | + * @throws IllegalStateException | ||
42 | + * if the view associated with the requested view ID has expired | ||
43 | + */ | ||
44 | + public BeanStore getStoreForView(Long viewId, AbstractCustomContext context) { | ||
45 | + FacesViewData data = null; | ||
46 | + synchronized (viewStore) { | ||
47 | + data = viewStore.get(viewId); | ||
48 | + if (data == null) { | ||
49 | + BeanStore store = AbstractCustomContext.createStore(); | ||
50 | + data = new FacesViewData(); | ||
51 | + data.store = store; | ||
52 | + viewStore.put(viewId, data); | ||
53 | + } else if (data.isExpired(maxInactiveTimeInSeconds)) { | ||
54 | + throw new IllegalStateException(ResourceBundle.getBundle("demoiselle-jsf-bundle").getString( | ||
55 | + "view-expired")); | ||
56 | + } | ||
31 | } | 57 | } |
32 | 58 | ||
33 | - return store; | 59 | + data.lastTimeAccessed = System.currentTimeMillis(); |
60 | + return data.store; | ||
34 | } | 61 | } |
35 | 62 | ||
63 | + /** | ||
64 | + * @see #destroyStoresInSession(AbstractCustomContext, boolean) | ||
65 | + */ | ||
66 | + public void destroyStoresInSession(AbstractCustomContext context) { | ||
67 | + destroyStoresInSession(context, false); | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * Destroys all View scoped beans and the associated {@link BeanStore} for this user's session. The destroyed beans | ||
72 | + * will respect CDI bean lifecycle, thus they'll trigger any events associated with destroying beans. | ||
73 | + * | ||
74 | + * @param context | ||
75 | + * ViewContext managing the view scoped beans | ||
76 | + * @param onlyExpired | ||
77 | + * Only destroy beans if the underlying view has expired | ||
78 | + */ | ||
36 | @SuppressWarnings({ "rawtypes", "unchecked" }) | 79 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
37 | - public void clear(AbstractCustomContext context) { | ||
38 | - if (store != null) { | ||
39 | - for (String id : store) { | ||
40 | - Contextual contextual = context.getContextualStore().getContextual(id); | ||
41 | - Object instance = store.getInstance(id); | ||
42 | - CreationalContext creationalContext = store.getCreationalContext(id); | ||
43 | - | ||
44 | - if (contextual != null && instance != null) { | ||
45 | - contextual.destroy(instance, creationalContext); | 80 | + public void destroyStoresInSession(final AbstractCustomContext context, final boolean onlyExpired) { |
81 | + for (Iterator<Entry<Long, FacesViewData>> it = viewStore.entrySet().iterator(); it.hasNext();) { | ||
82 | + Entry<Long, FacesViewData> currentEntry = it.next(); | ||
83 | + FacesViewData data = currentEntry.getValue(); | ||
84 | + | ||
85 | + if (data != null && data.store != null) { | ||
86 | + if (!onlyExpired || data.isExpired(maxInactiveTimeInSeconds)) { | ||
87 | + for (String id : data.store) { | ||
88 | + Contextual contextual = context.getContextualStore().getContextual(id); | ||
89 | + Object instance = data.store.getInstance(id); | ||
90 | + CreationalContext creationalContext = data.store.getCreationalContext(id); | ||
91 | + | ||
92 | + if (contextual != null && instance != null) { | ||
93 | + contextual.destroy(instance, creationalContext); | ||
94 | + } | ||
95 | + } | ||
96 | + | ||
97 | + data.store.clear(); | ||
98 | + it.remove(); | ||
46 | } | 99 | } |
47 | } | 100 | } |
48 | - store.clear(); | 101 | + } |
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * Contains a {@link BeanStore} with some metadata, like the last time this store was accessed (used to determine | ||
106 | + * when a store expires). | ||
107 | + * | ||
108 | + * @author serpro | ||
109 | + */ | ||
110 | + private static class FacesViewData { | ||
111 | + | ||
112 | + long lastTimeAccessed; | ||
113 | + | ||
114 | + BeanStore store; | ||
115 | + | ||
116 | + public synchronized boolean isExpired(long viewTimeoutInSeconds) { | ||
117 | + return ((System.currentTimeMillis() - lastTimeAccessed) / 1000) > viewTimeoutInSeconds; | ||
49 | } | 118 | } |
50 | } | 119 | } |
51 | } | 120 | } |
impl/extension/jsf/src/main/java/br/gov/frameworkdemoiselle/internal/context/FacesViewContextImpl.java
@@ -46,133 +46,193 @@ import javax.enterprise.event.Observes; | @@ -46,133 +46,193 @@ import javax.enterprise.event.Observes; | ||
46 | import javax.enterprise.inject.Alternative; | 46 | import javax.enterprise.inject.Alternative; |
47 | import javax.faces.component.UIViewRoot; | 47 | import javax.faces.component.UIViewRoot; |
48 | import javax.faces.context.FacesContext; | 48 | import javax.faces.context.FacesContext; |
49 | +import javax.servlet.ServletRequest; | ||
50 | +import javax.servlet.http.HttpServletRequest; | ||
49 | import javax.servlet.http.HttpSession; | 51 | import javax.servlet.http.HttpSession; |
50 | 52 | ||
51 | import br.gov.frameworkdemoiselle.annotation.Priority; | 53 | import br.gov.frameworkdemoiselle.annotation.Priority; |
52 | import br.gov.frameworkdemoiselle.context.ViewContext; | 54 | import br.gov.frameworkdemoiselle.context.ViewContext; |
55 | +import br.gov.frameworkdemoiselle.lifecycle.BeforeRequestDestroyed; | ||
53 | import br.gov.frameworkdemoiselle.lifecycle.BeforeSessionDestroyed; | 56 | import br.gov.frameworkdemoiselle.lifecycle.BeforeSessionDestroyed; |
54 | import br.gov.frameworkdemoiselle.lifecycle.ViewScoped; | 57 | import br.gov.frameworkdemoiselle.lifecycle.ViewScoped; |
55 | import br.gov.frameworkdemoiselle.util.Beans; | 58 | import br.gov.frameworkdemoiselle.util.Beans; |
56 | import br.gov.frameworkdemoiselle.util.Faces; | 59 | import br.gov.frameworkdemoiselle.util.Faces; |
57 | 60 | ||
58 | /** | 61 | /** |
59 | - * | ||
60 | - * This {@link ViewContext} implementation uses a map provided | ||
61 | - * by {@link UIViewRoot#getViewMap()} as a store. Any beans stored on | ||
62 | - * this store are kept as long as the view is still active. | 62 | + * This {@link ViewContext} implementation uses a map provided by {@link UIViewRoot#getViewMap()} as a store. Any beans |
63 | + * stored on this store are kept as long as the view is still active. | ||
63 | * | 64 | * |
64 | * @author serpro | 65 | * @author serpro |
65 | - * | ||
66 | */ | 66 | */ |
67 | @Priority(Priority.L2_PRIORITY) | 67 | @Priority(Priority.L2_PRIORITY) |
68 | @Alternative | 68 | @Alternative |
69 | public class FacesViewContextImpl extends AbstractCustomContext implements ViewContext { | 69 | public class FacesViewContextImpl extends AbstractCustomContext implements ViewContext { |
70 | - | 70 | + |
71 | private final AtomicLong atomicLong = new AtomicLong(); | 71 | private final AtomicLong atomicLong = new AtomicLong(); |
72 | - | ||
73 | - private ConcurrentHashMap<String, FacesViewBeanStore> sessionBeanStore = new ConcurrentHashMap<String, FacesViewBeanStore>(); | ||
74 | - | 72 | + |
73 | + // Armazena todas as views relacionadas à sessão atual. Quando uma sessão | ||
74 | + // termina, o store correspondente é destruído. | ||
75 | + private ConcurrentHashMap<String, FacesViewBeanStore> viewStoreInSession = new ConcurrentHashMap<String, FacesViewBeanStore>(); | ||
76 | + | ||
75 | private static final String FACES_KEY = FacesViewContextImpl.class.getCanonicalName(); | 77 | private static final String FACES_KEY = FacesViewContextImpl.class.getCanonicalName(); |
76 | - | 78 | + |
77 | public FacesViewContextImpl() { | 79 | public FacesViewContextImpl() { |
78 | super(ViewScoped.class); | 80 | super(ViewScoped.class); |
79 | } | 81 | } |
80 | - | 82 | + |
81 | @Override | 83 | @Override |
82 | protected boolean isStoreInitialized() { | 84 | protected boolean isStoreInitialized() { |
83 | - return FacesContext.getCurrentInstance()!=null && getSessionId()!=null; | 85 | + return FacesContext.getCurrentInstance() != null && getSessionId() != null; |
84 | } | 86 | } |
85 | 87 | ||
86 | @Override | 88 | @Override |
87 | protected BeanStore getStore() { | 89 | protected BeanStore getStore() { |
88 | String sessionId = getSessionId(); | 90 | String sessionId = getSessionId(); |
89 | - if (sessionId == null){ | 91 | + if (sessionId == null) { |
90 | return null; | 92 | return null; |
91 | } | 93 | } |
92 | - | 94 | + |
93 | /* | 95 | /* |
94 | - * Tenta obter o viewID de forma não thread-safe por questões de performance. | ||
95 | - * Se o viewID não existe entra em um trecho thread-safe para incrementa-lo, evitando | ||
96 | - * conflito entre duas requests tentando incrementar esse número. | 96 | + * Tenta obter o viewID de forma não thread-safe por questões de performance. Se o viewID não existe entra em um |
97 | + * trecho thread-safe para incrementa-lo, evitando conflito entre duas requests tentando incrementar esse | ||
98 | + * número. | ||
97 | */ | 99 | */ |
98 | - Long viewId = (Long)Faces.getViewMap().get(FACES_KEY); | ||
99 | - if (viewId==null){ | 100 | + Long viewId = (Long) Faces.getViewMap().get(FACES_KEY); |
101 | + if (viewId == null) { | ||
100 | synchronized (this) { | 102 | synchronized (this) { |
101 | - | ||
102 | - //Tenta obte-lo novamente, caso entre a primeira tentativa e o bloqueio | ||
103 | - //da thread outra thread já tenha criado o número. | ||
104 | - viewId = (Long)Faces.getViewMap().get(FACES_KEY); | ||
105 | - if (viewId==null){ | 103 | + |
104 | + // Tenta obte-lo novamente, caso entre a primeira tentativa e o | ||
105 | + // bloqueio | ||
106 | + // da thread outra thread já tenha criado o número. | ||
107 | + viewId = (Long) Faces.getViewMap().get(FACES_KEY); | ||
108 | + if (viewId == null) { | ||
106 | viewId = atomicLong.incrementAndGet(); | 109 | viewId = atomicLong.incrementAndGet(); |
107 | Faces.getViewMap().put(FACES_KEY, viewId); | 110 | Faces.getViewMap().put(FACES_KEY, viewId); |
108 | } | 111 | } |
109 | } | 112 | } |
110 | } | 113 | } |
111 | 114 | ||
112 | - //A mesma técnica de bloqueio de thread acima é usada aqui para | ||
113 | - //criar um SessionBeanStore caso o mesmo ainda não exista. | ||
114 | - FacesViewBeanStore currentStore = sessionBeanStore.get(sessionId); | ||
115 | - if (currentStore==null){ | 115 | + // A mesma técnica de bloqueio de thread acima é usada aqui para |
116 | + // criar um FacesViewBeanStore caso o mesmo ainda não exista, e | ||
117 | + // associa-lo à sessão atual. | ||
118 | + FacesViewBeanStore currentViewStore = viewStoreInSession.get(sessionId); | ||
119 | + if (currentViewStore == null) { | ||
116 | synchronized (this) { | 120 | synchronized (this) { |
117 | - currentStore = (FacesViewBeanStore) sessionBeanStore.get(sessionId); | ||
118 | - if (currentStore==null){ | ||
119 | - currentStore = new FacesViewBeanStore(); | ||
120 | - sessionBeanStore.put(sessionId, currentStore); | 121 | + currentViewStore = (FacesViewBeanStore) viewStoreInSession.get(sessionId); |
122 | + if (currentViewStore == null) { | ||
123 | + currentViewStore = new FacesViewBeanStore(getSessionTimeout()); | ||
124 | + viewStoreInSession.put(sessionId, currentViewStore); | ||
121 | } | 125 | } |
122 | } | 126 | } |
123 | } | 127 | } |
124 | 128 | ||
125 | - return currentStore.getStore(viewId, this); | 129 | + return currentViewStore.getStoreForView(viewId, this); |
126 | } | 130 | } |
127 | - | 131 | + |
128 | /* | 132 | /* |
129 | * Called before the session is invalidated for that user. | 133 | * Called before the session is invalidated for that user. |
130 | * Destroys all view scoped beans stored on that session. | 134 | * Destroys all view scoped beans stored on that session. |
131 | */ | 135 | */ |
132 | - private void clearInvalidatedSession(String sessionId){ | ||
133 | - if (sessionId != null){ | ||
134 | - final FacesViewBeanStore store = sessionBeanStore.get(sessionId); | ||
135 | - if (store!=null){ | ||
136 | - store.clear(this); | ||
137 | - sessionBeanStore.remove(sessionId); | 136 | + private void clearInvalidatedSession(String sessionId) { |
137 | + if (sessionId != null) { | ||
138 | + final FacesViewBeanStore store = viewStoreInSession.get(sessionId); | ||
139 | + if (store != null) { | ||
140 | + store.destroyStoresInSession(this); | ||
141 | + viewStoreInSession.remove(sessionId); | ||
142 | + } | ||
143 | + } | ||
144 | + } | ||
145 | + | ||
146 | + /* | ||
147 | + * Called at each new request at a given session. | ||
148 | + * Destroys any expired views. | ||
149 | + */ | ||
150 | + private synchronized void clearExpiredViews(String sessionId) { | ||
151 | + if (sessionId != null) { | ||
152 | + final FacesViewBeanStore store = viewStoreInSession.get(sessionId); | ||
153 | + if (store != null) { | ||
154 | + store.destroyStoresInSession(this, true); | ||
138 | } | 155 | } |
139 | } | 156 | } |
140 | } | 157 | } |
141 | - | 158 | + |
159 | + /* | ||
160 | + * Returns the current session ID. Creates a session if one doesn't exist. | ||
161 | + * Returns NULL if the session can't be created. | ||
162 | + */ | ||
163 | + private String getSessionId() { | ||
164 | + final HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext() | ||
165 | + .getSession(true); | ||
166 | + return session != null ? session.getId() : null; | ||
167 | + } | ||
168 | + | ||
142 | /* | 169 | /* |
143 | - * Returns the current session ID. Creates a session if one doesn't exist. Returns NULL if the session can't be created. | 170 | + * Returns the configured session timeout in seconds. This is the maximum |
171 | + * inactive interval, not the remaining timeout for this session. | ||
144 | */ | 172 | */ |
145 | - private String getSessionId(){ | ||
146 | - final HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true); | ||
147 | - return session!=null ? session.getId() : null; | 173 | + private int getSessionTimeout() { |
174 | + final HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext() | ||
175 | + .getSession(true); | ||
176 | + return session != null ? session.getMaxInactiveInterval() : 0; | ||
148 | } | 177 | } |
149 | - | 178 | + |
150 | /** | 179 | /** |
151 | - * Observes HTTP session lifecycle and notifies the ViewContext of session events (creation or destruction) | ||
152 | - * so view scoped beans can be created or destroyed based on their underlying session scopes. | 180 | + * Observes HTTP servlet lifecycle and notifies the ViewContext of session events (creation or destruction) |
181 | + * and request events (before going into scope and before going out of scope) so view | ||
182 | + * scoped beans can be created or destroyed based on their underlying session and request scopes. | ||
153 | * | 183 | * |
154 | * @author SERPRO | 184 | * @author SERPRO |
155 | - * | ||
156 | */ | 185 | */ |
157 | @ApplicationScoped | 186 | @ApplicationScoped |
158 | - protected static class FacesViewSessionListener { | ||
159 | - | 187 | + protected static class ServletEventListener { |
188 | + | ||
160 | /** | 189 | /** |
161 | - * Called before the session is invalidated for that user. | ||
162 | - * Destroys all view scoped beans stored on that session. | 190 | + * Called before the session is invalidated for that user. Destroys all view scoped beans stored on that |
191 | + * session. | ||
163 | */ | 192 | */ |
164 | - protected void clearInvalidatedSession(@Observes BeforeSessionDestroyed event){ | 193 | + protected void clearInvalidatedSession(@Observes BeforeSessionDestroyed event) { |
165 | String sessionId = event.getSessionId(); | 194 | String sessionId = event.getSessionId(); |
166 | - try{ | 195 | + try { |
167 | Context context = Beans.getBeanManager().getContext(ViewScoped.class); | 196 | Context context = Beans.getBeanManager().getContext(ViewScoped.class); |
168 | - if ( FacesViewContextImpl.class.isInstance(context) ){ | ||
169 | - ((FacesViewContextImpl)context).clearInvalidatedSession(sessionId); | 197 | + if (FacesViewContextImpl.class.isInstance(context)) { |
198 | + ((FacesViewContextImpl) context).clearInvalidatedSession(sessionId); | ||
170 | } | 199 | } |
200 | + } catch (ContextNotActiveException ce) { | ||
201 | + // Nada a fazer, contexto não está ativo. | ||
171 | } | 202 | } |
172 | - catch(ContextNotActiveException ce){ | ||
173 | - //Nada a fazer, contexto não está ativo. | 203 | + } |
204 | + | ||
205 | + /** | ||
206 | + * Called before the current request is about to go out of scope. Checks if any currently | ||
207 | + * active views have expired and requests the destruction of those beans according to CDI | ||
208 | + * lifecycle. | ||
209 | + * | ||
210 | + */ | ||
211 | + protected void clearExpiredViews(@Observes BeforeRequestDestroyed event) { | ||
212 | + ServletRequest request = event.getRequest(); | ||
213 | + | ||
214 | + if (HttpServletRequest.class.isInstance(request)) { | ||
215 | + HttpSession session = ((HttpServletRequest) request).getSession(false); | ||
216 | + | ||
217 | + if (session != null) { | ||
218 | + try { | ||
219 | + final Context context = Beans.getBeanManager().getContext(ViewScoped.class); | ||
220 | + final String currentSessionId = session.getId(); | ||
221 | + | ||
222 | + if (FacesViewContextImpl.class.isInstance(context)) { | ||
223 | + new Thread() { | ||
224 | + | ||
225 | + @Override | ||
226 | + public void run() { | ||
227 | + ((FacesViewContextImpl) context).clearExpiredViews(currentSessionId); | ||
228 | + } | ||
229 | + }.start(); | ||
230 | + } | ||
231 | + } catch (ContextNotActiveException ce) { | ||
232 | + // Nada a fazer, contexto não está ativo. | ||
233 | + } | ||
234 | + } | ||
174 | } | 235 | } |
175 | } | 236 | } |
176 | } | 237 | } |
177 | } | 238 | } |
178 | - |
impl/extension/jsf/src/main/resources/demoiselle-jsf-bundle.properties
@@ -37,4 +37,5 @@ id-converter-not-found=Voc\u00EA precisa criar um FacesConverter para a classe " | @@ -37,4 +37,5 @@ id-converter-not-found=Voc\u00EA precisa criar um FacesConverter para a classe " | ||
37 | login-page-not-found=A tela de login "{0}" n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.login.page" | 37 | login-page-not-found=A tela de login "{0}" n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.login.page" |
38 | after-login-page-not-found=A tela "{0}" acessada ap\u00F3s o login n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.redirect.after.login" | 38 | after-login-page-not-found=A tela "{0}" acessada ap\u00F3s o login n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.redirect.after.login" |
39 | after-logout-page-not-found=A tela "{0}" acessada ap\u00F3s o logout n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.redirect.after.logout" | 39 | after-logout-page-not-found=A tela "{0}" acessada ap\u00F3s o logout n\u00E3o foi encontrada. Caso essa n\u00E3o seja a p\u00E1gina correta, defina a p\u00E1gina no arquivo de configura\u00E7\u00E3o usando a chave "frameworkdemoiselle.security.redirect.after.logout" |
40 | -faces-context-not-available=N\u00E3o existe uma inst\u00E2ncia de FacesContext ativa para esse escopo | ||
41 | \ No newline at end of file | 40 | \ No newline at end of file |
41 | +faces-context-not-available=N\u00E3o existe uma inst\u00E2ncia de FacesContext ativa para esse escopo | ||
42 | +view-expired=A vis\u00E3o referenciada por essa tela expirou. | ||
42 | \ No newline at end of file | 43 | \ No newline at end of file |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/lifecycle/AfterSessionCreated.java
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
1 | package br.gov.frameworkdemoiselle.lifecycle; | 37 | package br.gov.frameworkdemoiselle.lifecycle; |
2 | 38 | ||
3 | /** | 39 | /** |
4 | * This interface represents an event fired after a new HTTP session is created. | 40 | * This interface represents an event fired after a new HTTP session is created. |
5 | * | 41 | * |
6 | * @author serpro | 42 | * @author serpro |
7 | - * | ||
8 | */ | 43 | */ |
9 | public interface AfterSessionCreated { | 44 | public interface AfterSessionCreated { |
10 | - | 45 | + |
11 | /** | 46 | /** |
12 | - * | ||
13 | * @return The ID of the recently created session | 47 | * @return The ID of the recently created session |
14 | */ | 48 | */ |
15 | public String getSessionId(); | 49 | public String getSessionId(); |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/lifecycle/BeforeRequestDestroyed.java
0 → 100644
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
37 | +package br.gov.frameworkdemoiselle.lifecycle; | ||
38 | + | ||
39 | +import javax.servlet.ServletContext; | ||
40 | +import javax.servlet.ServletRequest; | ||
41 | + | ||
42 | +/** | ||
43 | + * Event fired just before a request is about to go out of scope | ||
44 | + * | ||
45 | + * @author serpro | ||
46 | + */ | ||
47 | +public interface BeforeRequestDestroyed { | ||
48 | + | ||
49 | + public ServletRequest getRequest(); | ||
50 | + | ||
51 | + public ServletContext getServletContext(); | ||
52 | + | ||
53 | +} |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/lifecycle/BeforeRequestInitialized.java
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
37 | +package br.gov.frameworkdemoiselle.lifecycle; | ||
38 | + | ||
39 | +import javax.servlet.ServletContext; | ||
40 | +import javax.servlet.ServletRequest; | ||
41 | + | ||
42 | +/** | ||
43 | + * Event fired just before a request is about to come into scope. | ||
44 | + * | ||
45 | + * @author serpro | ||
46 | + * | ||
47 | + */ | ||
48 | +public interface BeforeRequestInitialized { | ||
49 | + | ||
50 | + public ServletRequest getRequest(); | ||
51 | + | ||
52 | + public ServletContext getServletContext(); | ||
53 | + | ||
54 | +} |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/lifecycle/BeforeSessionDestroyed.java
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
1 | package br.gov.frameworkdemoiselle.lifecycle; | 37 | package br.gov.frameworkdemoiselle.lifecycle; |
2 | 38 | ||
3 | /** | 39 | /** |
4 | * This interface represents an event fired before an HTTP session is destroyed. | 40 | * This interface represents an event fired before an HTTP session is destroyed. |
5 | * | 41 | * |
6 | * @author serpro | 42 | * @author serpro |
7 | - * | ||
8 | */ | 43 | */ |
9 | public interface BeforeSessionDestroyed { | 44 | public interface BeforeSessionDestroyed { |
10 | - | 45 | + |
11 | /** | 46 | /** |
12 | - * | ||
13 | * @return The session ID of the session about to be destroyed | 47 | * @return The session ID of the session about to be destroyed |
14 | */ | 48 | */ |
15 | public String getSessionId(); | 49 | public String getSessionId(); |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/util/RequestListener.java
0 → 100644
@@ -0,0 +1,94 @@ | @@ -0,0 +1,94 @@ | ||
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
37 | +package br.gov.frameworkdemoiselle.util; | ||
38 | + | ||
39 | +import javax.servlet.ServletContext; | ||
40 | +import javax.servlet.ServletRequest; | ||
41 | +import javax.servlet.ServletRequestEvent; | ||
42 | +import javax.servlet.ServletRequestListener; | ||
43 | +import javax.servlet.annotation.WebListener; | ||
44 | + | ||
45 | +import br.gov.frameworkdemoiselle.lifecycle.BeforeRequestDestroyed; | ||
46 | +import br.gov.frameworkdemoiselle.lifecycle.BeforeRequestInitialized; | ||
47 | + | ||
48 | +/** | ||
49 | + * <p> | ||
50 | + * Implements the {@link javax.servlet.ServletRequestListener} interface and fires two events. | ||
51 | + * </p> | ||
52 | + * <ul> | ||
53 | + * <li><strong>{@link BeforeRequestInitialized}</strong>: Just before a new HTTP request comes into scope</li> | ||
54 | + * <li><strong>{@link BeforeRequestDestroyed}</strong>: Just before an HTTP request will go out of scope</li> | ||
55 | + * </ul> | ||
56 | + * | ||
57 | + * @author serpro | ||
58 | + */ | ||
59 | +@WebListener | ||
60 | +public class RequestListener implements ServletRequestListener { | ||
61 | + | ||
62 | + @Override | ||
63 | + public void requestDestroyed(final ServletRequestEvent sre) { | ||
64 | + Beans.getBeanManager().fireEvent(new BeforeRequestDestroyed() { | ||
65 | + | ||
66 | + @Override | ||
67 | + public ServletRequest getRequest() { | ||
68 | + return sre.getServletRequest(); | ||
69 | + } | ||
70 | + | ||
71 | + @Override | ||
72 | + public ServletContext getServletContext() { | ||
73 | + return sre.getServletContext(); | ||
74 | + } | ||
75 | + }); | ||
76 | + } | ||
77 | + | ||
78 | + @Override | ||
79 | + public void requestInitialized(final ServletRequestEvent sre) { | ||
80 | + Beans.getBeanManager().fireEvent(new BeforeRequestDestroyed() { | ||
81 | + | ||
82 | + @Override | ||
83 | + public ServletRequest getRequest() { | ||
84 | + return sre.getServletRequest(); | ||
85 | + } | ||
86 | + | ||
87 | + @Override | ||
88 | + public ServletContext getServletContext() { | ||
89 | + return sre.getServletContext(); | ||
90 | + } | ||
91 | + }); | ||
92 | + } | ||
93 | + | ||
94 | +} |
impl/extension/servlet/src/main/java/br/gov/frameworkdemoiselle/util/SessionListener.java
1 | +/* | ||
2 | + * Demoiselle Framework | ||
3 | + * Copyright (C) 2010 SERPRO | ||
4 | + * ---------------------------------------------------------------------------- | ||
5 | + * This file is part of Demoiselle Framework. | ||
6 | + * | ||
7 | + * Demoiselle Framework is free software; you can redistribute it and/or | ||
8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | ||
9 | + * as published by the Free Software Foundation. | ||
10 | + * | ||
11 | + * This program is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | + * GNU General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | ||
17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||
18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | ||
19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | ||
20 | + * ---------------------------------------------------------------------------- | ||
21 | + * Este arquivo é parte do Framework Demoiselle. | ||
22 | + * | ||
23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | ||
24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | ||
25 | + * do Software Livre (FSF). | ||
26 | + * | ||
27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | ||
28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | ||
29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | ||
30 | + * para maiores detalhes. | ||
31 | + * | ||
32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | ||
33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | ||
34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | ||
35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | ||
36 | + */ | ||
1 | package br.gov.frameworkdemoiselle.util; | 37 | package br.gov.frameworkdemoiselle.util; |
2 | 38 | ||
39 | +import javax.servlet.annotation.WebListener; | ||
3 | import javax.servlet.http.HttpSession; | 40 | import javax.servlet.http.HttpSession; |
4 | import javax.servlet.http.HttpSessionEvent; | 41 | import javax.servlet.http.HttpSessionEvent; |
5 | import javax.servlet.http.HttpSessionListener; | 42 | import javax.servlet.http.HttpSessionListener; |
@@ -8,25 +45,27 @@ import br.gov.frameworkdemoiselle.lifecycle.AfterSessionCreated; | @@ -8,25 +45,27 @@ import br.gov.frameworkdemoiselle.lifecycle.AfterSessionCreated; | ||
8 | import br.gov.frameworkdemoiselle.lifecycle.BeforeSessionDestroyed; | 45 | import br.gov.frameworkdemoiselle.lifecycle.BeforeSessionDestroyed; |
9 | 46 | ||
10 | /** | 47 | /** |
11 | - * <p>Implements the {@link HttpSessionListener} interface and fires two events.</p> | ||
12 | - * | 48 | + * <p> |
49 | + * Implements the {@link HttpSessionListener} interface and fires two events. | ||
50 | + * </p> | ||
13 | * <ul> | 51 | * <ul> |
14 | * <li><strong>{@link AfterSessionCreated}</strong>: Just after a new HTTP session is created</li> | 52 | * <li><strong>{@link AfterSessionCreated}</strong>: Just after a new HTTP session is created</li> |
15 | * <li><strong>{@link BeforeSessionDestroyed}</strong>: Just before an HTTP session is invalidated</li> | 53 | * <li><strong>{@link BeforeSessionDestroyed}</strong>: Just before an HTTP session is invalidated</li> |
16 | * </ul> | 54 | * </ul> |
17 | * | 55 | * |
18 | * @author serpro | 56 | * @author serpro |
19 | - * | ||
20 | */ | 57 | */ |
58 | +@WebListener | ||
21 | public class SessionListener implements HttpSessionListener { | 59 | public class SessionListener implements HttpSessionListener { |
22 | - | 60 | + |
23 | @Override | 61 | @Override |
24 | public void sessionCreated(final HttpSessionEvent sessionEvent) { | 62 | public void sessionCreated(final HttpSessionEvent sessionEvent) { |
25 | Beans.getBeanManager().fireEvent(new AfterSessionCreated() { | 63 | Beans.getBeanManager().fireEvent(new AfterSessionCreated() { |
64 | + | ||
26 | @Override | 65 | @Override |
27 | public String getSessionId() { | 66 | public String getSessionId() { |
28 | HttpSession session = sessionEvent.getSession(); | 67 | HttpSession session = sessionEvent.getSession(); |
29 | - return session!=null ? session.getId() : null; | 68 | + return session != null ? session.getId() : null; |
30 | } | 69 | } |
31 | }); | 70 | }); |
32 | } | 71 | } |
@@ -34,10 +73,11 @@ public class SessionListener implements HttpSessionListener { | @@ -34,10 +73,11 @@ public class SessionListener implements HttpSessionListener { | ||
34 | @Override | 73 | @Override |
35 | public void sessionDestroyed(final HttpSessionEvent sessionEvent) { | 74 | public void sessionDestroyed(final HttpSessionEvent sessionEvent) { |
36 | Beans.getBeanManager().fireEvent(new BeforeSessionDestroyed() { | 75 | Beans.getBeanManager().fireEvent(new BeforeSessionDestroyed() { |
76 | + | ||
37 | @Override | 77 | @Override |
38 | public String getSessionId() { | 78 | public String getSessionId() { |
39 | HttpSession session = sessionEvent.getSession(); | 79 | HttpSession session = sessionEvent.getSession(); |
40 | - return session!=null ? session.getId() : null; | 80 | + return session != null ? session.getId() : null; |
41 | } | 81 | } |
42 | }); | 82 | }); |
43 | } | 83 | } |
impl/extension/servlet/src/main/resources/META-INF/web-fragment.xml
@@ -47,6 +47,10 @@ | @@ -47,6 +47,10 @@ | ||
47 | <listener> | 47 | <listener> |
48 | <listener-class>br.gov.frameworkdemoiselle.util.SessionListener</listener-class> | 48 | <listener-class>br.gov.frameworkdemoiselle.util.SessionListener</listener-class> |
49 | </listener> | 49 | </listener> |
50 | + | ||
51 | + <listener> | ||
52 | + <listener-class>br.gov.frameworkdemoiselle.util.RequestListener</listener-class> | ||
53 | + </listener> | ||
50 | 54 | ||
51 | <filter> | 55 | <filter> |
52 | <filter-name>Demoiselle Servlet Filter</filter-name> | 56 | <filter-name>Demoiselle Servlet Filter</filter-name> |