Re: Activation context for a component?

2010-02-18 Thread Nathan Kopp
Hey... I did a little follow-up on this and decided to create an event-safe
loop that can restore the state of the loop variable using the page
activation context.  It's not quite perfect, but it's good enough for my
needs right now.  For my application, the resulting code ended up looking
much cleaner than the version that used only the event's context to restore
the state.

It works like this:
1) Replace your t:loop component with t:safeloop  You should specify the
t:id parameter... you'll need to know it for step 3.
2) Provide an encoder for the loop value. This parameter is optional for
t:loop but required for t:safeloop.  However, only toClient() needs to
be implemented.
3) Annotate your loop value with @LoopValue(loopid) instead of @Property,
where loopid is the t:id specified for the t:safeloop.

The t:safeloop component stores the state, and @LoopValue creates a
special getter that can restore the state.

Unfortunately, there are some additional requirements that I'd like to
remove:
1) The loop source cannot be initialized by lifecycle methods (e.g.
@BeginRender), since they won't get called.
2) You must include @Inject ComponentResources res; in your component in
order for the code generated by @LoopValue to compile.
3) The underlying page must provide simple (one-line) boilerplate
onPassivate and onActivate methods, which can be provided by inheriting from
a superclass.
4) Care must be taken if you want to also use the page activation context
for other purposes.

So far, this is working very well for my application.  I haven't tested its
compatibility with the formEncode feature of the normal Loop component.  If
other people are interested, I'm willing to share the source code... but I
probably won't have time to provide much support.

-Nathan


On Tue, Feb 16, 2010 at 11:08 PM, Nathan Kopp nathan0...@nathankopp.comwrote:

 Probably the tip I needed was this:

 When using an EventLink inside a loop, be sure that your event handling
 method does not refer to any loop variable either directly or indirectly.
  Especially be cautions of referring to parameters that may have been bound
 to any loop variable or a field of a loop variable.  If you avoid referring
 to such parameters in the eventlink's event handler (and pass the
 information to that method using the context instead), Tapestry will not
 attempt to process the parameter binding, and therefore no problem will be
 caused by the null loop variable.

 I would have found this most easily if it were located in the primary
 documentation for either EventLink or Loop in the component reference.

 Tapestry's stack trace actually did a good job highlighting the offending
 line of code, once I figured out what was happening.

 Personally, I think it would be great if there would be a way for the Loop
 component to automatically encode loop state into something like the page
 activation context and then automatically restore that point-in-time state
 when processing the eventlink request.  It would work like a blend of the
 page activation context and the formState functionality already in the Loop
 component.  However, this feature isn't really necessary as long as
 developers use the action context and avoid the gotcha that I ran into.

 -Nathan



 On Tue, Feb 16, 2010 at 10:45 PM, Kalle Korhonen 
 kalle.o.korho...@gmail.com wrote:

 Nathan, since you invested considerable amount of time debugging a
 case that seems to be just a standard event bubbling behavior, do you
 think that there is anything you'd think the framework or somebody
 could do to make the logical error in your code more visible? I know
 Tapestry documentation has often been blamed and while everything is
 there, it's scattered - if you knew what you are looking for, you'd
 find it. But on the other side, I don't know how to make it better and
 I'm sure you can see now why the old-timers annoyingly enough just
 kept repeating the same message. So, is this just a case of having to
 learn the tricks of the trade or is there something we could
 collectively do to improve things?

 Kalle


 On Tue, Feb 16, 2010 at 7:18 PM, Nathan Kopp nathan0...@nathankopp.com
 wrote:
  For future reference... this in fact turned out to be a bug in my code.
   Under normal circumstances Tapestry will NOT attempt to perform
 parameter
  bindings when processing the EventLink.  However, I accidentally left a
 line
  of code in my event handling method which referenced one of the
 parameters
  which was bound to the loop variable.  The line of code was purely
  unnecessary, but it is what caused Tapestry to process the bindings, and
  thus trigger a null pointer exception.  Once I removed that line of
 code,
  Tapestry was able to execute my method without any exceptions.  Many
 thanks
  to those who offered the recommendations that eventually led me to
 locate my
  bug and resolve the problem.
 
  -Nathan
 
 
 
  On Tue, Feb 16, 2010 at 9:32 AM, Nathan Kopp nathan0...@nathankopp.com
 wrote:
 
 
 
  On 

