blob: 3a5f983912c6cb17431137751b5efb2f289ef848 [file] [log] [blame]
----
Injection with Components
----
Injection with Components
A key concept in Tapestry is the use of <injection>. The
{{{http://tapestry.apache.org/tapestry5/tapestry-ioc/index.html}Tapestry IoC container}} makes use of one form
of injection, via parameters to service builder methods.
For components, Tapestry takes a completely different tack: injection directly into
instance variables.
Inject Annotation
The {{{../../apidocs/org/apache/tapestry5/ioc/annotations/Inject.html}Inject annotation}} is used to identify fields that will contain injected services and other resources.
Tapestry allows for two kinds of injection:
* Explicit injection, where the particular service to be injected is specified.
* Default injection, where Tapestry determines the object to inject into the field based on its type.
[]
In both cases, the field is transformed into a read only value. As elsewhere in Tapestry, this transformation occurs
at runtime (which is very important in terms of being able to test your components).
Attempting to update an injected field will result in a runtime exception.
In addition, there are a few special cases that are triggered by specific field types, or additional annotations,
in addition, to Inject, on a field.
* Asset Injection
When the
{{{../../apidocs/org/apache/tapestry5/annotations/Path.html}Path}} annotation is also present, then the injected value
(relative to the component) will be a localized {{{assets.html}asset}}.
Symbols in the annotation value are expanded.
* Block Injection
For field type {{{../../apidocs/org/apache/tapestry5/Block.html}Block}}, the value of the Inject annotation is the
id of the {{{templates.apt}\<block\> element}} within the component's template. Normally, the id of the block is determined from the field name
(after stripping out leading "_" and "$" characters). Where that is not appropriate, an
{{{../../apidocs/org/apache/tapestry5/annotations/Id.html}Id}} annotation can be supplied:
+---+
@Inject
private Block foo;
@Inject
@Id("bar")
private Block barBlock;
+---+
The first injection will inject the Block with id "foo" (as always, case is ignored). The second injection will inject the Block with id "bar".
* Resource Injection
For a particular set of field types, Tapestry will inject a <resource> related to the component, such as its Locale.
A very common example occurs when a component needs access to its
{{{../../apidocs/org/apache/tapestry5/ComponentResources.html}resources}}. The component
can define a field of the appropriate type
and use the Inject annotation without a value:
+----+
@Inject
private ComponentResources resources;
+----+
Tapestry uses the type of the field, ComponentResources, to determine what to inject into this field.
The following types are supported for resources injection:
[java.lang.String]
The complete id of the component, which incorporates the complete class name of the containing page and the nested
id of the component within the page.
[java.util.Locale]
The locale for the component (all components within a page use the same locale).
[org.apache.commons.logging.Log]
A Log instance configured for the component, based on the component's class name.
[org.apache.tapestry5.ComponentResources]
The resources for the component, often used to generate links related to the component.
[org.apache.tapestry5.ioc.Messages]
The component message catalog for the component, from which
{{{localization.html}localized}} messages can be generated.
Explicit Service Injection
Here, a specific object is requested. A {{{../../apidocs/org/apache/tapestry5/annotations/Service.html}Service}} annotation
is used to identify the service name.
Example:
+----+
@Inject
@Service("Request")
private Request request;
+----+
This is generally not necessary; you should always be able to identify the service to be injected just by type, not
by explicit id. Explicit ids have the disadvantage of not being refactoring-safe: this won't happen with the Request service,
but perhaps in your own ... if you rename the service interface and rename the service id to match, your existing
injections using the explicit service id will break.
Default Injection
When the type and/or other annotations are not sufficient to identify the object or service to inject, Tapestry falls back on two remaining steps. It assumes
that the field type will be used to identify a service, by the service interface.
First, the object provider created by the Alias service is consulted. This object provider is used to disambiguate injections when there is more
than one service that implements the same service interface.
Second, a search for a unique service that implements the interface occurs. This will fail if either there are no services that implement the interface,
or there is more than one. In the latter case, you must disambiguate, either with a contribution to the Alias service, or by explicitly
identifying the service with the @Service annotation.
Defining New Injection Logic
Annonymous injection is controlled by the
{{{../../apidocs/org/apache/tapestry5/services/InjectionProvider.html}InjectionProvider}}
service. The configuration for this service is a
{{{http://tapestry.apache.org/tapestry5/tapestry-ioc/command.html}chain of command}} for handling component injections.