Hi, I am still using Tapestry 5.2.6, so I am not sure what changed in Tapestry 5.3. However I believe, that "field.inject(new Site());" line is wrong. It inserts a constant value to the field. I believe (if online documentation is still relevant) that you should use field.setConduit() instead, and provide FieldConduit<Site> instance that selects in get() method a correct Site based on a request.
See http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/plastic/PlasticField.html#setConduit(org.apache.tapestry5.plastic.FieldConduit) http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/plastic/FieldConduit.html However, I would recommend avoiding using such advanced techniques with a beta version of Tapestry. More mundane approach with normal injection of a service, that has a single method returning Site would work on all versions of Tapestry 5 without any headaches. Best regards, Cezary On Wed, Oct 5, 2011 at 7:07 PM, Sonny Gill <sonny.pub...@gmail.com> wrote: > Hi guys, > > I tried this a few days ago, ran into a few problems, and then tried again > today. > > Unfortunately I could not get this to work. > > On changing the method name to contributeSiteInjectionProvider, it was > detected by Tapestry, and the provider and FieldValueConduit is created, > but > the ReadOnlyFieldValueConduit.get() was never called. > > Then I upgraded to Tapestry 5.3-beta-16, and it looks > like ReadOnlyFieldValueConduit has been removed. > > > Finally, I tried to follow > http://wiki.apache.org/tapestry/JEE-Annotationand added the following > :- > > public class SiteAnnotationWorker implements ComponentClassTransformWorker2 > { > > @Override > public void transform(PlasticClass plasticClass, TransformationSupport > transformationSupport, MutableComponentModel mutableComponentModel) { > for (PlasticField field : > plasticClass.getFieldsWithAnnotation(Inject.class)) { > if (Site.class.getName().equals(field.getTypeName())) { > field.inject(new Site()); > field.claim(Inject.class); > } > } > } > > } > > and in AppModule, > > @Contribute(ComponentClassTransformWorker2.class) > @Primary > public static void > > provideClassTransformWorkers(OrderedConfiguration<ComponentClassTransformWorker2> > configuration) { > configuration.addInstance("site", SiteAnnotationWorker.class, > "before:Property"); > } > > With this, the field is injected correctly (great!). > > The problem now is that Tapestry continues to keep the injected object > around and injects the same object for every request. > This is probably correct for the use case > for ComponentClassTransformWorker(s), but I need to inject a different > object on each HTTP request. > > How can I achieve that? > > Again.. I am very thankful for the help received so far. I would have been > completely lost without it. > > > Best regards, > Sonny > > > > > On Wed, Sep 28, 2011 at 2:59 PM, Cezary Biernacki <cezary...@gmail.com > >wrote: > > > Hi, > > I built a website with similar requirements, and it is not hard to do > that > > with Tapestry. A simple approach is to built a service that returns > correct > > 'Site' instance, and use it everywhere where you need to 'site'. > > > > So instead having > > private Site site; > > > > you would have, e.g. > > @Inject > > private SiteLookup lookup; > > > > > > and instead using 'site', you would use 'lookup.getSite()'. SiteLookup > can > > depend on 'Request' service, so there is no need to pass it as argument > to > > getSite() method. > > > > But, if you are not afraid of some more advanced machinery, you can > > contribute your own InjectionProvider, and inject 'Site' directly, > > something > > like: > > > > > > public class SiteInjectionProvider implements InjectionProvider { > > private final Request request; > > > > public SiteInjectionProvider (Request request) { > > this.request = request; > > } > > > > @Override > > public boolean provideInjection(String fieldName, > > @SuppressWarnings("rawtypes") Class fieldType, > > ObjectLocator locator, ClassTransformation transformation, > > MutableComponentModel componentModel) { > > > > if (!Site.class.equals(fieldType)) { > > return false; > > } > > > > TransformField field = transformation.getField(fieldName); > > > > ComponentValueProvider<FieldValueConduit> provider = > > createProvider(fieldName); > > > > field.replaceAccess(provider); > > > > return true; > > } > > > > private ComponentValueProvider<FieldValueConduit> createProvider(final > > String fieldName) { > > > > return new ComponentValueProvider<FieldValueConduit>() { > > > > public FieldValueConduit get(final ComponentResources > resources) > > { > > > > return new ReadOnlyFieldValueConduit(resources, fieldName) > { > > public Object get() { > > return ....; // <--- here implement selecting > > correct Site based on Request > > } > > }; > > } > > > > }; > > } > > > > } > > > > > > Remember to contribute your injection provider in your AppModule > > > > @Contribute(InjectionProvider.class) > > public static void > > setupInjectingSite(OrderedConfiguration<InjectionProvider> configuration) > { > > configuration.addInstance("site", SiteInjectionProvider .class, > > "after:Default"); > > > > } > > > > > > After that, you would be able to use > > @Inject > > private Site site; > > > > on your pages and components. > > > > Best regards, > > Cezary > > > > > > > > > > > > > > > > On Wed, Sep 28, 2011 at 2:39 PM, Sonny Gill <sonny.pub...@gmail.com> > > wrote: > > > > > Thanks Barry. > > > > > > Site is a domain layer object and knows nothing about Request/Response > > etc. > > > There will be a limited number of Site objects, one for each site > > > supported, > > > created and configured at the application start up. > > > > > > I could set it up as a Service for Tapestry application. > > > But can I then provide a Service lookup method that can look at the > > current > > > request, get the correct Site using some criteria, and hand it over to > > > Tapestry to inject into the page for current request? > > > > > > So, something like :- > > > > > > public Service lookupSiteService(Request request) { > > > String id = ...get site id from the request in some way...; > > > > > > SiteRepository repository = ...; // Can I inject an implementation of > > > SiteRepository (also a domain layer object) here? > > > > > > return repository.getSite(id); > > > } > > > > > > > > > > > > -- > http://sonnygill.net/ > http://twitter.com/sonny_gill > http://www.linkedin.com/in/sonnygill >