Re: Activation context for a component?

2010-02-16 Thread Nathan Kopp
On Mon, Feb 15, 2010 at 3:21 PM, Thiago H. de Paula Figueiredo 
thiag...@gmail.com wrote:

 On Mon, 15 Feb 2010 03:51:08 -0200, Nathan Kopp nathan0...@nathankopp.com
 wrote:

  This looks like a bug in your code, most probably by working in a T4-ish
 way in T5.


 Well, it's certainly a bug in that I'm trying to do something that T5
 doesn't seem to handle out-of-the-box.


 I disagree. A bug is something that doesn't work like it should. In this
 case, it could be the lack of a feature, not a bug. Or just lack of T5
 experience. :)


I have to laugh at the miscommunication happening here.  Otherwise I'd get
frustrated.  I was not trying to say it was a bug in Tapestry.  It's a bug
in my code in the fact that I'm trying to use a nonexistent feature.  And
I'm NOT suggesting that T5 should replay loops like T4.  Tapestry has moved
beyond that and I have too.  I am fully aware that Tapestry has introduced a
number of other features (page activation context, action context, and
formState) to take the place of replaying loops.  I just haven't found the
thing that handles this particular use case.  It actually might be there
but I just don't know.  I do have a lack of T5 experience, as you point out.
 So I am asking to see if anyone on this forum can help me to discover what
I'm missing.

Please don't get defensive and think that I'm blaming T5.  I really like T5.
 But I need to get my code to work.



  First, I need to rely on a loop variable.  Period.  The component exists
 in the context of one iteration of the loop.  Without the loop variable, the
 component wouldn't need to exist.


 I didn't meant to remove the loop variable, just not using it when handling
 events.


And how do you propose I do that?  I'm NOT using the loop variable for
handling events in my Java code.  The NPE is happening not in my code but
rather in the middle of T5's processing of the component tree and handling
parameter bindings in preparation for triggering the event from th
eventlink.  I'm using the loop variable inside the TML file as part of
passing a parameter to a component.  There's no way around that, as far as I
can see, though I am open to suggestions.



  I'll rephrase my problem like this: I
 need to rely on the loop variable, but it is null when tapestry processes
 the click from the eventlink, so I need to find a way to make it not null
 while tapestry processes that eventlink click... and specifically make it
 equal the a value for a specific iteration through the loop... the
 iteration that was occurring at the time the eventlink was being rendered.


 You'll won't have a nice solution for that because, in an event request,
 the loop is not rerendered, so the loop variable is not set. That's how T5
 works. You need to find the solution in another way, most probably using the
 context of an EventLink.


As stated before, the context for the eventlink doesn't seem to solve the
problem.  I already tried.  My event method isn't even being reached,
because the NPE happens in the middle of Tapestry's code (parameter binding)
before Tapestry can get a chance to fire my event.  I need to find a way to
make the variable NOT NULL so that Tapestry is able to process all of the
necessary parameter bindings so that it can fire my event... only then can I
start thinking about the action context for the eventlink.



  3) context for eventlink, actionlink, and form;
 #3 wont' work because my loop is not happening at the evenlink level, but
 rather at an intermediate level


 There's no such thing as an EventLink level. Events bubble from inside to
 outside. Just pass all the needed info in the context. Inside your
 component, create an event handler method for the event.


Understood.  That's what I meant to say... the level of the component into
which the EventLink is placed... but that was really long so I wrote
eventlink level instead.  I already tried this suggestion and it didn't
work.  Trust me, please.  I really did try all of these things with real
code before saying that they didn't work.  I'm not just assuming that they
won't work... I actually really did try them all.  :-)


 And don't forget that the EventLink context is independent from the page
 activation context. ComponentEventRequestParameters has two contexts: the
 page one (getPageActivationContext) and the event one ().


