Maybe you now have time to take a look at this. I have no idea if attaching a PDF file works, but I'll just try!

I will also just paste it here but I have the feeling that the result will look ugly but anyway, here goes...







*Multiple Configurations extension to Tapestry IoC*

_*Goal*_

Create services with the same implementation but with a different configuration.

_*Description*_

With an annotation a service implementation can be assigned to a configuration group. This group is represented by a /Class/. (Just like markers.)

Tapestry Modules can contribute configuration markers (represented by a /class/) to a configuration group. The configuration marker can also be /null/.

If no markers are contributed, every service will be instantiated without additional markers. If markers are contributed, every service will be instantiated for each marker. If the /null/marker is contributed, then there will also be a service without additional markers.

The different instantiated services will be automatically linked to services within the same configuration group.

Configurations are contributed to a combination of service interface and markers. For a given service, it will use the contributions to the service /without the configuration marker/that has the @MultipleConfigurations annotation, plus the contributions to the service /with the configuration marker/.

_*Example*_

There are two services in the module ExampleModule, service One and Two, with implementation OneImpl and TwoImpl. The OneImpl service has the mark @Example to distinguish it from other services. OneImpl relies on TwoImpl, which is a local implementation of a service that is also implemented elsewhere.

Example code:

@Marker(Example.class) @ConfigurationGroup(ExampleGroup.class)

public class OneImpl implements One {

public OneImpl(@Local Two twoObject) {}

}

@ConfigurationGroup(ExampleGroup.class)

public class TwoImpl implements Two {

public TwoImpl() {}

}

@ContributeConfigurationMarker(ExampleGroup.class)

public static final void blablabla(Configuration<Class> cfg) {

cfg.add(...);

}

_Case 1: no markers_

If no markers are contributed, there will be two services, OneImpl with marker @Example and TwoImpl.

_Case 2: markers @Red and @Blue_

In this case, there will be four services. OneImpl with markers @Example and @Red, which uses TwoImpl with marker @Red; OneImpl with markers @Example and @Blue, which uses TwoImpl with marker @Blue.

_Case 3: markers @Red and null_

In this case there will also be four services. OneImpl with markers @Example and @Red, which uses TwoImpl with marker @Red; OneImpl with marker @Example, which uses TwoImpl without markers.

_Configuration example_

For case 3, there may be three contributions:

@Contribution(One.class) @Marker({Red.class})

public static void firstContribution() ...

@Contribution(One.class)

public static void secondContribution() …

@Contribution(One.class) @MultipleConfigurations

public static void thirdContribution() …

In this example, the service with marker @Red will receive the first and the third contributions. The service without markers will receive the first and the second contributions.

_*Extra features*_

It is sometimes necessary to know the different configurations and markers. One example is when contributing an object provider that has to provide a different object for every configuration. It is also possible to query the Registry for this information. Because this cannot be done in the startup phase, the contributed markers can also be injected.

We define two additional resources:

 *

   a Class with the @ConfigurationGroup annotation will at runtime hold
   the marker of this service or /null/ if it has none.

 *

   A Set or Collection with the @ConfigurationGroup annotation will
   hold all contributed markers, including /null/ if it has been
   contributed.

_*Naming*_

The names are not fixed yet so they are up to debate and preference.

 *

   the terms “configuration group” and “configuration marker”

 *

   the annotation @ConfigurationGroup

 *

   the annotation @MultipleConfigurations for contributions to all
   services in the same group

 *

   the annotation @ContributeConfigurationMarker for contributions to
   configuration groups

 *

   the injection marker @ConfigurationGroup


Op 19-7-2011 18:34, Thiago H. de Paula Figueiredo schreef:
Hi!

Unfortunately, currently I don't have to take a deep look and what you're doing, but from reading its description, it seems something that would be of great worth for Tapestry-IoC. Please keep up the good work. ;)

On Mon, 18 Jul 2011 18:25:21 -0300, Tom van Dijk <[email protected]> wrote:

I thought it would be a good idea to explain this part again:
The extension is simple: it allows reusing existing (in-use) service implementation, with a different marker. We can identify groups of services that are tightly related and that all need to be properly wired to eachother. They can be called "configuration groups"... maybe someone has a better name, feel free to suggest one. With the idea in mind that we would prefer to identify services using just the interface they implement and additional markers, this is the perfect way to get multiple services with the same implementation and a different configuration.

The trick is that it might be useful to somehow reuse implementations with a different configuration.

So how could we do it? We can't just create another instance of the implementation and pray it goes well. There can be various reasons why this would not work, for example, the service may use other services and set their state depending on the configuration. If for some reason the developer uses static fields, things would screw up. There may be other reasons for failure. However, if developers would annotate suitable classes, that actually can be instantiated for multiple configurations, that would 'guarantee' that no such problems exist. After all, these developers are then responsible for making sure there are no strange effects and everything is neat and tidy.

Now, in the case where a service uses other closely related services in a particular way, it is likely to be a good practice to create multiple instances of these services as well. Also, some modules (like the hibernate module) can provide objects and these should be provided for every instantiation too.

For simplicity, we could assume that the instantiation is done by means of contributing to the configuration group. For backward compatibility, there is "default behavior" if no contributions are done: just the normal behavior, as if there were no configuration group.

So what do we do with the hibernate and hibernate-core module? It boils down to annotating the classes with a simple syntax, and then making sure everything that used to be implemented well for the single-configuration case, still works afterwards AND still works in a multiple-configuration situation. I have done this for hibernate and hibernate-core and the concept works.

Tom.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]




---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to