...
This can be overridden by adding the @ServiceId annotation to the service builder method:
...
For autobuilt services, the service id can be specified by placing the @ServiceId annotation directly on a service implementation class.
...
What happens if there is more than one service that implements the JobScheduler interface, or the FileSystem interface? You'll see a runtime exception, because Tapestry is unable to resolve it down to a single service. At this point, it is necessary to disambiguate the link between the service interface and one service. One approach is to use the @InjectService annotation:
Code Block | ||||
---|---|---|---|---|
| ||||
public static Indexer build(@InjectService("JobScheduler") JobScheduler scheduler, @InjectService("FileSystem") FileSystem fileSystem) { IndexerImpl indexer = new IndexerImpl(fileSystem); scheduler.scheduleDailyJob(indexer); return indexer; } |
...
With a service builder method, you use the @Marker @Marker annotation:
Code Block | ||||
---|---|---|---|---|
| ||||
@Marker(Clustered.class) public JobScheduler buildClusteredJobScheduler() { return . . .; } |
...
A special marker interface, @Local@Local, indicates a dependency that should only be resolved using services from within the same module.
...
Understanding why this is a bad idea involves a long detour into inner details of the Java Memory Model. The short form is that other threads may end up invoking methods on the IndexerImpl instance, and its fields (even though they are final, even though they appear to already have been set) may be uninitialized.
Field Injection
The @Inject and @InjectService annotations may be used on instance fields of a service implementation class, as an alternative to passing dependencies of the service implementation in via the constructor.
...
This is useful when a service needs to keep request specific state, such as information extracted from the HttpServletRequest (in a web application). The default singleton model would not work in such a multi threaded multithreaded environment. Using perthread on select services allows state to be isolated to those services. Because the dispatch occurs inside the proxy, you can treat the service as a global, like any other.
...
The service implementation class may include the @Scope @Scope annotation. This is generally the preferred way to specify scope.
...
This can be tweaked slightly; by adding the @EagerLoad annotation to the service builder method, Tapestry will instantiate the service when the Registry is first created.
...