Understood.  That's why I mentioned both (#2 and #3) separately.  I'm well
aware that they are separate.

Please don't misunderstand the tone here... I am extremely grateful for the
desire to help me find a solution.  I love the fact that Tapestry has a
great community of users who are willing to give time to help.  But I do
know at least a bit of what I'm talking about.  I'm not looking for an RTFM
answer.  I've already read the manuals.  I've read some of the JavaDocs.
 I've read tutorials.  I've even looked at Tapestry's internal source code.
 I understand the concepts of T5 and how they differ from T4.  But none of
that has yet helped me 

Re: Activation context for a component?

2010-02-16 Thread Nathan Kopp
For future reference... this in fact turned out to be a bug in my code.
 Under normal circumstances Tapestry will NOT attempt to perform parameter
bindings when processing the EventLink.  However, I accidentally left a line
of code in my event handling method which referenced one of the parameters
which was bound to the loop variable.  The line of code was purely
unnecessary, but it is what caused Tapestry to process the bindings, and
thus trigger a null pointer exception.  Once I removed that line of code,
Tapestry was able to execute my method without any exceptions.  Many thanks
to those who offered the recommendations that eventually led me to locate my
bug and resolve the problem.

-Nathan



On Tue, Feb 16, 2010 at 9:32 AM, Nathan Kopp nathan0...@nathankopp.comwrote:



 On Mon, Feb 15, 2010 at 3:21 PM, Thiago H. de Paula Figueiredo 
 thiag...@gmail.com wrote:

 On Mon, 15 Feb 2010 03:51:08 -0200, Nathan Kopp 
 nathan0...@nathankopp.com wrote:

  This looks like a bug in your code, most probably by working in a T4-ish
 way in T5.


 Well, it's certainly a bug in that I'm trying to do something that T5
 doesn't seem to handle out-of-the-box.


 I disagree. A bug is something that doesn't work like it should. In this
 case, it could be the lack of a feature, not a bug. Or just lack of T5
 experience. :)


 I have to laugh at the miscommunication happening here.  Otherwise I'd get
 frustrated.  I was not trying to say it was a bug in Tapestry.  It's a bug
 in my code in the fact that I'm trying to use a nonexistent feature.  And
 I'm NOT suggesting that T5 should replay loops like T4.  Tapestry has moved
 beyond that and I have too.  I am fully aware that Tapestry has introduced a
 number of other features (page activation context, action context, and
 formState) to take the place of replaying loops.  I just haven't found the
 thing that handles this particular use case.  It actually might be there
 but I just don't know.  I do have a lack of T5 experience, as you point out.
  So I am asking to see if anyone on this forum can help me to discover what
 I'm missing.




Re: Activation context for a component?

2010-02-16 Thread Kalle Korhonen
Nathan, since you invested considerable amount of time debugging a
case that seems to be just a standard event bubbling behavior, do you
think that there is anything you'd think the framework or somebody
could do to make the logical error in your code more visible? I know
Tapestry documentation has often been blamed and while everything is
there, it's scattered - if you knew what you are looking for, you'd
find it. But on the other side, I don't know how to make it better and
I'm sure you can see now why the old-timers annoyingly enough just
kept repeating the same message. So, is this just a case of having to
learn the tricks of the trade or is there something we could
collectively do to improve things?

Kalle


