Re: t:grid coercing value when it shouldn't

2022-01-31 Thread Thiago H. de Paula Figueiredo
On Sat, Jan 29, 2022 at 8:13 PM Jonathan Meijer 
wrote:

> Thank you to both for your replies.
>

My pleasure to help!


> After reading and rereading the documentation, I'm getting a much better
> understanding of how (and how not) to use Tapestry.
>

Tapestry does have some concepts you need to understand well to use the
framework well.


> I'm trying to integrate with Cayenne without using the outdated integration
> module, and so far it's going well and I figured out my way around the
> coercion. Since my background is in WebObjects, I had to get used to this
> completely different paradigm.
>

Interesting! As far as I remember, WebObjects was an inspiration for
Tapestry in the beginning.


>
> Jonathan
>
> On Thu, Jan 27, 2022, 16:26 Thiago H. de Paula Figueiredo <
> thiag...@gmail.com> wrote:
>
> > On Fri, Jan 21, 2022 at 12:56 AM Jonathan Meijer  >
> > wrote:
> >
> > > Hi,
> > >
> >
> > Hi!
> >
> >
> > > New Tapestry user here, started with a bootstrapped 5.7.3 and
> > > experimenting.
> > >
> >
> > Welcome to Tapestry! We just released 5.8.0, by the way.
> >
> >
> > >   Delete
> > >
> >
> > I suggest using EventLink instead of ActionLink. Very similar, but easier
> > and more elegant to use.
> >
> > Delete
> >
> > Object onDelete(...) { ... }
> >
> >
> > >   What am I doing wrong?  There is really no room for error, the Blah
> > class
> > > is defined right there in the same class and the current row object has
> > > absolutely no reason to be converted to String.
> > >
> >
> > You passed an instance of Blah as the context of an ActionLink. This
> > component needs to know how to convert Blah to a string to be put in the
> > link's URL and how to do the conversion back so Tapestry can provide the
> > Blah instance to be passed to the event handler method when you click the
> > link. This is done by implementing the ValueEncoder instance for your
> class
> > then contributing it to the ValueEncoderSource service. Internally, when
> a
> > ValueEncoder isn't found for a given type, Tapestry tries to fallback on
> > using a coercion from String to type and type to String from the
> > TypeCoercer service. That's why I'm suggesting ValueEncoder and Voker is
> > suggesting a coercion and both solutions are valid. :) I just prefer the
> > ValueEncoder route in this case because it's specific for URLs (including
> > page activation context, event handler parameters, etc) and TypeCoercer
> is
> > more general-purpose conversions, specially for component and page
> > parameters (for example, Grid's source parameter receives a
> GridDataSource
> > but you can pass a List to it).
> >
> > Example of ValueEncoder usage:
> >
> > public class BlahValueEncoder implements ValueEncoder {
> > public String toClient(Blah value) {
> > (...)
> > }
> >
> > public Blah toValue(String clientValue)
> > {
> > (...)
> > }
> > }
> >
> > In AppModule:
> >
> > public static void
> > contributeValueEncoderSource(MappedConfiguration
> > configuration) {
> > configuration.add(Blah.class, new BlahValueEncoder()); // or,
> with
> > dependency injection: configuration.addInstance(Object.class,
> > BlahValueEncoder.class);
> > }
> >
> >
> >
> > >
> > > Kindly help,
> > >
> > > Jonathan
> > >
> >
> >
> > --
> > Thiago
> >
>


-- 
Thiago


Re: t:grid coercing value when it shouldn't

2022-01-29 Thread Jonathan Meijer
Thank you to both for your replies.

After reading and rereading the documentation, I'm getting a much better
understanding of how (and how not) to use Tapestry.

I'm trying to integrate with Cayenne without using the outdated integration
module, and so far it's going well and I figured out my way around the
coercion. Since my background is in WebObjects, I had to get used to this
completely different paradigm.

Jonathan

On Thu, Jan 27, 2022, 16:26 Thiago H. de Paula Figueiredo <
thiag...@gmail.com> wrote:

> On Fri, Jan 21, 2022 at 12:56 AM Jonathan Meijer 
> wrote:
>
> > Hi,
> >
>
> Hi!
>
>
> > New Tapestry user here, started with a bootstrapped 5.7.3 and
> > experimenting.
> >
>
> Welcome to Tapestry! We just released 5.8.0, by the way.
>
>
> >   Delete
> >
>
> I suggest using EventLink instead of ActionLink. Very similar, but easier
> and more elegant to use.
>
> Delete
>
> Object onDelete(...) { ... }
>
>
> >   What am I doing wrong?  There is really no room for error, the Blah
> class
> > is defined right there in the same class and the current row object has
> > absolutely no reason to be converted to String.
> >
>
> You passed an instance of Blah as the context of an ActionLink. This
> component needs to know how to convert Blah to a string to be put in the
> link's URL and how to do the conversion back so Tapestry can provide the
> Blah instance to be passed to the event handler method when you click the
> link. This is done by implementing the ValueEncoder instance for your class
> then contributing it to the ValueEncoderSource service. Internally, when a
> ValueEncoder isn't found for a given type, Tapestry tries to fallback on
> using a coercion from String to type and type to String from the
> TypeCoercer service. That's why I'm suggesting ValueEncoder and Voker is
> suggesting a coercion and both solutions are valid. :) I just prefer the
> ValueEncoder route in this case because it's specific for URLs (including
> page activation context, event handler parameters, etc) and TypeCoercer is
> more general-purpose conversions, specially for component and page
> parameters (for example, Grid's source parameter receives a GridDataSource
> but you can pass a List to it).
>
> Example of ValueEncoder usage:
>
> public class BlahValueEncoder implements ValueEncoder {
> public String toClient(Blah value) {
> (...)
> }
>
> public Blah toValue(String clientValue)
> {
> (...)
> }
> }
>
> In AppModule:
>
> public static void
> contributeValueEncoderSource(MappedConfiguration
> configuration) {
> configuration.add(Blah.class, new BlahValueEncoder()); // or, with
> dependency injection: configuration.addInstance(Object.class,
> BlahValueEncoder.class);
> }
>
>
>
> >
> > Kindly help,
> >
> > Jonathan
> >
>
>
> --
> Thiago
>


