tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Using JSR 330 standard annotations
Date Thu, 23 Jun 2011 10:41:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/12/_/styles/combined.css?spaceKey=TAPESTRY&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Using+JSR+330+standard+annotations">Using
JSR 330 standard annotations</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~drobiazko">Igor
Drobiazko</a>
    </h4>
        <br/>
                         <h4>Changes (6)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >|| JSR-330 \\ <br>javax.inject
|| Tapestry \\ <br></td></tr>
            <tr><td class="diff-unchanged" >org.apache.tapestry5.ioc.annotations
|| Comment || <br></td></tr>
            <tr><td class="diff-changed-lines" >| @Inject | @Inject <span class="diff-changed-words">|<span
class="diff-added-chars"style="background-color: #dfd;"> \</span>-<span class="diff-added-chars"style="background-color:
#dfd;"> </span>|</span> <br></td></tr>
            <tr><td class="diff-unchanged" >| @Inject \\ <br></td></tr>
            <tr><td class="diff-changed-lines" >@Named | @InjectService <span
class="diff-changed-words">|<span class="diff-added-chars"style="background-color: #dfd;">
\</span>-<span class="diff-added-chars"style="background-color: #dfd;"> </span>|</span>
<br></td></tr>
            <tr><td class="diff-changed-lines" >| @Scope | @Scope <span class="diff-changed-words">|<span
class="diff-added-chars"style="background-color: #dfd;"> \</span>-<span class="diff-added-chars"style="background-color:
#dfd;"> </span>|</span> <br></td></tr>
            <tr><td class="diff-changed-lines" >| @Qualifier <span class="diff-changed-words">|<span
class="diff-added-chars"style="background-color: #dfd;"> \</span>-<span class="diff-added-chars"style="background-color:
#dfd;"> </span>|</span> Tapestry marker annotations don’t need any qualifier
annotations | <br></td></tr>
            <tr><td class="diff-changed-lines" >| @Singleton <span class="diff-changed-words">|<span
class="diff-added-chars"style="background-color: #dfd;"> \</span>-<span class="diff-added-chars"style="background-color:
#dfd;"> </span>|</span> By default all Tapestry services are singletons | <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>h1. Field Injection <br> <br>Let’s start with field injection. In
Tapestry the injection into fields is triggered by&amp;nbsp;[@Inject|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html]&amp;nbsp;or&amp;nbsp;[@InjectService|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html]&amp;nbsp;annotations.
When @Inject annotation is present on a field, Tapestry tries to resolve the object to inject
by the type of the field. If several implementations of the same service interface are available
in the registry, you have to disambiguate which implementation you want to be injected. This
can be done by placing the&amp;nbsp;[@InjectService|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html]&amp;nbsp;annotation
on the injection point. <br>{code}import org.apache.tapestry5.ioc.annotations.Inject;
<br>import org.apache.tapestry5.ioc.annotations.InjectService; <br> <br>...
<br> <br>public class AuthenticationFilter implements ComponentRequestFilter {
<br> <br>   @InjectService(&quot;HttpBasic&quot;) <br>   private
AuthenticationService basicAuthService; <br> <br>   @InjectService(&quot;HttpDigest&quot;)
<br>   private AuthenticationService digestAuthService; <br> <br>   @Inject
<br>   private Response response; <br> <br>   ... <br> <br>}{code}
<br>Now let’s see the JSR-330 equivalent of the same service. As you can see the @Inject
annotations are interchangeable. The difference is how to get a service by its unique id.
For this purpose JSR-330 provides the&amp;nbsp;[@Named|http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Named.html]&amp;nbsp;annotation
which accompanies the @Inject annotation. <br>{code}import javax.inject.Inject; <br>import
javax.inject.Named; <br> <br>... <br> <br>public class AuthenticationFilter
implements ComponentRequestFilter { <br> <br>   @Inject @Named(&quot;HttpBasic&quot;)
<br>   private AuthenticationService basicAuthService; <br> <br>   @Inject
@Named(&quot;HttpDigest&quot;) <br>   private AuthenticationService digestAuthService;
<br> <br>   @Inject <br>   private Response response; <br> <br>
  ... <br> <br>}{code} <br> <br>h1. Constructor Injection <br>