On Tue, Feb 16, 2010 at 7:18 PM, Nathan Kopp nathan0...@nathankopp.com wrote:
 For future reference... this in fact turned out to be a bug in my code.
  Under normal circumstances Tapestry will NOT attempt to perform parameter
 bindings when processing the EventLink.  However, I accidentally left a line
 of code in my event handling method which referenced one of the parameters
 which was bound to the loop variable.  The line of code was purely
 unnecessary, but it is what caused Tapestry to process the bindings, and
 thus trigger a null pointer exception.  Once I removed that line of code,
 Tapestry was able to execute my method without any exceptions.  Many thanks
 to those who offered the recommendations that eventually led me to locate my
 bug and resolve the problem.

 -Nathan



 On Tue, Feb 16, 2010 at 9:32 AM, Nathan Kopp nathan0...@nathankopp.comwrote:



 On Mon, Feb 15, 2010 at 3:21 PM, Thiago H. de Paula Figueiredo 
 thiag...@gmail.com wrote:

 On Mon, 15 Feb 2010 03:51:08 -0200, Nathan Kopp 
 nathan0...@nathankopp.com wrote:

  This looks like a bug in your code, most probably by working in a T4-ish
 way in T5.


 Well, it's certainly a bug in that I'm trying to do something that T5
 doesn't seem to handle out-of-the-box.


 I disagree. A bug is something that doesn't work like it should. In this
 case, it could be the lack of a feature, not a bug. Or just lack of T5
 experience. :)


 I have to laugh at the miscommunication happening here.  Otherwise I'd get
 frustrated.  I was not trying to say it was a bug in Tapestry.  It's a bug
 in my code in the fact that I'm trying to use a nonexistent feature.  And
 I'm NOT suggesting that T5 should replay loops like T4.  Tapestry has moved
 beyond that and I have too.  I am fully aware that Tapestry has introduced a
 number of other features (page activation context, action context, and
 formState) to take the place of replaying loops.  I just haven't found the
 thing that handles this particular use case.  It actually might be there
 but I just don't know.  I do have a lack of T5 experience, as you point out.
  So I am asking to see if anyone on this forum can help me to discover what
 I'm missing.




-
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?

2010-02-16 Thread Nathan Kopp
Probably the tip I needed was this:

When using an EventLink inside a loop, be sure that your event handling
method does not refer to any loop variable either directly or indirectly.
 Especially be cautions of referring to parameters that may have been bound
to any loop variable or a field of a loop variable.  If you avoid referring
to such parameters in the eventlink's event handler (and pass the
information to that method using the context instead), Tapestry will not
attempt to process the parameter binding, and therefore no problem will be
caused by the null loop variable.

I would have found this most easily if it were located in the primary
documentation for either EventLink or Loop in the component reference.

Tapestry's stack trace actually did a good job highlighting the offending
line of code, once I figured out what was happening.

Personally, I think it would be great if there would be a way for the Loop
component to automatically encode loop state into something like the page
activation context and then automatically restore that point-in-time state
when processing the eventlink request.  It would work like a blend of the
page activation context and the formState functionality already in the Loop
component.  However, this feature isn't really necessary as long as
developers use the action context and avoid the gotcha that I ran into.

-Nathan



On Tue, Feb 16, 2010 at 10:45 PM, Kalle Korhonen kalle.o.korho...@gmail.com
 wrote:

 Nathan, since you invested considerable amount of time debugging a
 case that seems to be just a standard event bubbling behavior, do you
 think that there is anything you'd think the framework or somebody
 could do to make the logical error in your code more visible? I know
 Tapestry documentation has often been blamed and while everything is
 there, it's scattered - if you knew what you are looking for, you'd
 find it. But on the other side, I don't know how to make it better and
 I'm sure you can see now why the old-timers annoyingly enough just
 kept repeating the same message. So, is this just a case of having to
 learn the tricks of the trade or is there something we could
 collectively do to improve things?

 Kalle


 On Tue, Feb 16, 2010 at 7:18 PM, Nathan Kopp nathan0...@nathankopp.com
 wrote:
  For future reference... this in fact turned out to be a bug in my code.
   Under normal circumstances Tapestry will NOT attempt to perform
 parameter
  bindings when processing the EventLink.  However, I accidentally left a
 line
  of code in my event handling method which referenced one of the
 parameters
  which was bound to the loop variable.  The line of code was purely
  unnecessary, but it is what caused Tapestry to process the bindings, and
  thus trigger a null pointer exception.  Once I removed that line of code,
  Tapestry was able to execute my method without any exceptions.  Many
 thanks
  to those who offered the recommendations that eventually led me to locate
 my
  bug and resolve the problem.
 
  -Nathan
 
 
 
  On Tue, Feb 16, 2010 at 9:32 AM, Nathan Kopp nathan0...@nathankopp.com
 wrote:
 
 
 
  On Mon, Feb 15, 2010 at 3:21 PM, Thiago H. de Paula Figueiredo 
  thiag...@gmail.com wrote:
 
  On Mon, 15 Feb 2010 03:51:08 -0200, Nathan Kopp 
  nathan0...@nathankopp.com wrote:
 
   This looks like a bug in your code, most probably by working in a
 T4-ish
  way in T5.
 
 
  Well, it's certainly a bug in that I'm trying to do something that
 T5
  doesn't seem to handle out-of-the-box.
 
 
  I disagree. A bug is something that doesn't work like it should. In
 this
  case, it could be the lack of a feature, not a bug. Or just lack of T5
  experience. :)
 
 
  I have to laugh at the miscommunication happening here.  Otherwise I'd
 get
  frustrated.  I was not trying to say it was a bug in Tapestry.  It's a
 bug
  in my code in the fact that I'm trying to use a nonexistent feature.
  And
  I'm NOT suggesting that T5 should replay loops like T4.  Tapestry has
 moved
  beyond that and I have too.  I am fully aware that Tapestry has
 introduced a
  number of other features (page activation context, action context, and
  formState) to take the place of replaying loops.  I just haven't found
 the
  thing that handles this particular use case.  It actually might be
 there
  but I just don't know.  I do have a lack of T5 experience, as you point
 out.
   So I am asking to see if anyone on this forum can help me to discover
 what
  I'm missing.
 
 
 

 -
 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?