Re: t:grid coercing value when it shouldn't

2022-01-27 Thread Thiago H. de Paula Figueiredo
On Fri, Jan 21, 2022 at 12:56 AM Jonathan Meijer 
wrote:

> Hi,
>

Hi!


> New Tapestry user here, started with a bootstrapped 5.7.3 and
> experimenting.
>

Welcome to Tapestry! We just released 5.8.0, by the way.


>   Delete
>

I suggest using EventLink instead of ActionLink. Very similar, but easier
and more elegant to use.

Delete

Object onDelete(...) { ... }


>   What am I doing wrong?  There is really no room for error, the Blah class
> is defined right there in the same class and the current row object has
> absolutely no reason to be converted to String.
>

You passed an instance of Blah as the context of an ActionLink. This
component needs to know how to convert Blah to a string to be put in the
link's URL and how to do the conversion back so Tapestry can provide the
Blah instance to be passed to the event handler method when you click the
link. This is done by implementing the ValueEncoder instance for your class
then contributing it to the ValueEncoderSource service. Internally, when a
ValueEncoder isn't found for a given type, Tapestry tries to fallback on
using a coercion from String to type and type to String from the
TypeCoercer service. That's why I'm suggesting ValueEncoder and Voker is
suggesting a coercion and both solutions are valid. :) I just prefer the
ValueEncoder route in this case because it's specific for URLs (including
page activation context, event handler parameters, etc) and TypeCoercer is
more general-purpose conversions, specially for component and page
parameters (for example, Grid's source parameter receives a GridDataSource
but you can pass a List to it).

Example of ValueEncoder usage:

public class BlahValueEncoder implements ValueEncoder {
public String toClient(Blah value) {
(...)
}

public Blah toValue(String clientValue)
{
(...)
}
}

In AppModule:

public static void
contributeValueEncoderSource(MappedConfiguration
configuration) {
configuration.add(Blah.class, new BlahValueEncoder()); // or, with
dependency injection: configuration.addInstance(Object.class,
BlahValueEncoder.class);
}



>
> Kindly help,
>
> Jonathan
>


-- 
Thiago


Re: t:grid coercing value when it shouldn't

2022-01-20 Thread Volker Lamp
Hello Jonathan

New Tapestry user here, started with a bootstrapped 5.7.3 and experimenting.
>

Welcome + enjoy!


> What am I doing wrong?  There is really no room for error, the Blah class
> is defined right there in the same class and the current row object has
> absolutely no reason to be converted to String.
>

Quite the opposite - the String contained in the link needs to be coerced
back into a Blah object. Your code will render a useful link (e.g.,
http://localhost:8080/languages.delete/1). However, when the user clicks
it, Tapestry will have to coerce back the context ("1", in my example) to a
Blah object but doesn't know how, hence the error.

The solution is to contribute a Coercion, defining how to
coerce from a String value to a Blah object. Add the following to your
AppModule:

 public static void
contributeTypeCoercer(MappedConfiguration
configuration) {
Coercion coercion = new Coercion() {
public Blah coerce(String input) {
   return new Blah(Integer.valueOf(input));
}
};
CoercionTuple tuple = new CoercionTuple(String.class,
Blah.class, coercion);
configuration.add(tuple.getKey(), tuple);
}

Note Blah cannot be a static class within the Languages page class. Put
Blah in its own package (not within pages, services, or components) and it
will work.

See https://tapestry.apache.org/type-coercion.html for more details on
coercion.

Cheers,

Volker


t:grid coercing value when it shouldn't

2022-01-20 Thread Jonathan Meijer
Hi,

New Tapestry user here, started with a bootstrapped 5.7.3 and experimenting.

I tried to follow the grid example
https://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Grid.html
quite literally, however I had issues with coercion, so I simplified to try
to root out the issue.

What I now have is the simplest of table with a column for Delete links.
So the source is a List while the row is of course a Blah.
onActionFromDelete only takes a Blah as argument.  And regardless, I get
org.apache.tapestry5.ioc.internal.OperationException

Exception in method
net.xytra.cirrus.pages.blog.admin.Languages.onActionFromDelete(net.xytra.cirrus.pages.blog.admin.Languages$Blah),
parameter #1: org.apache.tapestry5.commons.util.UnknownValueException:
Could not find a coercion from type java.lang.String to type
net.xytra.cirrus.pages.blog.admin.Languages$Blah.

Here's the grid in tml:
http://tapestry.apache.org/schema/tapestry_5_4.xsd;
  xmlns:p="tapestry:parameter">

Available Languages

 
  Delete
 

Add language



And here's the class:
public class Languages {
@Property
private Blah test;

public List getLanguages() {
List list = new ArrayList();
list.add(new Blah(1));
list.add(new Blah(2));
return list;
}

public void onActionFromDelete(Blah test) {
System.err.println("--- onActionFromDelete:
test.class="+test.getClass().getName()+" and test="+test);
}

public static class Blah {
private int foo;

public Blah(int bar) {
foo = bar;
}

public String toString() {
return Integer.toString(foo);
}
}
}

What am I doing wrong?  There is really no room for error, the Blah class
is defined right there in the same class and the current row object has
absolutely no reason to be converted to String.

Kindly help,

Jonathan