<br>For constructor injection the @Inject annotations are interchangeable. You can use
either JSR-330 or Tapestry annotation to mark a constructor for injection. Note that at most
one constructor per class may be marked as injection point. <br> <br>However,
the semantics of constructor injection are different in JSR-330 and Tapestry IoC. In JSR-330
a constructor is injectable only if the @Inject annotation is present. <br>{code}public
class Car { <br> <br>   public Car() { ... } <br> <br>   @Inject <br>
  public Car(Engine engine) { ... } <br>}{code} <br>In Tapestry the @Inject annotation
for constructors is optional. All available constructors are candidates for injection: the
constructor with the most parameters will be invoked. <br>{code}public class Car { <br>
<br>   public Car() { ... } <br> <br>   public Car(Engine engine) { ...
} <br> <br>}{code} <br>When several constructors are available and you don’t
want the constructor with most&amp;nbsp; parameters to be injectable, you need to place
the&amp;nbsp;[@Inject|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html]&amp;nbsp;annotation.
<br>{code}public class Car { <br> <br>   public Car() { ... } <br>
<br>   @Inject <br>   public Car(Engine engine) { ... } <br> <br>
  public Car(Engine engine, Logger logger) { ... } <br> <br>}{code} <br>
<br>h1. Injection Into Pages and Components <br> <br>Inside Tapestry components,
injection occurs exclusively on fields. So far the injection was triggered by the&amp;nbsp;[@Inject|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html]&amp;nbsp;or&amp;nbsp;[@InjectService|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html]&amp;nbsp;annotations.
As of version 5.3 the injection points can also be marked with JSR-330 annotations. The following
example demonstrates that. <br>{code}public class Index { <br> <br>   @Inject
<br>   private Request request; <br> <br>   @javax.inject.Inject <br>
  private ComponentResources resources; <br> <br>   @javax.inject.Inject <br>
  @Named(&quot;FrenchGreeter&quot;) <br>   private Greeter greeter; <br>
<br>   @javax.inject.Inject <br>   @Symbol(SymbolConstants.PRODUCTION_MODE) <br>
  private boolean productionMode; <br> <br>   void onActivate() { ... } <br>
<br>}{code} <br> <br> <br> <br>h1. Marker/Qualifier Annotations
<br> <br>Both JSR-330 and Tapestry IoC allow you to disambiguate services by marker
or qualifier annotations, as shown in the following example. <br>{code}public class
Index { <br> <br>   @Inject <br>   @French <br>   private Greeter
greeter; <br> <br>}{code} <br>Again, there is a slight difference. In JSR-330
a qualifier annotation like&amp;nbsp;_@French_&amp;nbsp;in the example above needs
to be annotated by the&amp;nbsp;[@Qualifier|http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Qualifier.html]&amp;nbsp;annotation.
<br>{code}@Documented <br>@Retention(RetentionPolicy.RUNTIME) <br>@Target(ElementType.FIELD)
<br>@javax.inject.Qualifier <br>public @interface French { <br>}{code} <br>In
Tapestry any annotation can be a marker annotation. You don’t need to place something like
the&amp;nbsp;[@Qualifier|http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Qualifier.html]&amp;nbsp;annotation
on your marker annotation. <br> <br> <br>h1. Scopes <br> <br>By
default, a JSR-330 injector creates an instance, uses the instance for one injection, and
then forgets it. By placing the&amp;nbsp;[@Scope|http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Scope.html]&amp;nbsp;annotation
you can tell the injector to retain the instance for possible reuse in a later injection.
If you want a service to be a singleton, you need to use the&amp;nbsp;[@Singleton|http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Singleton.html]&amp;nbsp;annotation.
<br> <br>In Tapestry, it is exactly the other way around. By default a service
is a singleton. Once an instance is created, it is reused for injection. Another available
scope is&amp;nbsp;_perthread_, which exists primarily to help multi-threaded servlet applications.
If a service has&amp;nbsp;_perthread&amp;nbsp;_scope, it is recreated for every incoming
request. <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>Starting from Tapestry 5.3, it's possible to use JSR-330 annotations for
injection.&nbsp;</p>

<p>The following table demonstrates that most of annotations in Tapestry IoC and JSR-330
are interchangeable. However, there are few differences in semantics.</p>


