[
https://jira.jboss.org/jira/browse/JBSEAM-3622?page=com.atlassian.jira.pl...
]
Nikolay Elenkov commented on JBSEAM-3622:
-----------------------------------------
Thanks for looking into this.
I have a bunch of s:links that redirect to the top-page for every use case of my app.
Something like:
<s:link action="list-users" value="List Users" />
<s:link action="register-users" value="Register User" />
And in pages.xml:
<rule if-outcome="list-users">
<end-conversation before-redirect="true" />
<redirect view-id="/user-list.xhtml">
</redirect>
</rule>
<rule if-outcome="register-user">
<end-conversation before-redirect="true" />
<redirect view-id="/user-registration.xhtml" />
</rule>
If I click one of the above links, the current conversation ends with the redirect and
state is cleared (I can see that in my debug session attribute listener).
If I keep ending the conversation and starting a new one (click "List Users",
search, clisk "Register User", register new user; repeat) ,
all attributes but the SFSB's (Cf. 17/18/19$userManager in the description above) are
removed and session size keeps growing.
I stepped through this with the debugger and I couldn't see any other cleanup code
being executed, so I assumed this is the only place session
gets cleaned up.
I will put together a small app to reproduce this, when I get some time (next week
probably).
Here's what I used to test this:
public class MySessionAttributeListener implements HttpSessionAttributeListener {
public void attributeAdded(HttpSessionBindingEvent e) {
System.out.println("++++++ attribute added " + e.getName());
dumpNames(e.getSession());
}
public void attributeRemoved(HttpSessionBindingEvent e) {
System.out.println("---------- attribute removed " + e.getName());
// dumpNames(e.getSession());
}
public void attributeReplaced(HttpSessionBindingEvent e) {
System.out.println("attribute replaced " + e.getName());
// dumpNames(e.getSession());
}
private void dumpNames(HttpSession session) {
Enumeration e = session.getAttributeNames();
System.out.println("ATTRS START");
List<String> names = new ArrayList<String>();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
names.add(name);
}
Collections.sort(names);
for (String name : names) {
if (name.startsWith("org.jboss.seam.CONVERSATION")) {
System.out.println(name);
}
}
System.out.println("ATTRS END: " + names.size());
}
}
SFSB not removed from session when temporary conversation ends
--------------------------------------------------------------
Key: JBSEAM-3622
URL:
https://jira.jboss.org/jira/browse/JBSEAM-3622
Project: Seam
Issue Type: Bug
Components: Core
Affects Versions: 2.0.3.CR1, 2.1.0.GA
Environment: JBoss 4.2.2, Seam 2.0.3.CR1
Reporter: Nikolay Elenkov
Assignee: Norman Richards
Priority: Critical
Fix For: 2.1.1.CR1
I came across this while checking my app for session leaks. I used a simple listener that
dumps session attributes on every add/remove/replace.
When I end a conversation, all entities are removed from the session, as expected.
However, manager components (SFSB's) are left over. Repeatedly starting and ending a
conversation results in something like (17, 18, 19 have ended, all other attributes for
those conversations have been removed from session; 20 is active):
20:11:12,440 INFO [STDOUT] org.jboss.seam.CONVERSATION#17$userManager
20:11:12,440 INFO [STDOUT] org.jboss.seam.CONVERSATION#18$userManager
20:11:12,440 INFO [STDOUT] org.jboss.seam.CONVERSATION#19$userManager
20:11:12,440 INFO [STDOUT] org.jboss.seam.CONVERSATION#20$userManager
20:11:12,440 INFO [STDOUT] org.jboss.seam.CONVERSATION#20$user
I stepped through this with the debugger, and it seems that SFSB's are not removed if
the conversation is a temporary one.
Here's what (I think) happens:
1. Conversation ended by @End or pages.xml
2. SFSB's @Remove @Destroy destroy() method is called
3. RemoveInterceptor calls ServerConversationContext#remove(). That results in the
component's name being added to ServerConversationContext#removals.
4. When ServerConversationContext#flush() is called, names in the removals list are
not actually removed from the session, because the conversation is temporary (see ***
below)
from ServerConversationContext.java:
public void flush()
{
boolean longRunning = !isCurrent() ||
Manager.instance().isLongRunningConversation();
if ( longRunning )
{
// ....
}
else
{
//TODO: for a pure temporary conversation, this is unnecessary, optimize it
// *** Here: getNamesFromSession does not include removals, so they are left
over
// Should probably be like this:
// START
for (String name: removals) {
session.remove(getKey(name));
}
removals.clear();
// END
for ( String name: getNamesFromSession() )
{
session.remove( getKey(name) );
}
}
}
private Set<String> getNamesFromSession()
{
HashSet<String> results = new HashSet<String>();
String prefix = getPrefix(getId());
for (String name: session.keySet()) {
if (name.startsWith(prefix)) {
name = name.substring(prefix.length());
if (!removals.contains(name)) { // *** Here: name not added to results if in
the removals list
results.add(name);
}
}
}
return results;
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira