I tried your suggestion below and I still get errors when clicking column headings one after the other.

Error Message:

page recorder for page users is locked after a commit(), but received a change to property userList of component users.
Stack Trace:


   * 
org.apache.tapestry.record.PageRecorder.observeChange(PageRecorder.java:119)

   * org.apache.tapestry.Tapestry.fireObservedChange(Tapestry.java:1339)
   * 
org.apache.tapestry.AbstractComponent.fireObservedChange(AbstractComponent.java:304)

   * org.appfuse.web.UserList$Enhance_1.setUserList(UserList$Enhance_1.java)

   * org.appfuse.web.UserList.pageBeginRender(UserList.java:30)


UserList.java:

public abstract class UserList extends BasePage implements PageRenderListener {
public abstract UserManager getUserManager();
public abstract void setUserManager(UserManager manager);


   public abstract List getUsers();
   public abstract void setUsers(List users);

   public abstract String getMessage();
   public abstract void setMessage(String value);

   public abstract DateFormat getDateFormatter();
   public abstract void setDateFormatter(DateFormat value);

   public void pageBeginRender(PageEvent event) {
       if (event.getRequestCycle().isRewinding() || getUsers() != null) {
           return;
       }

setDateFormatter(new SimpleDateFormat("MM/dd/yyyy"));
setUsers(getUserManager().getUsers());
}
public String getFormattedDate(java.util.Date date) {
if (date == null) {
return "";
}
return getDateFormatter().format(date);
}
}


users.page:

<page-specification class="org.appfuse.web.UserList">
<property-specification name="userManager" type="org.appfuse.service.UserManager">
global.appContext.getBean("userManager")
</property-specification>


<property-specification name="users" type="java.util.List" persistent="yes"/>
<property-specification name="dateFormatter" type="java.text.DateFormat"/>
<property-specification name="message" type="java.lang.String"/>


   <property-specification name="row"/>
   <bean name="evenOdd" class="org.apache.tapestry.bean.EvenOdd"/>
   <context-asset name="upArrow" path="/images/arrow_up.png"/>
   <context-asset name="downArrow" path="/images/arrow_down.png"/>
</page-specification>

Thanks,

Matt


