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
>

Reply via email to