On Wednesday, November 28, 2012, Robert Hailey 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 always. Some of the best examples are in the Tapestry source code.
> As a (lazy?) tapestry developer, my first thought is to try this: > > @Inject > private PerThreadValue<Integer> widgetRenderCount; > > Although Tapestry could be extended to support this pattern, it is not so out of the box. > 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? The path of least resistance is to define your own service for tracking this kind of per-request information. You can then inject this service into any page or component that wants it. The scope annotation can be used to configure that service as per-thread http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Scope.html http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/ScopeConstants.html > > -- > Robert Hailey > > > -- Howard M. Lewis Ship Creator of Apache Tapestry The source for Tapestry training, mentoring and support. Contact me to learn how I can get you up and productive in Tapestry fast! (971) 678-5210 http://howardlewisship.com