> > > > Ernesto, > > > > Sorry this turned out to be kind of long, but it was the easiest way > > to try > > and answer your question. > > > > I was aware of the double-click problem, but based on your description > > I > > didn't feel that was your issue (although it is possible). I rarely > > see > > this in my apps, and your problem sounds more frequent and consistent. > > > > The persistent attribute goes in your .page file, like this: > > > > <property-specification name="userList" type="java.util.List" > > persistent="yes"/> > > > > I don't know much about AppFuse, but I doubt UserManager itself is > > serializable. Even so, it is not the type of object (an application > > singleton stored in your global) you would probably want to persist in > > an > > http session. Therefore, I would try adding abstract getters and > > setters of > > your actual user list in your .java page code (so Tapestry can enhance > > those > > methods), and then do something like: > > > > UserManager userManager = > > getGlobal().getAppContext().getBean("userManager"); > > setUserList( userManager.getUsers()); > > > > You could put that code in pageBeginRender(), but be sure and check for > > rewind first, for example: > > > > public void pageBeginRender(PageEvent event) > > { > > if(event.getRequestCycle().isRewinding()) > > return; > > > > UserManager userManager = > > getGlobal().getAppContext().getBean("userManager"); > > setUserList( userManager.getUsers()); > > } > > > > If you don't handle the rewind cycle, you will end up with the same > > type of > > exceptions you are already getting (page recorder locked, etc.). > > > > Looking back over your original code, I noticed a couple of problems. > > First, your 'message' variable is dangerous. Since Tapestry caches > > page > > objects in an internal pool, if you have instance variables in your > > page you > > have to take care to return the page to a pristine state after you are > > finished with it. Otherwise, a message may be generated for one user, > > and > > then another user could come along and reuse the cached page object, > > and > > they would see the first user's message! > > > > Tapestry has an elegant way to deal with this, but you have to know > > about it > > (all of this is explained very well in Tapestry in Action, if you > > happen to > > have it). You need to override the initialize() method, which Tapestry > > calls to initialize the page to a clean state (the name is somewhat > > confusing, since it is called at the end, rather than the beginning of > > page > > rendering). > > > > Another problem (or at least something to be aware of) is that your > > page > > doesn't implement PageRenderListener, and therefore won't be notified > > for > > render events (so the pageBeginRender above would never be invoked). > > Taking > > your original page code, here is a modified version: > > > > public abstract class UserList extends BasePage implements > > PageRenderListener > > { > > private String message; > > > > private DateFormat dateFormatter = new > > SimpleDateFormat("dd/MM/yyyy"); > > > > public abstract List getUserList(); > > public abstract void setUserList(List list); > > > > protected void initialize() { > > message = null; > > dateFormatter = null; > > } > > > > public void setMessage(String message) { > > this.message = message; > > } > > > > public String getMessage() { > > return this.message; > > } > > > > public DateFormat getDateFormatter() { > > return dateFormatter; > > } > > > > public void pageBeginRender(PageEvent event) > > { > > if(event.getRequestCycle().isRewinding()) > > return; > > > > UserManager userManager = > > getGlobal().getAppContext().getBean("userManager"); > > setUserList( userManager.getUsers()); > > } > > } > > > > In this page, there is no reason however to have instance variables for > > message and dateFormatter, and they can cause you problems if you > > forget to > > override initialize(). If you let Tapestry handle them, you can > > eliminate > > the instance variables and the initialize() method, but add abstract > > setters > > and getters and set your properties in pageBeginRender (or whereever > > else is > > appropriate, such as in your form listener method). So, this is > > probably > > better: > > > > public abstract class UserList extends BasePage implements > > PageRenderListene > > r > > { > > public abstract List getUserList(); > > public abstract void setUserList(List list); > > > > public abstract String getMessage(); > > public abstract void setMessage(String value); > > > > public abstract DateFormat getDateFormatter(); > > public abstract void setDateFormatter(DateFormat value); > > > > public void pageBeginRender(PageEvent event) > > { > > if(event.getRequestCycle().isRewinding()) > > return; > > > > setDateFormatter( new SimpleDateFormat("dd/MM/yyyy")); > > > > UserManager userManager = > > getGlobal().getAppContext().getBean("userManager"); > > setUserList( userManager.getUsers()); > > } > > } > > > > Be sure and add <property-specification> elements in your > > UserList.page file > > for each of your abstract methods above. > > > > <property-specification name="userList" type="java.util.List" > > persistent="yes" /> > > <property-specification name="dateFormatter" > > type="java.text.DateFormat" /> > > <property-specification name="message" type="java.lang.String" /> > > > > This was all keyed free-hand, so there may be some mistakes, but you > > should > > get the idea. Again, I would recommend Tapestry in Action, as these > > points > > and many others are covered in great detail. > > > > Shawn > > > > > > -----Original Message----- > > From: news [mailto:[EMAIL PROTECTED] Behalf Of Ernesto Echeverria > > Sent: Friday, March 04, 2005 10:55 AM > > To: [email protected] > > Subject: Re: Possible Bug in table component? > > > > > > Shawn, where exactly would that property go in order to try? > > > > BTW I've read the other comments and it's not necessarily a > > double-click > > issue. Sometimes it's clicks in sucession (but not that continuous), if > > that was the case it would look like a very slow component. > > > > Shawn Church wrote: > >> You might try making userManager a persistent page property > >> (persistent="yes"). Hopefully org.appfuse.service.UserManager is > >> Serializable, but you will discover quickly if this is the case. > >> Contrib:table uses the http session by default to store the table > >> state. > >> If this fixes your problem, you can decide whether or not a stateful > >> UserManager is acceptable. If not, maybe you can make just your > >> "users" > >> list persistent. Contrib:table is flexible enough to allow you to > >> provide your own state manager, but you can try this first as a test. > >> > >> Shawn > > > > >



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to