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 <jonny.mei...@gmail.com> > 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. > > > > <t:actionlink t:id="delete" context="test">Delete</t:actionlink> > > > > I suggest using EventLink instead of ActionLink. Very similar, but easier > and more elegant to use. > > <t:eventlink event="delete" context="test">Delete</t:eventlink> > > 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<Blah> { > public String toClient(Blah value) { > (...) > } > > public Blah toValue(String clientValue) > { > (...) > } > } > > In AppModule: > > public static void > contributeValueEncoderSource(MappedConfiguration<Class, Object> > configuration) { > configuration.add(Blah.class, new BlahValueEncoder()); // or, with > dependency injection: configuration.addInstance(Object.class, > BlahValueEncoder.class); > } > > > > > > > Kindly help, > > > > Jonathan > > > > > -- > Thiago >