2010-02-15 Thread Inge Solvoll
I also think that you're over-complicating this. To me this sounds like a
very normal use case, looping over items and creating a form for each one.
It should just work. And it shouldn't be too many lines of complicated
code either, so the code listed here confuses me a bit.

Someone should post the rather simple code needed to do this. I don't have
the time right now :)

On Mon, Feb 15, 2010 at 12:06 AM, Thiago H. de Paula Figueiredo 
thiag...@gmail.com wrote:

 On Sun, 14 Feb 2010 17:33:43 -0200, Nathan Kopp nathan0...@nathankopp.com
 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?

2010-02-15 Thread Nathan Kopp
On Sun, Feb 14, 2010 at 3:07 PM, Thiago H. de Paula Figueiredo 
thiag...@gmail.com wrote:

 On Sun, 14 Feb 2010 00:10:02 -0200, Nathan Kopp nathan.k...@gmail.com
 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.


Understood. While I always liked the (poorly named) rewind phase, I do
understand that lots of other people disliked it and I don't mind that it is
gone. However, I'm trying to find an alternative method to achieve the same
end goal (i.e. effective handling of highly dynamic custom components nested
inside loops).


  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.


That's what I meant by deepest level... sorry for not being clearer.
 However, in my case the NPE happens one layer deeper than the EventLink
instance level.  This means that the NPE happens BEFORE my event handler has
a chance do anything with the context.  T5 bails out with the NPE before it
ever gets to the level containing the EventLink.


 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.


Well, it's certainly a bug in that I'm trying to do something that T5
doesn't seem to handle out-of-the-box.  However, that doesn't change the
fact that I need to achieve my end goal.  I'm searching for the T5-style way
of doing what I need to do.  I'd like to stay in the box as much as
possible, but I'm not afraid to step outside the box as long as the code is
pretty.


 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.


First, I need to rely on a loop variable.  Period.  The component exists in
the context of one iteration of the loop.  Without the loop variable, the
component wouldn't need to exist.  I'll rephrase my problem like this: I
need to rely on the loop variable, but it is null when tapestry processes
the click from the eventlink, so I need to find a way to make it not null
while tapestry processes that eventlink click... and specifically make it
equal the a value for a specific iteration through the loop... the iteration
that was occurring at the time the eventlink was being rendered.

From what I understand, the page activation context (onPassivate/onActivate)
IS one of the T5 ways of handling the loop variable in lieu of the rewind
phase.  In T5, you must encode the state in the next user input using the
URL or hidden form fields.  I know of three ways to do this:
1) and formState for a loop inside a form.
2) page activation context;
2) context for eventlink, actionlink, and form;

