Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
java
java
  public static FileServicerFileServiceDispatcher buildFileServicerDispatcher(Map<String,FileServicer> contributions)
  {
    return new FileServiceDispatcherImpl(contributions);
  } 

In order to provide a value for the contribution parameter, Tapestry will collect contributions from service contribution methods. It will ensure that the keys and values match the generic types shown (String for the key, FileServicer for the value). The map will be assembled and passed into the service builder method, and from there, into the FileServiceDispatcherImpl contructorconstructor.

So where do the values come from? Service contributor methods, methods that start with "contribute":

...

Because Tapestry IoC is highly dynamic (it scans the visible JAR manifest files to identify module classes), the FileServicerDispatcher service may be in one module, and the other contributing modules (such as the one that contributes the Office file services) may be written at a much later date. With no change to the FileServicerDispatcher service or its module class, the new services "plug into" the overall solution, simply by having their JAR's on runtime classpath.

Naming conventions vs. Annotations

If you prefer annotations over naming conventions you can use the Contribute annotation. As of version 5.2 this annotation that may be placed on a contributor method of a module instead of starting the methods name with "contribute". The value of the annotation is the type of the service to contribute into.

The primary reasons to use @Contribute and marker annotations is twofold:

  • There is no longer a linkage between the contribution method name and the service id, which is much more refactoring safe: if you change the service interface name, or the id of the service, your method will still be invoked when using @Contribute.
  • It makes it much easier for an override of the service to get the configuration intended for the original service.

The following example is an alternative for the contribution method above.

Code Block
java
java

@Contribute(FileServiceDispatcher.class)
public static void arbitraryMethodName(MappedConfiguration<String,FileServicer> configuration)
{
    configuration.add("doc", new WordFileServicer());
    configuration.add("ppt", new PowerPointFileServicer());
}  

If you have several implementations of a service interface, you have to disambiguate the services. For this purpose the marker annotations should be placed on the contributor method.

Code Block
java
java

@Contribute(FileServiceDispatcher.class)
@Red @Blue
public static void arbitraryMethodName(MappedConfiguration<String,FileServicer> configuration)
{
    configuration.add("doc", new WordFileServicer());
    configuration.add("ppt", new PowerPointFileServicer());
}

In this example, the method will only be invoked when constructing a service configuration where the service itself has both the Red and Blue marker annotations. Tapestry knows which annotations are marker annotations, and which marker annotations apply to the service, via the Marker annotation on the service implementation.

If the special Local annotation is present, then contribution is made only to the configuration of a service being constructed in the same module.

It is not impossible that the same contribution method will be invoked to contribute to the configuration of multiple different services.

Code Block
java
java

  @Contribute(FileServiceDispatcher.class)
  @Local
  public static void arbitraryMethodName(MappedConfiguration<String,FileServicer> configuration)
  {
    configuration.add("doc", new WordFileServicer());
    configuration.add("ppt", new PowerPointFileServicer());
  }  

Configuration Types

There are three different styles of configurations (with matching contributions):

...