Re: Newbie help with For and TextField components

2007-01-11 Thread Jim Downing

Hi Daniel,

thanks very much for this, it makes things much clearer (best 
explanation of it I've seen by a long chalk!).


I'll take your advice and create a holder object for my string that uses 
a UUID to identify the strings.


Thanks!

jim

Daniel Tabuenca wrote:

Eventually I'm going to be saving the values in RDF - the values won't
have a persistent key, they're just literal values. I'm also keen to
avoid using any session persistence but will do if it's necessary. Can
tapestry deal with simple values that don't have identity in this way?


To understand this you need to know what that key is really used for.

Say I have a Person Object...

public class Person(){

public String name;
public String id;
}

and two person Object sin a list;

Person bob;
Person alice;
List personList;

bob.setName("Bob");
bob.setId("1");

alice.setName("Alice");
alice.setId("2");

personList.add(bob);
personList.add(alice);



Now... when if I set my keyExpression to be person.id when tapestry
renders out the form it stores a hidden field with the ids in order..
in this case it would have "1" and "2". Why is this important?  Well
you have to understand what happens during a rewind. It is nothing
magical really and the simplistic way to explain is that your page
just renders out again but with the form bindings reversed so in
your case



when it gets to that input field... instead of reading the "value"
parameter with getName() it simply writes that paremeter with
setName().


so say I got the page and it has a list of my current users

* [ BOB ]
* [ALICE ]

now I want to change Bob's name to Robert so I edit.

* [ROBERT]
* [ALICE]

and hit submit..

What happens if while I was changing the name on the form.. someone
somehow change the original person list so that the names are
backwards so the objects are { alice, bob}. If tapestry allowed it
this would be bad! Because you meant to change Bob's name but as far
as Tapestry is concerned you just instructed it to set the name on the
first item on the list to "Robert". And if the order on the list was
somehow changed it's your Alice object that will get it's name change.

This is why tapestry stores extra information in the hidden field.
What it does, is before actually calling setName() it will check that
your keyExpression submitted with the form matches the keyExpression
of the object from the list. If the list got changed this will be
different and tapestry will detect this and throw you an exception so
you don't accidentally delete or modify th wrong object.

Of course... if you don't have a real key you can either make one up.
Or if your oject converts automatically to a string tapestry will just
store that in the hidden fields. Of course, if you don't care about
what I just described or you know for certain that nobody will modify
the list, you could set keyExpression to something constant so it
always matches no matter what.

I hope this explenation was useful. The whole rewind idea seemed
magical to me until someone explained it to me like this.



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



Re: Newbie help with For and TextField components

2007-01-10 Thread Daniel Tabuenca

Eventually I'm going to be saving the values in RDF - the values won't
have a persistent key, they're just literal values. I'm also keen to
avoid using any session persistence but will do if it's necessary. Can
tapestry deal with simple values that don't have identity in this way?


To understand this you need to know what that key is really used for.

Say I have a Person Object...

public class Person(){

public String name;
public String id;
}

and two person Object sin a list;

Person bob;
Person alice;
List personList;

bob.setName("Bob");
bob.setId("1");

alice.setName("Alice");
alice.setId("2");

personList.add(bob);
personList.add(alice);



Now... when if I set my keyExpression to be person.id when tapestry
renders out the form it stores a hidden field with the ids in order..
in this case it would have "1" and "2". Why is this important?  Well
you have to understand what happens during a rewind. It is nothing
magical really and the simplistic way to explain is that your page
just renders out again but with the form bindings reversed so in
your case



when it gets to that input field... instead of reading the "value"
parameter with getName() it simply writes that paremeter with
setName().


so say I got the page and it has a list of my current users

* [ BOB ]
* [ALICE ]

now I want to change Bob's name to Robert so I edit.

* [ROBERT]
* [ALICE]

and hit submit..

What happens if while I was changing the name on the form.. someone
somehow change the original person list so that the names are
backwards so the objects are { alice, bob}. If tapestry allowed it
this would be bad! Because you meant to change Bob's name but as far
as Tapestry is concerned you just instructed it to set the name on the
first item on the list to "Robert". And if the order on the list was
somehow changed it's your Alice object that will get it's name change.

This is why tapestry stores extra information in the hidden field.
What it does, is before actually calling setName() it will check that
your keyExpression submitted with the form matches the keyExpression
of the object from the list. If the list got changed this will be
different and tapestry will detect this and throw you an exception so
you don't accidentally delete or modify th wrong object.

Of course... if you don't have a real key you can either make one up.
Or if your oject converts automatically to a string tapestry will just
store that in the hidden fields. Of course, if you don't care about
what I just described or you know for certain that nobody will modify
the list, you could set keyExpression to something constant so it
always matches no matter what.

I hope this explenation was useful. The whole rewind idea seemed
magical to me until someone explained it to me like this.

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



Re: Newbie help with For and TextField components

2007-01-10 Thread Daniel Tabuenca

Well it's because you are using strings directly. Here's what the
equivalent of what is going on in JAVA:

List names  = NAMES;

for( String name : names ){
name = " NEW VALUE FROM INPUT FIELD";
// but strings are immutable so name has a new string reference and
does not modify
// the one that is part of the list.
}

What happens is your new name is stored only in the "name" property
and never makes it back to your list try printing out getName()
and you will see that it is probably set to your last name on the
list.







On 1/10/07, Jim Downing <[EMAIL PROTECTED]> wrote:

Hi Daniel,

thanks for the help!

Daniel Tabuenca wrote:
> The Chart example the plotValues property is persisted:
>
>  class="org.apache.tapestry.workbench.chart.ChartPage">
>
>  
>
> ...
>
>
> I am assuming you are not persisting since from your logs:
>
> 9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
> Rewind? true
> 9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names
> list

It's true, I wasn't persisting them. To be ultra-simplistic I've done
this by storing them back in a static field: -

Home.java:
...
public static List NAMES = new ArrayList();
public void pageBeginRender(PageEvent event) {
LOG.info("Begin render. Rewind? " +
getRequestCycle().isRewinding() +". Names: "+ getNames());
LOG.info("Initializing names list to "+ NAMES);
setNames(NAMES);
}

public void submit() {
LOG.info("Submitted. List is: " + getNames());
NAMES = getNames();
}

public void add() {
LOG.info("Adding a blank name to " + getNames());
List nms = getNames();
nms.add("");
setNames(nms);
}
...


Unfortunately that doesn't seem to be at the heart of the problem - the
list now grows as desired when the 'add' listener is called, but the
values in the list aren't changed. It looks like the form values aren't
correctly set after the rewind, e.g. in the log excerpt below I'd be
expecting to see the (non-blank) form values in the message at the
highlighted point: -

 INFO  com.example.pages.Home  - Begin render. Rewind? true.  Names: null
 INFO  com.example.pages.Home  - Initializing names list to [, , ]
--> INFO  com.example.pages.Home  - Submitted. List is: [, , ] <--
 INFO  com.example.pages.Home  - Begin render. Rewind? false. Names: [, , ]
 INFO  com.example.pages.Home  - Initializing names list to [, , ]

Eventually I'm going to be saving the values in RDF - the values won't
have a persistent key, they're just literal values. I'm also keen to
avoid using any session persistence but will do if it's necessary. Can
tapestry deal with simple values that don't have identity in this way?

Thanks,

jim



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




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



Re: Newbie help with For and TextField components

2007-01-10 Thread Jim Downing

Hi Firas,

Firas Adiler wrote:

I'm a bit puzzled myself, but how did you manage to run the app without
providing setters for 'idx' and 'name' fields:
public abstract void setIdx(int idx)
public abstract void setName(String name)?
  


Seems to work fine just defining the getter in other situations - I 
think the setter appears by reflection magic.


jim

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



Re: Newbie help with For and TextField components

2007-01-10 Thread Jim Downing
Hi Daniel, 


thanks for the help!

Daniel Tabuenca wrote:

The Chart example the plotValues property is persisted:

class="org.apache.tapestry.workbench.chart.ChartPage">


 

...


I am assuming you are not persisting since from your logs:

9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names 
list


It's true, I wasn't persisting them. To be ultra-simplistic I've done 
this by storing them back in a static field: -


Home.java:
...
   public static List NAMES = new ArrayList();
   public void pageBeginRender(PageEvent event) {
   LOG.info("Begin render. Rewind? " + 
getRequestCycle().isRewinding() +". Names: "+ getNames());

   LOG.info("Initializing names list to "+ NAMES);
   setNames(NAMES);
   }

   public void submit() {
   LOG.info("Submitted. List is: " + getNames());
   NAMES = getNames();
   }

   public void add() {
   LOG.info("Adding a blank name to " + getNames());
   List nms = getNames();
   nms.add("");
   setNames(nms);
   }
...


Unfortunately that doesn't seem to be at the heart of the problem - the 
list now grows as desired when the 'add' listener is called, but the 
values in the list aren't changed. It looks like the form values aren't 
correctly set after the rewind, e.g. in the log excerpt below I'd be 
expecting to see the (non-blank) form values in the message at the 
highlighted point: -


INFO  com.example.pages.Home  - Begin render. Rewind? true.  Names: null
INFO  com.example.pages.Home  - Initializing names list to [, , ]
--> INFO  com.example.pages.Home  - Submitted. List is: [, , ] <--
INFO  com.example.pages.Home  - Begin render. Rewind? false. Names: [, , ]
INFO  com.example.pages.Home  - Initializing names list to [, , ]

Eventually I'm going to be saving the values in RDF - the values won't 
have a persistent key, they're just literal values. I'm also keen to 
avoid using any session persistence but will do if it's necessary. Can 
tapestry deal with simple values that don't have identity in this way?


Thanks,

jim



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



Re: Newbie help with For and TextField components

2007-01-10 Thread Daniel Tabuenca

The Chart example the plotValues property is persisted:



 

...


I am assuming you are not persisting since from your logs:

9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list

The list gest reinitialized on each request.


I think you may be misunderstanding the @For loop. @For inside a form
will not create a List or populate it for you. @For works with an
existing list and in your case the existing list is a new list on each
beginRender. @For then iterates over an empty list which means nothing
inside it will ever get executed (all your form input fields never get
rewound). The keyExpression is used only to verify that the list that
you are working with  has not changed since you rendered the page. In
your case it HAS! When you rendered the page originally your list had
a blank name in it. On the rewind it has no elements. Maybe tapestry
should be smarter and throw an error when the size of the list doesn't
match the size from when it was rendered.






On 1/10/07, Jim Downing <[EMAIL PROTECTED]> wrote:

Hi Jesse,

Jesse Kuhnert wrote:
> I think the problem with this approach is that the For component has
> no way of uniquely identifying your list values.
>
> I would try using the keyExpression or converter parameters of the For
> component to do this instead.
> http://tapestry.apache.org/tapestry4.1/components/general/for.html

Thanks for the pointers, but I'm still having problems, using either a
custom converter or a keyExpression (using "toString()"). As I
understand it either of these methods rely on there being a single
reference to the object that doesn't change between requests. This
obviously doesn't exist for value objects.

What I'm finding confusing is that this looks to me just like the
example in the charts pane of the tapestry workbench demo; there a list
of PlotValues is edited without keyExpresssion or a converter. Why is
this different?

Would a reasonable hack be to bind the value of the text field input to
a property with a concrete setter that used the @For index to build the
new list items manually?

Thanks,

jim

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




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



RE: Newbie help with For and TextField components

2007-01-10 Thread Firas Adiler
Jim,

I'm a bit puzzled myself, but how did you manage to run the app without
providing setters for 'idx' and 'name' fields:
public abstract void setIdx(int idx)
public abstract void setName(String name)?

Regards,



-Original Message-
From: Jim Downing [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, January 09, 2007 3:47 PM
To: users@tapestry.apache.org
Subject: Newbie help with For and TextField components

Hi,

I'm trying to get some simple list editing working using For and TextField
but not having much luck.

Home.html: -

http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en"> 
Example app   Hello
world! List of names:

1  

Home.java

public abstract class Home extends BasePage implements
PageBeginRenderListener {

private static final Logger LOG = Logger.getLogger(Home.class);

public void pageBeginRender(PageEvent event) {
LOG.info("Begin render. Rewind? " +
getRequestCycle().isRewinding());
if(getNames()== null) {
LOG.info("Initializing names list");
setNames(new ArrayList());
}
}

public void submit() {
LOG.info("Submitted. List is: " + getNames());
}

public void add() {
LOG.info("Adding a blank name to "+ getNames());
List nms = getNames();
nms.add("");
setNames(nms);
}
   
public abstract List getNames();

public abstract void setNames(List nms);

public abstract String getName();

public abstract int getIdx();
}

When I click the "Add" button I get: -

9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render. 
Rewind? true
9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9627423 [btpool0-3] INFO  com.example.pages.Home  - Adding a blank name to
[]
9627424 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is: 
[]
9627424 [btpool0-3] INFO  com.example.pages.Home  - Begin render. 
Rewind? false

Then changing the value in the form input and clicking submit produces
this: -

9638858 [btpool0-3] INFO  com.example.pages.Home  - Begin render. 
Rewind? true
9638858 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9638859 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is: []
9638859 [btpool0-3] INFO  com.example.pages.Home  - Begin render. 
Rewind? false

I'm puzzled - why hasn't the list been populated from the TextFields in the
For loop?

Any pointers gratefully received.

cheers,
jim



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



Re: Newbie help with For and TextField components

2007-01-10 Thread Daniel Tabuenca

I don't get it. What are you trying to do? You aren't persisting your
list anywhere so at each render or rewind your lists starts off
null. so by the time it gets to the @For loop the @For loop has
nothing to iterate over. Am I missing something?




On 1/9/07, Jim Downing <[EMAIL PROTECTED]> wrote:

Hi,

I'm trying to get some simple list editing working using For and
TextField but not having much luck.

Home.html: -

http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">

Example app


Hello world!
List
of names:

1 






Home.java

public abstract class Home extends BasePage implements
PageBeginRenderListener {

private static final Logger LOG = Logger.getLogger(Home.class);

public void pageBeginRender(PageEvent event) {
LOG.info("Begin render. Rewind? " +
getRequestCycle().isRewinding());
if(getNames()== null) {
LOG.info("Initializing names list");
setNames(new ArrayList());
}
}

public void submit() {
LOG.info("Submitted. List is: " + getNames());
}

public void add() {
LOG.info("Adding a blank name to "+ getNames());
List nms = getNames();
nms.add("");
setNames(nms);
}

public abstract List getNames();

public abstract void setNames(List nms);

public abstract String getName();

public abstract int getIdx();
}

When I click the "Add" button I get: -

9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9627423 [btpool0-3] INFO  com.example.pages.Home  - Adding a blank name
to []
9627424 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is:
[]
9627424 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? false

Then changing the value in the form input and clicking submit produces
this: -

9638858 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9638858 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9638859 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is: []
9638859 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? false

I'm puzzled - why hasn't the list been populated from the TextFields in
the For loop?

Any pointers gratefully received.

cheers,
jim


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




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



Re: Newbie help with For and TextField components

2007-01-10 Thread Jim Downing

Hi Jesse,

Jesse Kuhnert wrote:

I think the problem with this approach is that the For component has
no way of uniquely identifying your list values.

I would try using the keyExpression or converter parameters of the For
component to do this instead.
http://tapestry.apache.org/tapestry4.1/components/general/for.html


Thanks for the pointers, but I'm still having problems, using either a 
custom converter or a keyExpression (using "toString()"). As I 
understand it either of these methods rely on there being a single 
reference to the object that doesn't change between requests. This 
obviously doesn't exist for value objects.


What I'm finding confusing is that this looks to me just like the 
example in the charts pane of the tapestry workbench demo; there a list 
of PlotValues is edited without keyExpresssion or a converter. Why is 
this different?


Would a reasonable hack be to bind the value of the text field input to 
a property with a concrete setter that used the @For index to build the 
new list items manually?


Thanks,

jim

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



Re: Newbie help with For and TextField components

2007-01-10 Thread Jesse Kuhnert

I think the problem with this approach is that the For component has
no way of uniquely identifying your list values.

I would try using the keyExpression or converter parameters of the For
component to do this instead.
http://tapestry.apache.org/tapestry4.1/components/general/for.html



On 1/9/07, Jim Downing <[EMAIL PROTECTED]> wrote:

Hi,

I'm trying to get some simple list editing working using For and
TextField but not having much luck.

Home.html: -

http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">

Example app


Hello world!
List
of names:

1 






Home.java

public abstract class Home extends BasePage implements
PageBeginRenderListener {

private static final Logger LOG = Logger.getLogger(Home.class);

public void pageBeginRender(PageEvent event) {
LOG.info("Begin render. Rewind? " +
getRequestCycle().isRewinding());
if(getNames()== null) {
LOG.info("Initializing names list");
setNames(new ArrayList());
}
}

public void submit() {
LOG.info("Submitted. List is: " + getNames());
}

public void add() {
LOG.info("Adding a blank name to "+ getNames());
List nms = getNames();
nms.add("");
setNames(nms);
}

public abstract List getNames();

public abstract void setNames(List nms);

public abstract String getName();

public abstract int getIdx();
}

When I click the "Add" button I get: -

9627410 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9627411 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9627423 [btpool0-3] INFO  com.example.pages.Home  - Adding a blank name
to []
9627424 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is:
[]
9627424 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? false

Then changing the value in the form input and clicking submit produces
this: -

9638858 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? true
9638858 [btpool0-3] INFO  com.example.pages.Home  - Initializing names list
9638859 [btpool0-3] INFO  com.example.pages.Home  - Submitted. List is: []
9638859 [btpool0-3] INFO  com.example.pages.Home  - Begin render.
Rewind? false

I'm puzzled - why hasn't the list been populated from the TextFields in
the For loop?

Any pointers gratefully received.

cheers,
jim


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





--
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

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