#1 won't work for me because my loop is not enclosed in a form, and the
action is an eventlink, not a form submission.
#2 won't work because my loop is not happening at the page level, but rather
at an intermediate level
#3 wont' work because my loop is not happening at the evenlink level, but
rather at an intermediate level

Note: it might be possible to get the page activation context to work... but
I need some way to communicate the info from the loop to the page activation
context, and from the page activation context back to the loop.  I might
make a custom Loop component that is capable of storing its current state
into the page activation context.  I think I can use a ComponentResources to
handle this.


  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.


Hmmm... an interesting idea.  I guess I could replace
ComponentEventLinkEncoder with a custom implementation, but that sounds a
little scary.  I think I'll try the custom Loop component that stores state
in the page activation context.  Thanks for the idea of injecting something
into my component, though... that spurred my idea of injecting
ComponentResources so that my component can communicate with the underlying
page to store state in the activation context.  :)

I hope this is starting 

Re: Activation context for a component?

2010-02-15 Thread Nathan Kopp
I agree... It sounded like a normal use case to me and I was fully expecting
it to just work.  But it didn't.  I'm not trying to complicate things...
I'm looking for an uncomplicated solution... but I have not found one yet.

All of the code necessary to run this example can be found in my original
email except for the backing-bean for the Test page and some boilerplate
code (XML headers, Java getters/setters, and imports).  Below is the Java
code for the Test page without the onPassivate/onActivate methods.  This
isn't pseudo-code... all of this is the real code that I created for myself
to isolate the issue that I'm facing.  I tried to boil the use case down to
its simplest form to make sure nothing else was happening behind the scenes
to break it.

Here's the backing-bean for the Test.tml page:

public class Test
{
@Property private Foo fooLoopVar;

// this static list takes the place of an injected JPA DAO
private static ListFoo list = new ArrayListFoo();
static {
list.add(new Foo(foo1, new Donkey(donkey1,This is Donkey 1)));
list.add(new Foo(foo2, new Donkey(donkey2,This is Donkey 2)));
list.add(new Foo(foo3, new Donkey(donkey3,This is Donkey 3)));
}

public Foo getFirstFoo() { return getFooList().get(0); }
public Foo getSecondFoo() { return getFooList().get(1); }
public Foo getThirdFoo() { return getFooList().get(2); }
public ListFoo getFooList() { return list; }
}

If you take this code combined with the code in the original email, you have
all you need to demonstrate the null pointer exception.  Add the
onPassivate/onActivate methods to make the NPE go away... but remember that
this solution doesn't work if Test is used as a component instead of a
page.

To summarize the code:
Two simple Java Beans : Foo and Donkey; Donkey contains string name and
string descr;  Foo contains string name and a reference to a Donkey.
One component that takes a Donkey as a parameter, displays the Donkey, and
contains an embedded editing form that can be turned on and off using
eventlinks internal to the component.
One page, containing a list of Foo objects, each containing a Donkey object.
 It uses the custom component to render (with editing capability) each
Donkey in the list.

-Nathan



On Mon, Feb 15, 2010 at 3:01 AM, Inge Solvoll inge.tapes...@gmail.comwrote:

 I also think that you're over-complicating this. To me this sounds like a
 very normal use case, looping over items and creating a form for each one.
 It should just work. And it shouldn't be too many lines of complicated
 code either, so the code listed here confuses me a bit.

 Someone should post the rather simple code needed to do this. I don't have
 the time right now :)

 On Mon, Feb 15, 2010 at 12:06 AM, Thiago H. de Paula Figueiredo 
 thiag...@gmail.com wrote:

  On Sun, 14 Feb 2010 17:33:43 -0200, Nathan Kopp 
 nathan0...@nathankopp.com
  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?

2010-02-15 Thread Thiago H. de Paula Figueiredo
On Mon, 15 Feb 2010 03:51:08 -0200, Nathan Kopp  
nathan0...@nathankopp.com wrote:



This looks like a bug in your code, most probably by working in a T4-ish
way in T5.


Well, it's certainly a bug in that I'm trying to do something that T5
doesn't seem to handle out-of-the-box.


