Re: Activation context for a component?
On Sun, 14 Feb 2010 17:33:43 -0200, Nathan Kopp wrote: Even with your suggested change, this would still generate a null pointer exception (NPE) in the same place, since the problem lies with "fooLoopVar" being null when the eventlink is click is processed by Tapestry. You simply can't use it in the EventLink method handler. The NPE happens before I even get to rendering the description text field. Never forget that T5 uses redirect after post, so the event handling request is not the same as the render request. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, software architect and developer, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Activation context for a component?
Good thought, but the copy of Donkey isn't the problem. (Actually, when using Hibernate or JPA, you'd want to make a copy to allow "cancel" to work, because altering a JPA entity by binding directly to the "real" instance could cause the database to be updated immediately... JPA/Hibernate doesn't wait for you to call any saveToDb or persist method.) Note that my instance used for editing has the @Persist annotation, so Tapestry does a great job remembering its state. Even with your suggested change, this would still generate a null pointer exception (NPE) in the same place, since the problem lies with "fooLoopVar" being null when the eventlink is click is processed by Tapestry. The NPE happens before I even get to rendering the description text field. -Nathan On Sun, Feb 14, 2010 at 2:02 PM, wrote: > Hi Nathan, > > > Anywhere on my site where I display a Donkey, I want to let the user edit > the instance. > So then do exactly that... Tapestry 5 is sometimes simpler than you might > expect, to me it seems you are complicating things unnecessarily... why are > you creating new instances when editing? You shouldn't need to, simply pass > in foo and call getDonkey and edit that instance. Your loop should just > work, simply bind foo and the correct instance will always be bound, with a > new instance of the inlinedit component for every iteration, so you have no > need for extended context info in this case. > > >Here's a foo: ${fooLoopVar.name} > > > > > public class ViewDonkeyInlineEdit > { >@Parameter (allownull=false, required=true) >@Property >private Foo foo; > > >//wired to your event onEdit etc. >@Persist @Property private Boolean isEditing; > > >public void onSaveEditDonkey() { >foo.getDonkey().saveToDB(); >} > } > > > Description: > > Its that simple. > > Peter > > > - Original Message - > From: "Nathan Kopp" > To: users@tapestry.apache.org > Sent: Sunday, 14 February, 2010 04:10:02 GMT +02:00 Athens, Beirut, > Bucharest, Istanbul > Subject: Activation context for a component? > > Hey everyone! I'm new here and I apologize for not lurking long before > posting. I have searched the archives extensively for this issue and have > come up empty, so I'm just going to jump in. > [clip] >
Re: Activation context for a component?
Hi! On Sun, 14 Feb 2010 00:10:02 -0200, Nathan Kopp wrote: There are two things preventing this from working: First, Tapestry does not replay the loop when processing the eventlink (like it did in the 3.x and 4.x days). Therefore, "fooLoopVar" never gets changed from its default of null. Tapestry 5 doesn't have the rewind phase like previous versions had. And that's a very good thing, because it was quite complicated to understand and make it work. You should use the context parameter of EventLink and ActionLink to pass information to the event handler method. Second, there's only one instance of the ViewDonkeyInlineEdit component inside the loop. Yes. Less memory usage! The solution is the same as above. All of the eventlink URLs look identical, so there's no way to tell which Donkey should be edited. See above. I tried using the "context" parameter of the eventlink component, but since events start at the deepest level and bubble up, It starts at the EventLink instance level, not from the deepest one. I got the null pointerexception before I could use the context for anything useful at the outer (page) level. This looks like a bug in your code, most probably by working in a T4-ish way in T5. In Test.java, I added: String onPassivate() { return fooLoopVar==null?null:fooLoopVar.getName(); } You shouldn't rely in a variable used as a Loop object (in this case, fooLoopVar), as T5 doesn't have a rewind phase. Basically, I need something that works like the page activation context, but generalized to work with any component at any level of the component tree. Inject ComponentEventLinkEncoder and use its decodePageRenderRequest(Request request) method (when rendering) or decodePageRenderRequest(Request request) (when handling an event). Both methods return an object that contains the page activation context. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, software architect and developer, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Activation context for a component?
Hi Nathan, > Anywhere on my site where I display a Donkey, I want to let the user edit the > instance. So then do exactly that... Tapestry 5 is sometimes simpler than you might expect, to me it seems you are complicating things unnecessarily... why are you creating new instances when editing? You shouldn't need to, simply pass in foo and call getDonkey and edit that instance. Your loop should just work, simply bind foo and the correct instance will always be bound, with a new instance of the inlinedit component for every iteration, so you have no need for extended context info in this case. Here's a foo: ${fooLoopVar.name} public class ViewDonkeyInlineEdit { @Parameter (allownull=false, required=true) @Property private Foo foo; //wired to your event onEdit etc. @Persist @Property private Boolean isEditing; public void onSaveEditDonkey() { foo.getDonkey().saveToDB(); } } Description: Its that simple. Peter - Original Message - From: "Nathan Kopp" To: users@tapestry.apache.org Sent: Sunday, 14 February, 2010 04:10:02 GMT +02:00 Athens, Beirut, Bucharest, Istanbul Subject: Activation context for a component? Hey everyone! I'm new here and I apologize for not lurking long before posting. I have searched the archives extensively for this issue and have come up empty, so I'm just going to jump in. I'm working in Tapestry 5.1.0.5 (the latest as far as I know) and I've run into a use-case that I can't figure out how to solve cleanly with T5. I actually used Tapestry extensively back in the 3.x and 4.x days, partially because it could solve this particular use case very well when other frameworks would fall flat. Unfortunately, Tapestry works differently now, so I think I need some help solving this in the new paradigm. Also, this is really long, because I wanted to include lots of code to give really good context to my question. Here goes: I have two objects, let's call them Foo and Donkey (shout-out to the Java Posse). Each Foo object contains a Donkey object, like this: public class Donkey { private String name; private String descr; // constructor & getters/setters go here } public class Foo { private String name; private Donkey donkey; // constructor & getters/setters go here } Now... the Donkey object represents user-contributed content. Anywhere on my site where I display a Donkey, I want to let the user edit the instance. To do this, I've created a reusable custom component that displays the Donkey, including inline editing capabilities. It's rudimentary now, but eventually it'll probably use an Ajax modal popup from ChenilleKit. ==ViewDonkeyInlineEdit.tml=== http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";> http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Donkey's name: ${donkey.name} Description: Cancel Description: ${donkey.descr} Edit ViewDonkeyInlineEdit.java= public class ViewDonkeyInlineEdit { @Property @Parameter private Donkey donkey; @Persist @Property private Donkey editDonkey; public boolean isEditing() { return (editDonkey!=null && editDonkey.getName().equals(donkey.getName())); } public void onStartEditDonkey() { editDonkey = new Donkey(donkey.getName(), donkey.getDescr()); } public void onSaveEditDonkey() { donkey.setDescr(editDonkey.getDescr()); editDonkey = null; } public void onCancelEditDonkey() { editDonkey = null; } } == Now, let's use it in a page: Test.tml == http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Here's a foo: ${firstFoo.name} Here's a foo: ${secondFoo.name} Here's a foo: ${thirdFoo.name} = This works great. No problems. Clearly, though, this is *screaming* to be put into a loop. So, let's try this: === Test.tml (version 2) = http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Here's a foo: ${fooLoopVar.name} == Of course, this doesn't work. (If it did work, I wouldn't be writing this message right now.) When I click the "edit" link to triggger the "startDonkeyEdit" event, I get a null pointer exception. There are two things preventing this from working: First, Tapestry does not replay the loop when processing the eventlink (like it did in the 3.x and 4.x days). Therefore, "fooLoopVar" never gets changed from its default of null. Second, there's only one instance of the ViewDonkeyInlineEdit component inside the loop. All of the eventlink URLs look identical, so there's no way to tell which Donkey should be edited. I tried
Re: [T5.2.0-SNAPSHOT] Block to String without MarkupWriter
Nothing obvious is coming to me; a Block represents markup and needs a markup writer to execute. You can leverage some of the internal Tapestry services to render the content much like a partial page render, perhaps. On Thu, Jan 28, 2010 at 8:36 AM, Joost Schouten (ml) wrote: > Hi, > > I have Build a GridToCSVExport mixin. This all works great up to the stage > where I try render the override parameter blocks like "propertyNameCell". I > can obtain the Block's, but can see no way to render the block to String > without a MarkupWriter. Any pointers would be appreciated. > > Cheers, > Joost > > - > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > > -- Howard M. Lewis Ship Creator of Apache Tapestry The source for Tapestry training, mentoring and support. Contact me to learn how I can get you up and productive in Tapestry fast! (971) 678-5210 http://howardlewisship.com - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Activation context for a component?
Hey everyone! I'm new here and I apologize for not lurking long before posting. I have searched the archives extensively for this issue and have come up empty, so I'm just going to jump in. I'm working in Tapestry 5.1.0.5 (the latest as far as I know) and I've run into a use-case that I can't figure out how to solve cleanly with T5. I actually used Tapestry extensively back in the 3.x and 4.x days, partially because it could solve this particular use case very well when other frameworks would fall flat. Unfortunately, Tapestry works differently now, so I think I need some help solving this in the new paradigm. Also, this is really long, because I wanted to include lots of code to give really good context to my question. Here goes: I have two objects, let's call them Foo and Donkey (shout-out to the Java Posse). Each Foo object contains a Donkey object, like this: public class Donkey { private String name; private String descr; // constructor & getters/setters go here } public class Foo { private String name; private Donkey donkey; // constructor & getters/setters go here } Now... the Donkey object represents user-contributed content. Anywhere on my site where I display a Donkey, I want to let the user edit the instance. To do this, I've created a reusable custom component that displays the Donkey, including inline editing capabilities. It's rudimentary now, but eventually it'll probably use an Ajax modal popup from ChenilleKit. ==ViewDonkeyInlineEdit.tml=== http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";> http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Donkey's name: ${donkey.name} Description: Cancel Description: ${donkey.descr} Edit ViewDonkeyInlineEdit.java= public class ViewDonkeyInlineEdit { @Property @Parameter private Donkey donkey; @Persist @Property private Donkey editDonkey; public boolean isEditing() { return (editDonkey!=null && editDonkey.getName().equals(donkey.getName())); } public void onStartEditDonkey() { editDonkey = new Donkey(donkey.getName(), donkey.getDescr()); } public void onSaveEditDonkey() { donkey.setDescr(editDonkey.getDescr()); editDonkey = null; } public void onCancelEditDonkey() { editDonkey = null; } } == Now, let's use it in a page: Test.tml == http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Here's a foo: ${firstFoo.name} Here's a foo: ${secondFoo.name} Here's a foo: ${thirdFoo.name} = This works great. No problems. Clearly, though, this is *screaming* to be put into a loop. So, let's try this: === Test.tml (version 2) = http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"; xmlns:p="tapestry:parameter"> Here's a foo: ${fooLoopVar.name} == Of course, this doesn't work. (If it did work, I wouldn't be writing this message right now.) When I click the "edit" link to triggger the "startDonkeyEdit" event, I get a null pointer exception. There are two things preventing this from working: First, Tapestry does not replay the loop when processing the eventlink (like it did in the 3.x and 4.x days). Therefore, "fooLoopVar" never gets changed from its default of null. Second, there's only one instance of the ViewDonkeyInlineEdit component inside the loop. All of the eventlink URLs look identical, so there's no way to tell which Donkey should be edited. I tried using the "context" parameter of the eventlink component, but since events start at the deepest level and bubble up, I got the null pointer exception before I could use the context for anything useful at the outer (page) level. Next, I tried adding an activation context to the page. In Test.java, I added: String onPassivate() { return fooLoopVar==null?null:fooLoopVar.getName(); } public void onActivate(String fooName) { for(Foo foo : list) { if(foo.getName().equals(fooName)) { this.fooLoopVar = foo; } } } This worked really well. It appears that the page's onPassivate() method is called for each generation of eventlink, yielding a different URL each time. I thought I had found my solution! Of course, if that were true I wouldn't be writing this email. Because I'll be using this inline-editing component throughout the site, loops will often occur embedded inside a few layers of components instead of at the page level. If you convert Test.java to a component and put it into a page, then the activation context won't work any more. Activation contexts are only for pages. Now I'm back to square one. :-( Basically, I need something th