Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: restore

Scrollbar

You inform Tapestry about your services and contributions by providing a module class.

...

Service builder methods are public methods. They are often static. Here's a trivial example:

Code Block
java
java
package org.example.myapp.services;

public class MyAppModule
{
  public static Indexer build()
  {
    return new IndexerImpl();
  }
}

Any public method (static or instance) whose name starts with "build" is a service builder method, implicitly defining a service within the module.

...

You can give a service an explicit id by adding it to the method name: buildIndexer(). This is useful when you do not want the service id to match the service interface name (for example, when you have different services that implement the same interface), or when you need to avoid name collisions on the method name (Java allows only a single method with a given name and set of parameters, even if the return types are different, so if you have two different service builder methods that take the same parameters, you should give them explicit service ids in the method name).

Tapestry IoC is case insensitive; later we can refer to this service as "indexer" or "INDEXER" or any variation thereof, and connect to this service.

...

We could extend this example by adding additional service builder methods, or by showing how to inject dependencies. See the service documentation for more details.

Autobuilding Services

Main article: Defining Tapestry IOC ServicesIoC Modules

An alternate, and usually preferred, way to define a service is via a module's bind() method. The previous example can be rewritten as:

Code Block
java
java
package org.example.myapp.services;

import org.apache.tapestry5.ioc.ServiceBinder;

public class MyAppModule
{
  public static void bind(ServiceBinder binder)
  {
     binder.bind(Indexer.class, IndexerImpl.class);
  }
}

For more details, see see Defining Tapestry IOC ServicesIoC Modules. In most cases, autobuilding is the preferred approach.

...

The bind() method must be static; an exception is thrown if the bind() method exists but is an instance method.

Anchor
Cacheing_Services
Cacheing_Services
Caching Services

You will occasionally find yourself in the position of injecting the same services into your service builder or service decorator methods repeatedly (this occurs much less often since the introduction of service autobuilding). This can result in quite a bit of redundant typing. Less code is better code, so as an alternative, you may define a constructor for your module that accepts annotated parameters (as with service builder injection).

This gives you a chance to store common services in instance variables for later use inside service builder methods.

Code Block
java
java
public class MyModule
{   
  private final JobScheduler scheduler;
  private final FileSystem fileSystem;
  
  public MyModule(JobScheduler scheduler, FileSystem fileSystem)
  {
    this.scheduler = scheduler;
    this.fileSystem = fileSystem;
  }
  
  public Indexer build()
  {
    IndexerImpl indexer = new IndexerImpl(fileSystem);
      
    scheduler.scheduleDailyJob(indexer);
      
    return indexer;
  }
}

Notice that we've switched from static methods to instance methods. Since the builder methods are not static, the MyModule class will be instantiated so that the methods may be invoked. The constructor receives two common dependencies, which are stored into instance fields that may later be used inside service builder methods such as buildIndexer().

...

Again, keep the methods very simple. Use parameter injection to gain access to the dependencies you need.

...

Often, all services in a module should share a marker, this can be specified with a @Marker annotation on the module class. For example, the TapestryIOCModule:

Code Block
java
java
@Marker(Builtin.class)
public final class TapestryIOCModule
{
  . . .

This references a particular annotation class, Builtin:

Code Block
java
java
@Target(
{ PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Builtin
{

}

The annotation can be applied to method and constructor parameters, for use within the IoC container. It can also be applied to fields, though this is specific to the Tapestry web framework.

...

Using this style, the previous example of a module class may be rewritten:

Code Block
java
java
public class MyModule
{
  @Inject
  private JobScheduler scheduler;

  @Inject
  private FileSystem fileSystem;

  public Indexer build()
  {
    IndexerImpl indexer = new IndexerImpl(fileSystem);
      
    scheduler.scheduleDailyJob(indexer);

    return indexer;
  }
}

 

Scrollbar