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