> > On May 12, 2021, at 1:50 PM, D Tim Cummings <t...@triptera.com.au.INVALID> > wrote: > > Does anyone know of any good open-source Cayenne Tapestry apps that show > best practice and latest features for using these two frameworks > together? Most of the Tapestry examples use Hibernate. > > Tim
Hi Tim, Not aware of any other than this ancient one [1] (I see your commits in there :)) . Also you probably know that Bootique supports Tapestry [2], and that's what we are on. As for the Tapestry part, we are using vanilla Tapestry functionality for the most part. Looking at my own (non-open source) Tapestry modules [3,4], the only Cayenne extension is encoders for Persistent and ObjectId [5], so that objects can be encoded/decoded to/from page URL parameters. So our entire integration can fit in an email message, and that's the beauty of it :) Andrus ----- [1] https://github.com/andrus/wowodc13 [2] https://github.com/bootique/bootique-tapestry [3] Bootique config: TapestryModule.extend(binder).addTapestryModule(TapestryModule.class) // this ensures that T5 JS/CSS only includes when the page or components explicitly import parts of // the stack .setSymbol(SymbolConstants.INCLUDE_CORE_STACK, "false") // turn off Tapestry Bootstrap .. we don't have much choice in the matter of the root selection // it has to be one of the standard T5 locations. "META-INF/asset" is the most neutral one.. .setSymbol(SymbolConstants.BOOTSTRAP_ROOT, "classpath:/META-INF/assets") .setSymbol(SymbolConstants.OMIT_GENERATOR_META, "true"); [4] Tapestry module loaded via Bootique: public class TapestryModule { public void contributeValueEncoderSource( MappedConfiguration<Class, ValueEncoderFactory> configuration, PersistentCoder persistentCoder, ObjectIdCoder objectIdCoder) { configuration.add(Persistent.class, c -> persistentCoder); configuration.add(ObjectId.class, c -> objectIdCoder); } } [5] ID coders import org.apache.cayenne.ObjectId; import org.apache.cayenne.lifecycle.id.IdCoder; import org.apache.tapestry5.ValueEncoder; public class ObjectIdCoder implements ValueEncoder<ObjectId> { private IdCoder idCoder; public ObjectIdCoder(IdCoder idCoder) { this.idCoder = idCoder; } @Override public String toClient(ObjectId value) { return idCoder.getStringId(value); } @Override public ObjectId toValue(String clientValue) { return idCoder.getObjectId(clientValue); } } import org.apache.cayenne.Cayenne; import org.apache.cayenne.ObjectContext; import org.apache.cayenne.Persistent; import org.apache.cayenne.lifecycle.id.IdCoder; import org.apache.tapestry5.ValueEncoder; public class PersistentCoder implements ValueEncoder<Persistent> { private IdCoder idCoder; private Supplier<ObjectContext> contextSupplier; public PersistentCoder(IdCoder idCoder, Supplier<ObjectContext> contextSupplier) { this.idCoder = idCoder; this.contextSupplier = contextSupplier; } @Override public String toClient(Persistent value) { return idCoder.getStringId(value); } @Override public Persistent toValue(String clientValue) { // TODO: should we be using ObjectIdQuery with caching? return (Persistent) Cayenne.objectForPK( contextSupplier.get(), idCoder.getObjectId(clientValue)); } }