Unless I'm mistaken (which is possible), tapestry will create two distinct components when building the component trees, and they will not have access to the same variable.
So a template like: <html ...> <t:widget/> <t:widget/> <t:widget/> </html> Would yield three log messages of "rendered 1 time". -- Robert Hailey On 2012/11/28 (Nov), at 5:08 PM, Josh Canfield wrote: > Hi Robert. > > Are you looking for a reason to use PreThreadValue? Or do you just want to > have a page/component level property that you can access for the life of > the request? > > In a page or component you just declare the variable and let tapestry do > it's magic in the background. > > private int widgetRenderCount = 0; > > void afterRender() { > ++widgetRenderCount; > log.debug("{} widgets have now rendered in this request!", > count); > } > > > If you want to use it in a singleton service then you need to do the > plumbing. > > Josh > > > On Wed, Nov 28, 2012 at 2:32 PM, Robert Hailey <rhai...@allogy.com> wrote: > >> >> I've read the "everyone out of the pool" blog post, but have not been able >> to find an example of how to best use per-thread value on a page or service >> (seems like what's provided is an internal tapestry case). >> >> As a (lazy?) tapestry developer, my first thought is to try this: >> >> @Inject >> private PerThreadValue<Integer> widgetRenderCount; >> >> Which probably isn't the expected use-case, because it doesn't work: "no >> service implements PerThreadValue interface" (or thereabout) >> >> I then though I was probably looking one abstraction layer too deep (as >> the article does talk about transparent perthread access)... so then I >> thought of this: >> >> @Inject >> @PerThread >> private Integer widgetRenderCount; >> >> Which made a degree of sense because "Persist" is deprecated, but no such >> annotation exists. >> >> So then I thought I could create my own perthreadvalue-providing service >> (to realize the first example) like this: >> >> public void contributeMasterObjectProvider( >> OrderedConfiguration<ObjectProvider> configuration, >> final PerthreadManager perthreadManager >> ) >> { >> configuration.add("PerThreadValue", new ObjectProvider() { >> public <T> T provide(Class<T> tClass, AnnotationProvider >> annotationProvider, ObjectLocator objectLocator) { >> return (T)perthreadManager.createValue(); >> } >> }); >> } >> >> ... but that fails due to the "MasterObjectProvider somehow depends on >> itself" error message and what's probably a blindingly-obvious lack of >> knowledge on my part concerning how tapestry actually provides virtually >> interfaced objects. >> >> So now I have fallen back to patterns like this, that seem to work, but >> seem to be much clunkier than I would expect: >> >> @Inject >> private PerThreadManager perThreadManager; >> private static PerThreadValue<Integer> widgetRenderCount; >> >> void afterRender() { >> if (widgetRenderCount==null) { >> widgetRenderCount=perthreadManager.createValue(); >> } >> int count=widgetRenderCount.get(0); >> count++; >> log.debug("{} widgets have now rendered in this request!", >> count); >> widgetRenderCount.set(count); >> } >> >> >> Am I missing something? If so, how is PerThreadValue intended to be used? >> >> -- >> Robert Hailey >> >> >>