I disagree. A bug is something that doesn't work like it should. In this  
case, it could be the lack of a feature, not a bug. Or just lack of T5  
experience. :)


First, I need to rely on a loop variable.  Period.  The component exists  
in the context of one iteration of the loop.  Without the loop variable,  
the

component wouldn't need to exist.


I didn't meant to remove the loop variable, just not using it when  
handling events.



I'll rephrase my problem like this: I
need to rely on the loop variable, but it is null when tapestry processes
the click from the eventlink, so I need to find a way to make it not null
while tapestry processes that eventlink click... and specifically make it
equal the a value for a specific iteration through the loop... the  
iteration that was occurring at the time the eventlink was being  
rendered.


You'll won't have a nice solution for that because, in an event request,  
the loop is not rerendered, so the loop variable is not set. That's how T5  
works. You need to find the solution in another way, most probably using  
the context of an EventLink.



3) context for eventlink, actionlink, and form;
#3 wont' work because my loop is not happening at the evenlink level, but
rather at an intermediate level


There's no such thing as an EventLink level. Events bubble from inside to  
outside. Just pass all the needed info in the context. Inside your  
component, create an event handler method for the event.


And don't forget that the EventLink context is independent from the page  
activation context. ComponentEventRequestParameters has two contexts: the  
page one (getPageActivationContext) and the event one ().


--
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?

2010-02-14 Thread P . Stavrinides
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.  

t:loop source=fooList value=fooLoopVar
Here's a foo: ${fooLoopVar.name}br/
t:viewDonkeyInlineEdit foo=fooLoopVar/br/br/
/t:loop


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: t:textfield value=foo.donkey.descr size=50/

Its that simple.

Peter

 
- Original Message -
From: Nathan Kopp nathan.k...@gmail.com
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===
!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN 
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd;
t:container xmlns:t=http://tapestry.apache.org/schema/tapestry_5_1_0.xsd;
xmlns:p=tapestry:parameter
Donkey's name: ${donkey.name}br/
t:if test=editing
t:form
t:errors/
Description: t:textfield value=editDonkey.descr size=50/
t:submit value=Save event=saveEditDonkey/ t:eventlink
event=cancelEditDonkeyCancel/t:eventlinkbr/
/t:form
p:else
Description: ${donkey.descr} t:eventlink
event=startEditDonkeyEdit/t:eventlinkbr/
/p:else
/t:if
/t:container
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 ==
html xmlns:t=http://tapestry.apache.org/schema/tapestry_5_1_0.xsd;
  xmlns:p=tapestry:parameter

Here's a foo: ${firstFoo.name}br/
t:viewDonkeyInlineEdit donkey=firstFoo.donkey/br/br/

Here's a foo: ${secondFoo.name}br/
t:viewDonkeyInlineEdit donkey=secondFoo.donkey/br/br/

Here's a foo: ${thirdFoo.name}br/
t:viewDonkeyInlineEdit donkey=thirdFoo.donkey/br/
/html
=

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) =
html xmlns:t=http://tapestry.apache.org/schema/tapestry_5_1_0.xsd;
   xmlns:p=tapestry:parameter
t:loop source=fooList value=fooLoopVar
  

Re: Activation context for a component?

2010-02-14 Thread Thiago H. de Paula Figueiredo

Hi!

On Sun, 14 Feb 2010 00:10:02 -0200, Nathan Kopp nathan.k...@gmail.com  
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?

2010-02-14 Thread Nathan Kopp
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, p.stavrini...@albourne.com 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.

t:loop source=fooList value=fooLoopVar
Here's a foo: ${fooLoopVar.name}br/
 t:viewDonkeyInlineEdit foo=fooLoopVar/br/br/
/t:loop


 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: t:textfield value=foo.donkey.descr size=50/

 Its that simple.

 Peter


 - Original Message -
 From: Nathan Kopp nathan.k...@gmail.com
 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?

2010-02-14 Thread Thiago H. de Paula Figueiredo
On Sun, 14 Feb 2010 17:33:43 -0200, Nathan Kopp  
nathan0...@nathankopp.com 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