<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> JSR-330 <br class="atl-forced-newline" />
javax.inject </th>
<th class='confluenceTh'> Tapestry <br class="atl-forced-newline" />
org.apache.tapestry5.ioc.annotations </th>
<th class='confluenceTh'> Comment </th>
</tr>
<tr>
<td class='confluenceTd'> @Inject </td>
<td class='confluenceTd'> @Inject </td>
<td class='confluenceTd'> &#45; </td>
</tr>
<tr>
<td class='confluenceTd'> @Inject <br class="atl-forced-newline" />
@Named </td>
<td class='confluenceTd'> @InjectService </td>
<td class='confluenceTd'> &#45; </td>
</tr>
<tr>
<td class='confluenceTd'> @Scope </td>
<td class='confluenceTd'> @Scope </td>
<td class='confluenceTd'> &#45; </td>
</tr>
<tr>
<td class='confluenceTd'> @Qualifier </td>
<td class='confluenceTd'> &#45; </td>
<td class='confluenceTd'> Tapestry marker annotations don’t need any qualifier annotations
</td>
</tr>
<tr>
<td class='confluenceTd'> @Singleton </td>
<td class='confluenceTd'> &#45; </td>
<td class='confluenceTd'> By default all Tapestry services are singletons </td>
</tr>
</tbody></table>
</div>


<h1><a name="UsingJSR330standardannotations-FieldInjection"></a>Field Injection</h1>

<p>Let’s start with field injection. In Tapestry the injection into fields is triggered
by&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html"
class="external-link" rel="nofollow">@Inject</a>&nbsp;or&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html"
class="external-link" rel="nofollow">@InjectService</a>&nbsp;annotations. When
@Inject annotation is present on a field, Tapestry tries to resolve the object to inject by
the type of the field. If several implementations of the same service interface are available
in the registry, you have to disambiguate which implementation you want to be injected. This
can be done by placing the&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html"
class="external-link" rel="nofollow">@InjectService</a>&nbsp;annotation on the
injection point.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">import</span> org.apache.tapestry5.ioc.annotations.Inject;
<span class="code-keyword">import</span> org.apache.tapestry5.ioc.annotations.InjectService;

...

<span class="code-keyword">public</span> class AuthenticationFilter <span class="code-keyword">implements</span>
ComponentRequestFilter {

   @InjectService(<span class="code-quote">"HttpBasic"</span>)
   <span class="code-keyword">private</span> AuthenticationService basicAuthService;

   @InjectService(<span class="code-quote">"HttpDigest"</span>)
   <span class="code-keyword">private</span> AuthenticationService digestAuthService;

   @Inject
   <span class="code-keyword">private</span> Response response;

   ...

}</pre>
</div></div>
<p>Now let’s see the JSR-330 equivalent of the same service. As you can see the @Inject
annotations are interchangeable. The difference is how to get a service by its unique id.
For this purpose JSR-330 provides the&nbsp;<a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Named.html"
class="external-link" rel="nofollow">@Named</a>&nbsp;annotation which accompanies
the @Inject annotation.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">import</span> javax.inject.Inject;
<span class="code-keyword">import</span> javax.inject.Named;

...

<span class="code-keyword">public</span> class AuthenticationFilter <span class="code-keyword">implements</span>
ComponentRequestFilter {

   @Inject @Named(<span class="code-quote">"HttpBasic"</span>)
   <span class="code-keyword">private</span> AuthenticationService basicAuthService;

   @Inject @Named(<span class="code-quote">"HttpDigest"</span>)
   <span class="code-keyword">private</span> AuthenticationService digestAuthService;

   @Inject
   <span class="code-keyword">private</span> Response response;

   ...

}</pre>
</div></div>

<h1><a name="UsingJSR330standardannotations-ConstructorInjection"></a>Constructor
Injection</h1>

<p>For constructor injection the @Inject annotations are interchangeable. You can use
either JSR-330 or Tapestry annotation to mark a constructor for injection. Note that at most
one constructor per class may be marked as injection point.</p>

