Issue Details (XML | Word | Printable)

Key: BEEHIVE-1028
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Yongqin Xu
Reporter: Chad Schoettger
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
Beehive

Controls in pageflows do not appear to be receiving lifecycle events in the proper order

Created: 13/Dec/05 05:32 AM   Updated: 09/Feb/06 02:45 AM
Return to search
Component/s: NetUI
Affects Version/s: 1.0, 1.0.1
Fix Version/s: 1.0.1

Time Tracking:
Not Specified

File Attachments:
  Size
Zip Archive Licensed for inclusion in ASF works beehive1028.zip 2005-12-13 06:16 AM Chad Schoettger 3.16 MB
Zip Archive Licensed for inclusion in ASF works jira1028Simplified.zip 2005-12-16 10:09 AM Rich Feit 10 kB

Resolution Date: 25/Jan/06 05:46 AM


 Description  « Hide
So I have a small webapp which basically consists of a pageflow and a jdbc control. The single jsp in the web app invokes an action in the page flow as:

  <tr><td><img src="doRenderChart.do?versionName=9.2Beta&projectName=Workshop&componentName=W-IDE&JFWidth=500&JFHeight=300" border="0"/></td></tr>

It does this 10 or 11 times to build a table which contains images generated by the action using the jdbc control to retrieve data from a database. Typically (although not always) at least one of the images will not be generated due to an SQL Error throw by the jdbc control. The error is that the SQLConnection has been closed.

Here is a portion of the tomcat log, I've added some debugging statements in the ControlContainerContext class to help me see what was going on, the doRenderChart() is the page flow action being called by the jsp. It appears the control's begin and end events are not fired in the right order, causing (in some instances) the control to be unititialzed before a call has been completed.


log4j:WARN Please initialize the log4j system properly.
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=null
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDE
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Docs
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDECore
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-External
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Project
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Javelin
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeControls
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeNetUI
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Upgrade
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 33
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=null
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 33
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Docs
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDE
BEGIN_CONTEXT: THREAD ID = 33
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 33
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-External
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 33
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDECore
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Project
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 33
calling version=9.2Beta project=Workshop component=W-Javelin
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeControls
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 33
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeNetUI
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Upgrade
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
END_CONTEXT: THREAD ID = 33
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
Listening for transport dt_shmem at address: jdbconn
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=null
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Docs
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-External
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDE
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
BEGIN_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-IDECore
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
**** Enter: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 34
calling version=9.2Beta project=Workshop component=W-Project
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Javelin
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeControls
BEGIN_CONTEXT: THREAD ID = 34
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-RuntimeNetUI
BEGIN_CONTEXT: THREAD ID = 35
**** Leave: doRenderChart() ****
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 35
BEGIN_CONTEXT: THREAD ID = 35
**** Enter: doRenderChart() ****
calling version=9.2Beta project=Workshop component=W-Upgrade
**** Leave: doRenderChart() ****
BEGIN_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 35
END_CONTEXT: THREAD ID = 34
END_CONTEXT: THREAD ID = 34


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Chad Schoettger made changes - 13/Dec/05 05:33 AM
Field Original Value New Value
Summary Controls in pageflows do not appear to be recieving lifecycle events in the proper order Controls in pageflows do not appear to be receiving lifecycle events in the proper order
Chad Schoettger added a comment - 13/Dec/05 06:16 AM
attached web app to reproduce this issue.

Chad Schoettger made changes - 13/Dec/05 06:16 AM
Attachment beehive1028.zip [ 12321296 ]
Eddie O'Neil added a comment - 13/Dec/05 06:22 AM
Chad, from the repro application, what is both the expected and observed behavior here?

Eddie O'Neil added a comment - 13/Dec/05 06:22 AM
Adding 1.1 to the affects version.

Eddie O'Neil made changes - 13/Dec/05 06:22 AM
Affects Version/s 1.1 [ 12310333 ]
Chad Schoettger added a comment - 16/Dec/05 02:23 AM
Appears to be a pageflow issue, assigning to Rich.

Chad Schoettger made changes - 16/Dec/05 02:23 AM
Assignee Chad Schoettger [ chad_s ] Rich Feit [ rich ]
Rich Feit added a comment - 16/Dec/05 06:36 AM
Hey Chad, when I run /Controller.jpf, I get the following output:

**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****
**** Enter: doRenderChart() ****
**** Leave: doRenderChart() ****

This seems OK -- what should I be looking for?

Rich Feit made changes - 16/Dec/05 06:36 AM
Assignee Rich Feit [ rich ] Chad Schoettger [ chad_s ]
Rich Feit added a comment - 16/Dec/05 06:59 AM
OK, I've actually added this code in my control:

    @Context
    ResourceContext resourceContext;

    @EventHandler(field="resourceContext",
                  eventSet=ResourceContext.ResourceEvents.class,
                  eventName="onAcquire")
    public void onAcquire()
    {
        System.err.println("&&&&& onAcquire");
    }
  
    @EventHandler(field="resourceContext",
                  eventSet=ResourceContext.ResourceEvents.class,
                  eventName="onRelease")
    public void onRelease()
    {
        System.err.println("&&&&& onRelease");
    }


So the question is, how *should* "&&&&& onAcquire" and "&&&&& onRelease" be interleaved in the rest of the output? You can kick this back to me with that info -- thanks.

