Thanks that's really useful and does exactly what we want, it's not a problem
for us to make all our controller interfaces extend a marker type. 

Cheers

Dave


joshcanfield wrote:
> 
> I'm assuming that your users aren't uploading the components or the
> services, just the pages?
> 
> If you use a common interface for your services you can use that class
> to access the registry.
> 
> I built a quick binding factory and wrote a couple services for it to
> use here is the implementation:
> 
> public class ServiceBindingFactory implements BindingFactory {
>    private BindingSource _source;
> 
>    private ObjectLocator _locator;
> 
>    ServiceBindingFactory(final BindingSource source, ObjectLocator
> locator) {
>        _source = source;
>        _locator = locator;
>    }
> 
>    public Binding newBinding(String description, ComponentResources
> container, ComponentResources component,
>                              String expression, Location location) {
> 
>        Object service = null;
>        try {
> // All services that use this binding must implement the PublicService
> Interface
> // this also allows you to keep your private services private.
>            service = _locator.getService(expression, PublicService.class);
>        } catch (RuntimeException e ) {
>            // just ignore it we'll handle null later.
>        }
> 
>        return new ServiceBinding(service, expression, location);
>    }
> 
>    public class ServiceBinding extends AbstractBinding {
>        private Location _location;
>        private Object _service;
>        private String _expression;
> 
>        ServiceBinding(Object service, String expression, Location
> location) {
>            _service = service;
>            _expression = expression;
>            _location = location;
>        }
> 
>        public Object get() {
>            if (_service == null) {
>                throw new TapestryException("Unable to locate service:
> " + _expression
>                        , _location, null);
>            }
>            return _service;
>        }
>    }
> }
> 
> 
> The binder and services are added to the AppModule like this:
> 
> public class AppModule {
>    public static void bind(ServiceBinder binder) {
>        // Bind the PublicService classes available to unsafe templates
> via the "service" binding.
>        binder.bind(ColorService.class,
> RedColorService.class).withId("redcolorservice");
>        binder.bind(ColorService.class,
> BlueColorService.class).withId("bluecolorservice");
> 
>        binder.bind(FontService.class,
> ArialFontService.class).withId("arialfontservice");
>        binder.bind(FontService.class,
> MonospaceFontService.class).withId("monospacefontservice");
>    }
> 
>    public static void contributeBindingSource(
>            MappedConfiguration<String, BindingFactory> configuration,
>            BindingSource bindingSource,
>            ObjectLocator objectLocator
>    ) {
>        configuration.add("service", new
> ServiceBindingFactory(bindingSource,objectLocator));
>    }
> }
> 
> Your component might look like this:
> 
> public class StyleAdder {
> 
>   �...@parameter
>    private ColorService _color;
>   �...@parameter
>    private FontService _font;
> 
>    void beforeRenderTemplate(MarkupWriter writer) {
>        writer.element("div");
>        StringBuilder style = new StringBuilder();
>        if (_color != null)
>            style.append("color:").append(_color.getColor()).append(';');
> 
>        if (_font != null) {
>          
>  style.append("font-family:").append(_font.getFont()).append(';');
>        }
>        if ( style.length() > 0 )
>            writer.attributes("style", style);
>    }
> 
>    void afterRenderTemplate(MarkupWriter writer) {
>        writer.end();
>    }
> }
> 
> And the page would include the component like this:
> 
> <t:StyleAdder t:font="service:monospacefontservice"
> t:color="service:bluecolorservice">Blue Text</t:StyleAdder>
> <t:StyleAdder t:color="service:redcolorservice">Red Text</t:StyleAdder>
> <t:StyleAdder t:font="service:arialfontservice"
> t:color="service:redcolorservice">Red Arial Text</t:StyleAdder>
> 
> 
> Josh
> 
> On Mon, Sep 21, 2009 at 6:28 AM, david.boyce
> <david.bo...@thisisnumero.com> wrote:
>>
>>
>> What does the text "dooferController" represent in this context? Is it
>>> a string that represents the name of the service interface that you
>>> want to load? or is it a property in your page that holds a reference
>>> to the service implementation?
>>>
>>
>> Sorry, my question probably wasn't very clear. Basically, the components
>> we
>> are creating are intended to be reusable, and their behaviour is largely
>> defined by services they delegate to, as per your graphing example with
>> the
>> BarChartService, PieChartService and ScatterPlotService.
>>
>> In our product most of the tml is actually supplied by the user, and
>> there
>> is no backing code for any of this tml in the conventional sense. When a
>> component is used, it's quite convenient to specify the implementation of
>> its backing service as a parameter, however, the only way I can see of
>> doing
>> this is to introduce a new binding type, which in my example I've called
>> "service". The implementation of the sevice binding would ideally pull
>> the
>> service out of the Registry.
>>
>> The problem is when you get into the BindingFactory implementation:
>>
>> @Inject Registry registry;
>>
>> @Override
>> public Binding newBinding(
>>                        final String description,
>>                        final ComponentResources container,
>>                        final ComponentResources component,
>>                        String expression,
>>                        final Location location) {
>>
>>   // oops, how do i get the type?
>>   registry.getService(expression, meh?);
>> }
>>
>> So I appreciate that you could probably pass the service id and the
>> service
>> type in the expression somehow, but that seems weak to me and wouldn't go
>> down well with our users.
>>
>> As it happens, we had been passing the services into the components in a
>> different way previously, as we couldn't see a good way of achieving it
>> via
>> parameters (for the previously stated reasons), but came back to it
>> recently. After posting the previous message on this forum, I had the
>> idea
>> of doing the following, using a bespoke binding type I had already
>> created
>> called factory.
>>
>> The gist of this approach is to have 2 parameters, an internal parameter
>> for
>> the actual service, where you specifiy both the service id and the
>> parameter
>> type, and a public parameter for the service id (which gets fed into the
>> first parameter).
>>
>> // the user specifies this...
>> @Property @Parameter(required=true, defaultPrefix="literal")
>> private String controller;
>>
>> // this is a bespoke binding type, the user doesn't modify this parameter
>> @Parameter(defaultPrefix="factory", value="tapestry(" +
>>        "id -> prop:controller," +
>>        "serviceType -> prop:controllerType )")
>> private DataFormRendererController controllerService;
>>
>> Which basically achieves what we want, but still doesn't seem very good -
>> we
>> have to repeat this pattern for every component we have and require 2
>> parameters per service.
>>
>> It just seems to me that being able to inject services out of the
>> tapestry
>> registry into the components via parameters without having to perform any
>> special incantations would be a nice feature... but meh, what do I know
>> (apparently nothing).
>>
>> Cheers,
>>
>> Dave
>>
>>
>>
>>
>>
>>
>> --
>> View this message in context:
>> http://www.nabble.com/passing-a-service-into-a-component-as-a-parameter-tp25505462p25530329.html
>> Sent from the Tapestry - User mailing list archive at Nabble.com.
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
>> For additional commands, e-mail: users-h...@tapestry.apache.org
>>
>>
> 
> 
> 
> --
> --
> TheDailyTube.com. Sign up and get the best new videos on the internet
> delivered fresh to your inbox.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> For additional commands, e-mail: users-h...@tapestry.apache.org
> 
> 
> 

-- 
View this message in context: 
http://www.nabble.com/passing-a-service-into-a-component-as-a-parameter-tp25505462p25566444.html
Sent from the Tapestry - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to