<p>However, the semantics of constructor injection are different in JSR-330 and Tapestry
IoC. In JSR-330 a constructor is injectable only if the @Inject annotation is present.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Car
{

   <span class="code-keyword">public</span> Car() { ... }

   @Inject
   <span class="code-keyword">public</span> Car(Engine engine) { ... }
}</pre>
</div></div>
<p>In Tapestry the @Inject annotation for constructors is optional. All available constructors
are candidates for injection: the constructor with the most parameters will be invoked.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Car
{

   <span class="code-keyword">public</span> Car() { ... }

   <span class="code-keyword">public</span> Car(Engine engine) { ... }

}</pre>
</div></div>
<p>When several constructors are available and you don’t want the constructor with
most&nbsp; parameters to be injectable, you need to place the&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html"
class="external-link" rel="nofollow">@Inject</a>&nbsp;annotation.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Car
{

   <span class="code-keyword">public</span> Car() { ... }

   @Inject
   <span class="code-keyword">public</span> Car(Engine engine) { ... }

   <span class="code-keyword">public</span> Car(Engine engine, Logger logger)
{ ... }

}</pre>
</div></div>

<h1><a name="UsingJSR330standardannotations-InjectionIntoPagesandComponents"></a>Injection
Into Pages and Components</h1>

<p>Inside Tapestry components, injection occurs exclusively on fields. So far the injection
was triggered by the&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html"
class="external-link" rel="nofollow">@Inject</a>&nbsp;or&nbsp;<a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/InjectService.html"
class="external-link" rel="nofollow">@InjectService</a>&nbsp;annotations. As
of version 5.3 the injection points can also be marked with JSR-330 annotations. The following
example demonstrates that.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Index
{

   @Inject
   <span class="code-keyword">private</span> Request request;

   @javax.inject.Inject
   <span class="code-keyword">private</span> ComponentResources resources;

   @javax.inject.Inject
   @Named(<span class="code-quote">"FrenchGreeter"</span>)
   <span class="code-keyword">private</span> Greeter greeter;

   @javax.inject.Inject
   @Symbol(SymbolConstants.PRODUCTION_MODE)
   <span class="code-keyword">private</span> <span class="code-object">boolean</span>
productionMode;

   void onActivate() { ... }

}</pre>
</div></div>



<h1><a name="UsingJSR330standardannotations-Marker%2FQualifierAnnotations"></a>Marker/Qualifier
Annotations</h1>

<p>Both JSR-330 and Tapestry IoC allow you to disambiguate services by marker or qualifier
annotations, as shown in the following example.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Index
{

   @Inject
   @French
   <span class="code-keyword">private</span> Greeter greeter;

}</pre>
</div></div>
<p>Again, there is a slight difference. In JSR-330 a qualifier annotation like&nbsp;<em>@French</em>&nbsp;in
the example above needs to be annotated by the&nbsp;<a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Qualifier.html"
class="external-link" rel="nofollow">@Qualifier</a>&nbsp;annotation.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@javax.inject.Qualifier
<span class="code-keyword">public</span> @<span class="code-keyword">interface</span>
French {
}</pre>
</div></div>
<p>In Tapestry any annotation can be a marker annotation. You don’t need to place
something like the&nbsp;<a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Qualifier.html"
class="external-link" rel="nofollow">@Qualifier</a>&nbsp;annotation on your marker
annotation.</p>


<h1><a name="UsingJSR330standardannotations-Scopes"></a>Scopes</h1>

<p>By default, a JSR-330 injector creates an instance, uses the instance for one injection,
and then forgets it. By placing the&nbsp;<a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Scope.html"
class="external-link" rel="nofollow">@Scope</a>&nbsp;annotation you can tell
the injector to retain the instance for possible reuse in a later injection. If you want a
service to be a singleton, you need to use the&nbsp;<a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/Singleton.html"
class="external-link" rel="nofollow">@Singleton</a>&nbsp;annotation.</p>

<p>In Tapestry, it is exactly the other way around. By default a service is a singleton.
Once an instance is created, it is reused for injection. Another available scope is&nbsp;<em>perthread</em>,
which exists primarily to help multi-threaded servlet applications. If a service has&nbsp;_perthread&nbsp;_scope,
it is recreated for every incoming request.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Using+JSR+330+standard+annotations">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=26120928&revisedVersion=2&originalVersion=1">View
Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message