I think we are talking about two different things here or there is a Tapestry feature I don't know about. I'm looking for a feature that will return a new "Plain Old Object" from an Interface. A simple example:
Map map = objectFactory.build(Map.class); The service would know how to do this because I have the following configuration: configuration.add(Map.class,HashMap.class); So in this example the Map instance would be a new HashMap instance. I realize I can build something that does this with the current version of Tapestry but I don't know any existing service that does this out of the box. I think in order to build a set of Modules that cooperate thru Interfaces there needs to be a common way to instantiate real classes from Interfaces. On Fri, Sep 27, 2013 at 7:05 PM, Thiago H de Paula Figueiredo < [email protected]> wrote: > On Fri, 27 Sep 2013 18:09:13 -0300, Barry Books <[email protected]> wrote: > > It useful for library modules because you can build a set of pages, >> components and classes that work on Interfaces instead of concrete >> classes. >> The application can just implement the interfaces and contribute them. In >> my case about I have an Invoice interface that's is defined in a shop >> module. The shop module just operates on the Interface. Then I have a web >> app that implements that Interface in my case as a DynamoDB object. >> Others could implement it as a JPA or Hibernate object. >> > > A library module can define interfaces and @Inject them without the module > itself defining the service implementations. Of course, to test or use it, > you'll need to create and define implementations for that services, maybe > mocks in some module class outside the library component that defines that > inteface, but that's not a requirement for building a module library. All > you need to do is to *not* define the service and let other module class > (maybe AppModule) do that. If no one actually provides a service > implementation, Tapestry will raise an exception explaining that. > > > There are several reasons it needs to be in the core. >> >> 1. It would be great if BeanEditForm used it so BeanEditForm could work >> with interfaces. >> > > Actually, implementing BeanModel yourself or decorating one created > through BeanModelSource and passing it to BeanEditForm and BeanEditor, > probably by decorating or advising the BeanModelSource service, you can > implement the BeanModel.newInstance() method (or decorate the BeanModel > created by BeanModelSource and override the newInstance() method) and have > it instantiate any object you want automatically (as long at it implements > the interface, of course). > > > 2. If you are going to build a Modules based on Interfaces it needs to be >> in the core otherwise everyone will end up with a different >> implementation and they don't interoperate. >> > > I'm sorry, I'm not following you here, maybe because of my explanation > below. > > > 3. It's easier to use in pages/components than locator. >> > > Agreed. If it's just about instantiating objects based on interfaces, I've > just discovered ObjectProvider and MasterObjectProvider (which is basically > a façade around the list of ObjectProviders), which I believe may fit the > scenario you're thinking: > > /** > * Object providers represent an alternate way to locate an object > provided somewhere in the {@link > * org.apache.tapestry5.ioc.**Registry}. Instead of using a just the > service id to gain access to a service within the > * Registry, object providers in different flavors are capable of vending, > or even creating, objects of disparate types > * from disparate sources. > * <p/> > * Object providers are consulted in a strict order, and the first > non-null result is taken. > * <p/> > * In many cases, an object provider searches for additional annotations > on the element (usually a parameter, or perhaps > * a field) for which a value is required. > */ > public interface ObjectProvider { > <T> T provide(Class<T> objectType, AnnotationProvider > annotationProvider, ObjectLocator locator); > > } > > 4. Tapestry is really good about using Interfaces to define functionality >> but it's difficult to do this in modules that define components. This >> solves most of the problems. >> > > I'm sorry, I'm not following you here, maybe because of my explanation > above. > > By the way, for many scenarios, I've found that defining a chain of > responsibility service (which Tapestry calls chain of command for some > reason) the best way for dealing with stuff with distributed configuration > instead of just defining a service. For example, your scenario deals with > instantiating objects defining a given interface the library which defines > this interface doesn't know the implementations. So I could define an > InterfaceInstantiator service: > > @UsesOrderedConfiguration(**InterfaceInstantiator.class); > public interface InterfaceInstantiator<T> { > /** > * Instantiates an object of the given type. If this > implementation doesn't support that type, > * this method should return null. > */ > <T> instantiate(Class<T> type); > } > > And define it as a service that receives instances of itself as its > distributed configuration (!!!): > > public static InterfaceInstantiator buildInterfaceInstantiator( > OrderedConfiguration<**InterfaceInstantiator> configuration, > ChainBuilder chainBuilder) { > > return chainBuilder.build(**IterfaceInstantiator.class, > configuration); > > } > > By the way, many of the most important Tapestry services are defined in > this Inception-esque this way (MasterDispatcher, > ComponentClassTransformerWorke**r, DataTypeAnalyzer, InjctionProvider). > > Summary: what I wrote here will probably be turned into a blog post about > chain of responsibility in Tapestry-IoC later, but I think ObjectProvider > and MasterObjectProvider are widely unknown interfaces that already do what > you want. > > > -- > Thiago H. de Paula Figueiredo > > ------------------------------**------------------------------**--------- > To unsubscribe, e-mail: > dev-unsubscribe@tapestry.**apache.org<[email protected]> > For additional commands, e-mail: [email protected] > >
