injecao.xml
29.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ ]>
<chapter id="injecao">
<title>Injeção de dependência</title>
<para>
TODO: Injeção de dependência, tratando sobre a injeção em si, os contextos, fábricas, loaders.
</para>
<para>
One of the most significant features of CDI—certainly the most recognized—is dependency injection;
excuse me, <emphasis>typesafe</emphasis> dependency injection.
</para>
<section>
<title>Injection points</title>
<para>
The <literal>@Inject</literal> annotation lets us define an injection point that is injected during bean
instantiation. Injection can occur via three different mechanisms.
</para>
<para>
<emphasis>Bean constructor</emphasis> parameter injection:
</para>
<programlisting role="JAVA"><![CDATA[public class Checkout {
private final ShoppingCart cart;
@Inject
public Checkout(ShoppingCart cart) {
this.cart = cart;
}
}]]></programlisting>
<note>
<para>
A bean can only have one injectable constructor.
</para>
</note>
<para>
<emphasis>Initializer method</emphasis> parameter injection:
</para>
<programlisting role="JAVA"><![CDATA[public class Checkout {
private ShoppingCart cart;
@Inject
void setShoppingCart(ShoppingCart cart) {
this.cart = cart;
}
}]]></programlisting>
<note>
<para>
A bean can have multiple initializer methods. If the bean is a session bean, the initializer method
is not required to be a business method of the session bean.
</para>
</note>
<para>
And direct field injection:
</para>
<programlisting role="JAVA"><![CDATA[public class Checkout {
private @Inject ShoppingCart cart;
}]]></programlisting>
<note>
<para>
Getter and setter methods are not required for field injection to work (unlike with JSF managed beans).
</para>
</note>
<para>
Dependency injection always occurs when the bean instance is first instantiated by the container.
Simplifying just a little, things happen in this order:
</para>
<itemizedlist>
<listitem>
<para>
First, the container calls the bean constructor (the default constructor or the one annotated
<literal>@Inject</literal>), to obtain an instance of the bean.
</para>
</listitem>
<listitem>
<para>
Next, the container initializes the values of all injected fields of the bean.
</para>
</listitem>
<listitem>
<para>
Next, the container calls all initializer methods of bean (the call order is not portable, don't
rely on it).
</para>
</listitem>
<listitem>
<para>
Finally, the <literal>@PostConstruct</literal> method, if any, is called.
</para>
</listitem>
</itemizedlist>
<para>(The only complication is that the container might call initializer methods declared by a superclass
before initializing injected fields declared by a subclass.)</para>
<tip>
<para>
One major advantage of constructor injection is that it allows the bean to be immutable.
</para>
</tip>
<para>
CDI also supports parameter injection for some other methods that are invoked by the container. For instance,
parameter injection is supported for producer methods:
</para>
<programlisting role="JAVA"><![CDATA[@Produces Checkout createCheckout(ShoppingCart cart) {
return new Checkout(cart);
}]]></programlisting>
<para>
This is a case where the <literal>@Inject</literal> annotation <emphasis>is not</emphasis> required at the
injection point. The same is true for observer methods (which we'll meet in <xref linkend="events"/>) and
disposer methods.
</para>
</section>
<section>
<title>What gets injected</title>
<para>
The CDI specification defines a procedure, called <emphasis>typesafe resolution</emphasis>, that the container
follows when identifying the bean to inject to an injection point. This algorithm looks complex at first, but
once you understand it, it's really quite intuitive. Typesafe resolution is performed at system initialization
time, which means that the container will inform the developer immediately if a bean's
dependencies cannot be satisfied.
</para>
<para>
The purpose of this algorithm is to allow multiple beans to implement the same bean type and either:
</para>
<itemizedlist>
<listitem>
<para>
allow the client to select which implementation it requires using a <emphasis>qualifier</emphasis> or
</para>
</listitem>
<listitem>
<para>
allow the application deployer to select which implementation is appropriate for a particular deployment,
without changes to the client, by enabling or disabling an <emphasis>alternative</emphasis>, or
</para>
</listitem>
<listitem>
<para>
allow the beans to be isolated into separate modules.
</para>
</listitem>
</itemizedlist>
<para>
Obviously, if you have exactly one bean of a given type, and an injection point with that same type, then bean A is
going to go into slot A. That's the simplest possible scenario. When you first start your application, you'll
likely have lots of those.
</para>
<para>
But then, things start to get complicated. Let's explore how the container determines which bean to inject in
more advanced cases. We'll start by taking a closer look at qualifiers.
</para>
</section>
<section>
<title>Qualifier annotations</title>
<para>
If we have more than one bean that implements a particular bean type, the injection point can specify exactly
which bean should be injected using a qualifier annotation. For example, there might be two implementations of
<literal>PaymentProcessor</literal>:
</para>
<programlisting role="JAVA"><![CDATA[@Synchronous
public class SynchronousPaymentProcessor implements PaymentProcessor {
public void process(Payment payment) { ... }
}]]></programlisting>
<programlisting role="JAVA"><![CDATA[@Asynchronous
public class AsynchronousPaymentProcessor implements PaymentProcessor {
public void process(Payment payment) { ... }
}]]></programlisting>
<para>
Where <literal>@Synchronous</literal> and <literal>@Asynchronous</literal> are qualifier annotations:
</para>
<programlisting role="JAVA"><![CDATA[@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Synchronous {}]]></programlisting>
<programlisting role="JAVA"><![CDATA[@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Asynchronous {}]]></programlisting>
<para>
A client bean developer uses the qualifier annotation to specify exactly which bean should be injected.
</para>
<para>Using field injection:</para>
<programlisting role="JAVA"><![CDATA[@Inject @Synchronous PaymentProcessor syncPaymentProcessor;
@Inject @Asynchronous PaymentProcessor asyncPaymentProcessor;]]></programlisting>
<para>Using initializer method injection:</para>
<programlisting role="JAVA"><![CDATA[@Inject
public void setPaymentProcessors(@Synchronous PaymentProcessor syncPaymentProcessor,
@Asynchronous PaymentProcessor asyncPaymentProcessor) {
this.syncPaymentProcessor = syncPaymentProcessor;
this.asyncPaymentProcessor = asyncPaymentProcessor;
}]]></programlisting>
<para>Using constructor injection:</para>
<programlisting role="JAVA"><![CDATA[@Inject
public Checkout(@Synchronous PaymentProcessor syncPaymentProcessor,
@Asynchronous PaymentProcessor asyncPaymentProcessor) {
this.syncPaymentProcessor = syncPaymentProcessor;
this.asyncPaymentProcessor = asyncPaymentProcessor;
}]]></programlisting>
<para>
Qualifier annotations can also qualify method arguments of producer, disposer and observer methods. Combining
qualified arguments with producer methods is a good way to have an implementation of a bean type
selected at runtime based on the state of the system:
</para>
<programlisting role="JAVA"><![CDATA[@Produces
PaymentProcessor getPaymentProcessor(@Synchronous PaymentProcessor syncPaymentProcessor,
@Asynchronous PaymentProcessor asyncPaymentProcessor) {
return isSynchronous() ? syncPaymentProcessor : asyncPaymentProcessor;
}]]></programlisting>
<para>
If an injected field or a parameter of a bean constructor or initializer method is not explicitly annotated
with a qualifier, the default qualifier, <literal>@Default</literal>, is assumed.
</para>
<para>
Now, you may be thinking, <emphasis>"What's the different between using a qualifier and just specifying the
exact implementation class you want?"</emphasis> It's important to understand that a qualifier is like an
extension of the interface. It does not create a direct dependency to any particular implementation. There
may be multiple alterative implementations of <literal>@Asynchronous PaymentProcessor</literal>!
</para>
</section>
<section>
<title>The built-in qualifiers <literal>@Default</literal> and <literal>@Any</literal></title>
<para>Whenever a bean or injection point does not explicitly declare a qualifier, the container assumes the
qualifier <literal>@Default</literal>. From time to time, you'll need to decare an injection point without
specifying a qualifier. There's a qualifier for that too. All beans have the qualifier <literal>@Any</literal>.
Therefore, by explicitly specifying <literal>@Any</literal> at an injection point, you suppress the default
qualifier, without otherwise restricting the beans that are eligible for injection.</para>
<tip>
<para>This is especially useful if you want to iterate over all beans with a certain bean type. For example:</para>
<programlisting role="JAVA"><![CDATA[@Inject
void initServices(@Any Instance<Service> services) {
for (Service service: services) {
service.init();
}
}]]></programlisting>
</tip>
</section>
<section>
<title>Qualifiers with members</title>
<para>
Java annotations can have members. We can use annotation members to further discriminate a qualifier. This
prevents a potential explosion of new annotations. For example, instead of creating several qualifiers
representing different payment methods, we could aggregate them into a single annotation with a member:
</para>
<programlisting role="JAVA"><![CDATA[@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PayBy {
PaymentMethod value();
}]]></programlisting>
<para>
Then we select one of the possible member values when appling the qualifier:
</para>
<programlisting role="JAVA"><![CDATA[private @Inject @PayBy(CHECK) PaymentProcessor checkPayment;]]></programlisting>
<para>
We can force the container to ignore a member of a qualifier type by annotating the member
<literal>@Nonbinding</literal>.
</para>
<programlisting role="JAVA"><![CDATA[@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PayBy {
PaymentMethod value();
@Nonbinding String comment() default "";
}]]></programlisting>
</section>
<section>
<title>Multiple qualifiers</title>
<para>
An injection point may specify multiple qualifiers:
</para>
<programlisting role="JAVA"><![CDATA[@Inject @Synchronous @Reliable PaymentProcessor syncPaymentProcessor;]]></programlisting>
<para>
Then only a bean which has <emphasis>both</emphasis> qualifier annotations would be eligible for
injection.
</para>
<programlisting role="JAVA"><![CDATA[@Synchronous @Reliable
public class SynchronousReliablePaymentProcessor implements PaymentProcessor {
public void process(Payment payment) { ... }
}]]></programlisting>
</section>
<section id="alternatives">
<title>Alternatives</title>
<para>Alternatives are beans whose implementation is specific to a particular client module or deployment
scenario. This alternative defines a mock implementation of both <literal>@Synchronous PaymentProcessor</literal>
and <literal>@Asynchronous PaymentProcessor</literal>, all in one:</para>
<programlisting role="JAVA"><![CDATA[@Alternative @Synchronous @Asynchronous
public class MockPaymentProcessor implements PaymentProcessor {
public void process(Payment payment) { ... }
}]]></programlisting>
<para>
By default, <literal>@Alternative</literal> beans are disabled. We need to <emphasis>enable</emphasis> an
alternative in the <literal>beans.xml</literal> descriptor of a bean archive to make it available for
instantiation and injection. This activation only applies to the beans in that archive.
</para>
<programlisting role="XML"><![CDATA[<beans
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
<class>org.mycompany.mock.MockPaymentProcessor</class>
</alternatives>
</beans>]]></programlisting>
<para>
When an ambiguous dependency exists at an injection point, the container attempts to resolve the ambiguity
by looking for an enabled alternative among the beans that could be injected. If there is exactly one
enabled alternative, that's the bean that will be injected.
</para>
</section>
<section>
<title>Fixing unsatisfied and ambiguous dependencies</title>
<para>
The typesafe resolution algorithm fails when, after considering the qualifier annotations on all beans that
implement the bean type of an injection point and filtering out disabled beans (<literal>@Alternative</literal>
beans which are not explicitly enabled), the container is unable to identify exactly one bean to inject. The
container will abort deployment, informing us of the unsatisfied or ambiguous dependency.
</para>
<para>
During the course of your development, you're going to encounter this situation. Let's learn how to resolve it.
</para>
<para>
To fix an <emphasis>unsatisfied dependency</emphasis>, either:
</para>
<itemizedlist>
<listitem>
<para>
create a bean which implements the bean type and has all the qualifier types of the injection point,
</para>
</listitem>
<listitem>
<para>
make sure that the bean you already have is in the classpath of the module with the injection point, or
</para>
</listitem>
<listitem>
<para>
explicitly enable an <literal>@Alternative</literal> bean that implements the bean type and has the
appropriate qualifier types, using <literal>beans.xml</literal>.
</para>
</listitem>
</itemizedlist>
<para>
To fix an <emphasis>ambiguous dependency</emphasis>, either:
</para>
<itemizedlist>
<listitem>
<para>
introduce a qualifier to distinguish between the two implementations of the bean type,
</para>
</listitem>
<listitem>
<para>
disable one of the beans by annotating it <literal>@Alternative</literal>,
</para>
</listitem>
<listitem>
<para>
move one of the implementations to a module that is not in the classpath of the module with the
injection point, or
</para>
</listitem>
<listitem>
<para>
disable one of two <literal>@Alternative</literal> beans that are trying to occupy the same space,
using <literal>beans.xml</literal>.
</para>
</listitem>
</itemizedlist>
<para>
See <ulink
url="http://sfwk.org/Documentation/HowDoAResolveAnAmbiguousResolutionExceptionBetweenAProducerMethodAndARawType">this
FAQ</ulink> for step-by-step instructions for how to resolve an ambigous resolution exception between a raw
bean type and a producer method that returns the same bean type.
</para>
<tip>
<para>Just remember: "There can be only one."</para>
</tip>
<para>
On the other hand, if you really do have an optional or multivalued injection point, you should change
the type of your injection point to <literal>Instance</literal>, as we'll see in <xref linkend="lookup"/>.
</para>
<para>
Now there's one more issue you need to be aware of when using the dependency injection service.
</para>
</section>
<section>
<title>Client proxies</title>
<para>
Clients of an injected bean do not usually hold a direct reference to a bean instance, unless the bean is
a dependent object (scope <literal>@Dependent</literal>).
</para>
<para>
Imagine that a bean bound to the application scope held a direct reference to a bean bound to the request
scope. The application-scoped bean is shared between many different requests. However, each request should see
a different instance of the request scoped bean—the current one!
</para>
<para>
Now imagine that a bean bound to the session scope holds a direct reference to a bean bound to the application
scope. From time to time, the session context is serialized to disk in order to use memory more efficiently.
However, the application scoped bean instance should not be serialized along with the session scoped bean! It
can get that reference any time. No need to hoard it!
</para>
<para>
Therefore, unless a bean has the default scope <literal>@Dependent</literal>, the container must indirect all
injected references to the bean through a proxy object. This <emphasis>client proxy</emphasis> is responsible
for ensuring that the bean instance that receives a method invocation is the instance that is associated with
the current context. The client proxy also allows beans bound to contexts such as the session context to be
serialized to disk without recursively serializing other injected beans.
</para>
<para>
Unfortunately, due to limitations of the Java language, some Java types cannot be proxied by the container.
If an injection point declared with one of these types resolves to a bean with any scope other than
<literal>@Dependent</literal>, the container will abort deployment, informing us of the problem.
</para>
<para>The following Java types cannot be proxied by the container:</para>
<itemizedlist>
<listitem>
<para>classes which don't have a non-private constructor with no parameters, and</para>
</listitem>
<listitem>
<para>
classes which are declared <literal>final</literal> or have a <literal>final</literal> method,
</para>
</listitem>
<listitem>
<para>arrays and primitive types.</para>
</listitem>
</itemizedlist>
<para>
It's usually very easy to fix an unproxyable dependency problem. If an injection point of type
<literal>X</literal> results in an unproxyable dependency, simply:
</para>
<itemizedlist>
<listitem>
<para>
add a constructor with no parameters to <literal>X</literal>,
</para>
</listitem>
<listitem>
<para>
change the type of the injection point to <literal>Instance<X></literal>,
</para>
</listitem>
<listitem>
<para>
introduce an interface <literal>Y</literal>, implemented by the injected bean, and change
the type of the injection point to <literal>Y</literal>, or
</para>
</listitem>
<listitem>
<para>
if all else fails, change the scope of the injected bean to <literal>@Dependent</literal>.
</para>
</listitem>
</itemizedlist>
<note>
<para>
A future release of Weld will likely support a non-standard workaround for this limitation, using
non-portable JVM APIs:
</para>
<itemizedlist>
<listitem>
<para>
Sun, IcedTea, Mac: <literal>Unsafe.allocateInstance()</literal> (The most efficient)
</para>
</listitem>
<listitem>
<para>
IBM, JRockit: <literal>ReflectionFactory.newConstructorForSerialization()</literal>
</para>
</listitem>
</itemizedlist>
<para>
But we didn't get around to implementing this yet.
</para>
</note>
</section>
<section id="lookup">
<title>Obtaining a contextual instance by programmatic lookup</title>
<para>
In certain situations, injection is not the most convenient way to obtain a contextual reference. For example,
it may not be used when:
</para>
<itemizedlist>
<listitem>
<para>
the bean type or qualifiers vary dynamically at runtime, or
</para>
</listitem>
<listitem>
<para>
depending upon the deployment, there may be no bean which satisfies the type and qualifiers, or
</para>
</listitem>
<listitem>
<para>
we would like to iterate over all beans of a certain type.
</para>
</listitem>
</itemizedlist>
<para>
In these situations, the application may obtain an instance of the interface <literal>Instance</literal>,
parameterized for the bean type, by injection:
</para>
<programlisting role="JAVA"><![CDATA[@Inject Instance<PaymentProcessor> paymentProcessorSource;]]></programlisting>
<para>
The <literal>get()</literal> method of <literal>Instance</literal> produces a contextual instance of the bean.
</para>
<programlisting role="JAVA"><![CDATA[PaymentProcessor p = paymentProcessorSource.get();]]></programlisting>
<para>
Qualifiers can be specified in one of two ways:
</para>
<itemizedlist>
<listitem>
<para>by annotating the <literal>Instance</literal> injection point, or</para>
</listitem>
<listitem>
<para>by passing qualifiers to the <literal>select()</literal> of <literal>Event</literal>.</para>
</listitem>
</itemizedlist>
<para>
Specifying the qualifiers at the injection point is much, much easier:
</para>
<programlisting role="JAVA"><![CDATA[@Inject @Asynchronous Instance<PaymentProcessor> paymentProcessorSource;]]></programlisting>
<para>
Now, the <literal>PaymentProcessor</literal> returned by <literal>get()</literal> will have the qualifier
<literal>@Asynchronous</literal>.
</para>
<para>
Alternatively, we can specify the qualifier dynamically. First, we add the <literal>@Any</literal> qualifier to
the injection point, to suppress the default qualifier. (All beans have the qualifier <literal>@Any</literal>.)
</para>
<programlisting role="JAVA"><![CDATA[@Inject @Any Instance<PaymentProcessor> paymentProcessorSource;]]></programlisting>
<para>
Next, we need to obtain an instance of our qualifier type. Since annotatons are interfaces, we can't just write
<literal>new Asynchronous()</literal>. It's also quite tedious to create a concrete implementation of an annotation
type from scratch. Instead, CDI lets us obtain a qualifier instance by subclassing the helper class
<literal>AnnotationLiteral</literal>.
</para>
<programlisting role="JAVA"><![CDATA[abstract class AsynchronousQualifier
extends AnnotationLiteral<Asynchronous> implements Asynchronous {}]]></programlisting>
<para>
In some cases, we can use an anonymous class:
</para>
<programlisting role="JAVA"><![CDATA[PaymentProcessor p = paymentProcessorSource
.select(new AnnotationLiteral<Asynchronous>() {});]]></programlisting>
<note>
<para>
We can't use an anonymous class to implement a qualifier type with members.
</para>
</note>
<para>
Now, finally, we can pass the qualifier to the <literal>select()</literal> method of <literal>Instance</literal>.
</para>
<programlisting><![CDATA[Annotation qualifier = synchronously ?
new SynchronousQualifier() : new AsynchronousQualifier();
PaymentProcessor p = anyPaymentProcessor.select(qualifier).get().process(payment);]]></programlisting>
</section>
<section>
<title>The <literal>InjectionPoint</literal> object</title>
<para>There are certain kinds of dependent objects (beans with scope <literal>@Dependent</literal>)
that need to know something about the object or injection point into which they are injected in order
to be able to do what they do. For example:</para>
<itemizedlist>
<listitem>
<para>The log category for a <literal>Logger</literal> depends upon the class of the object
that owns it.</para>
</listitem>
<listitem>
<para>Injection of a HTTP parameter or header value depends upon what parameter
or header name was specified at the injection point.</para>
</listitem>
<listitem>
<para>Injection of the result of an EL expression evaluation depends upon the
expression that was specified at the injection point.</para>
</listitem>
</itemizedlist>
<para>A bean with scope <literal>@Dependent</literal> may inject an instance of
<literal>InjectionPoint</literal> and access metadata relating to the injection point to which
it belongs.</para>
<para>Let's look at an example. The following code is verbose, and vulnerable to refactoring
problems:</para>
<programlisting role="JAVA"><![CDATA[Logger log = Logger.getLogger(MyClass.class.getName());]]></programlisting>
<para>This clever little producer method lets you inject a JDK <literal>Logger</literal> without
explicitly specifying the log category:</para>
<programlisting role="JAVA"><![CDATA[class LogFactory {
@Produces Logger createLogger(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}]]></programlisting>
<para>We can now write:</para>
<programlisting role="JAVA"><![CDATA[@Inject Logger log;]]></programlisting>
<para>Not convinced? Then here's a second example. To inject HTTP parameters, we need to define
a qualifier type:</para>
<programlisting role="JAVA"><![CDATA[@BindingType
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
@Nonbinding public String value();
}]]></programlisting>
<para>We would use this qualifier type at injection points as follows:</para>
<programlisting role="JAVA"><![CDATA[@HttpParam("username") String username;
@HttpParam("password") String password;]]></programlisting>
<para>The following producer method does the work:</para>
<programlisting role="JAVA"><![CDATA[class HttpParams
@Produces @HttpParam("")
String getParamValue(ServletRequest request, InjectionPoint ip) {
return request.getParameter(ip.getAnnotated().getAnnotation(HttpParam.class).value());
}
}]]></programlisting>
<para>(Note that the <literal>value()</literal> member of the <literal>HttpParam</literal>
annotation is ignored by the container since it is annotated <literal>@Nonbinding.</literal>)</para>
<para>The container provides a built-in bean that implements the <literal>InjectionPoint</literal>
interface:</para>
<programlisting role="JAVA"><![CDATA[public interface InjectionPoint {
public Type getType();
public Set<Annotation> getQualifiers();
public Bean<?> getBean();
public Member getMember();
public Annotated getAnnotated();
public boolean isDelegate();
public boolean isTransient();
}]]></programlisting>
</section>
<!--
vim:et:ts=3:sw=3:tw=120
-->
</chapter>