Rich Feit added a comment - 16/Dec/05 10:07 AM
Chad, I'm attaching a Controls-only webapp that proves one of three things:

    1) This is fundamentally a problem with Controls.
    2) At least one piece of the problem is within Controls.
    3) The NetUI framework is using Controls incorrectly, since it uses Controls in the way that this repro app uses Controls.

Hopefully you or someone else can tell me whether it's 1/2, or 3. :)

Basically, the issue involves using the *same instance* of a Control from two separate threads. To reproduce the problem:

    - Deploy the attached app to Tomcat.
    - Hit http://localhost:8080/jira1028Simplified/one.jsp.
    - Make sure your Tomcat console is visible.
    - Click the "go" link in the browser (to eliminate variables, please use Firefox, not IE or Mozilla).
    - When you see "Click again!" on the console, click the "go" link again.

You'll see the following output (the numbers are thread-IDs). Notice that there's only one call to each of onAcquire/onRelease (on the first thread), even though dummyControlMethod gets called from both threads.

    34 onAcquire
    34 begin dummyControlMethod
    34 end dummyControlMethod
    35 begin dummyControlMethod
    34 onRelease
    35 end dummyControlMethod

Rich Feit added a comment - 16/Dec/05 10:09 AM
The repro app. Note that you will have to change the value of beehive.home in build.properties for this to build.

Rich Feit made changes - 16/Dec/05 10:09 AM
Attachment jira1028Simplified.zip [ 12321355 ]
Rich Feit added a comment - 17/Dec/05 01:48 AM
Note that the bad behavior exists even if I make dummyControlMethod synchronized:

34 onAcquire
34 begin dummyControlMethod
34 end dummyControlMethod
34 onRelease
35 begin dummyControlMethod
35 end dummyControlMethod

Chad Schoettger added a comment - 07/Jan/06 12:58 AM
After further investigation this appears to be a problem with the ControlFilter and PageFlow.

Basically what is happening is:

*) The bean context is being stored in the session.
*) When the context's 'beginContext()' method is called, it is passed the current request and response as parameters - which ties the bean context to a particular servlet request/response.
*) If another thread with the same session makes a request, the same bean context is used but if the bean context associated with the first thread has not completed its servlet request/response information is overwritten by the second thread's request.

I belive that the core isssue here is that it is improper to store a bean context in a session, since the bean context works on a per-request scope, but at any given time there may be multiple requests made on a single session.\

My recommendation would be to remove the ability to store the bean context in the session, and just create a new bean context for each request recieved. This is a fairly straightforward modification to the ControlFilter but may need some additional investigation on the page flow side of things.

Rich Feit added a comment - 09/Jan/06 04:44 PM
The main question would be: is it OK to maintain a reference to a control that lives longer than a context that it's resided in? Since Control member variables in page flows end up stored in the session, each one would get put into a different context for each request. If it's OK to have a longer-lived Control, then it sounds like this will work.

If you take that approach (making it invalid to store the context in the session), then I assume you'd deprecate the Servlet init param that enables this behavior in ServletBeanContext?

Repository Revision Date User Message
ASF #369582 Mon Jan 16 21:56:43 UTC 2006 cschoett Partial fix for BEEHIVE-1028, this fix addresses the ControlFilter only NOT pageflows. The fix consists of removing the 'useSession' flag from the ControlFilter and creating a new control bean context for each request.
Files Changed
MODIFY /beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/servlet/ControlFilter.java

Chad Schoettger added a comment - 17/Jan/06 06:58 AM
Commited fix to ControlFilter for this bug. Fix consists of removing the 'useSession' initParam for the ControlFiler and creating a new ControlBeanContext for each request the ControlFilter recieves.

This fix in no way resolves this issue for pageflows.

Daryl Olander made changes - 24/Jan/06 03:10 AM
Fix Version/s 1.0.1 [ 12310717 ]
Daryl Olander added a comment - 25/Jan/06 05:46 AM
I reworked how the ControlContainerContext inside of the page flow runtime works to fix a number of problems that could have caused problems. The following is a brief description of this fix.

There are now two sets of ControlContainerContext (CCC) objects. For page flows and faces backing files, the CCC is scoped into the lifetime of the page flow. For all shared flows (and global app) there is a single CCC.

In order to handle the property beginContext/endContext, we now do the beginContext/endContext in the three single threaded execution sections where page flow code runs. These are the around onCreate, beforeAction/Action/afterAction, and then JSP rendering. In each of these sections will will run beginContext and endContext. In addition, there is a single lock object that is obtained to gain access to the shared flow CCC.

The result is that we now provide single threaded access to a shared flow (assuming that there is a control in some shared flow). In addition, we will serialize execution of thread within the session. We also run the proper resource event lifecycle on the controls.


Daryl Olander made changes - 25/Jan/06 05:46 AM
Resolution Fixed [ 1 ]
Status Open [ 1 ] Resolved [ 5 ]
Alejandro Ramirez added a comment - 02/Feb/06 07:02 AM
Please verify

Alejandro Ramirez made changes - 02/Feb/06 07:02 AM
Assignee Chad Schoettger [ chad_s ] Yongqin Xu [ yongqxu ]
Yongqin Xu added a comment - 09/Feb/06 02:45 AM
re-run the web app, the connection closed exception does not happen anymore.

Yongqin Xu made changes - 09/Feb/06 02:45 AM
Status Resolved [ 5 ] Closed [ 6 ]