ee.xml
10.8 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
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ ]>
<chapter id="ee">
<title>Java EE integration</title>
<para>
CDI is fully integrated into the Java EE environment. Beans have access to Java EE resources and JPA persistence
contexts. They may be used in Unified EL expressions in JSF and JSP pages. They may even be injected into other
platform components, such as servlets and message-driven Beans, which are not beans themselves.
</para>
<section>
<title>Built-in beans</title>
<para>
In the Java EE environment, the container provides the following built-in beans, all with the qualifier
<literal>@Default</literal>:
</para>
<itemizedlist>
<listitem>
<para>
the current JTA <literal>UserTransaction</literal>,
</para>
</listitem>
<listitem>
<para>
a <literal>Principal</literal> representing the current caller identity,
</para>
</listitem>
<listitem>
<para>
the default <ulink url="http://jcp.org/en/jsr/detail?id=303">Bean Validation</ulink>
<literal>ValidationFactory</literal>, and
</para>
</listitem>
<listitem>
<para>
a <literal>Validator</literal> for the default <literal>ValidationFactory</literal>.
</para>
</listitem>
</itemizedlist>
<note>
<para>
The CDI specification does not require the servlet context objects, <literal>HttpServletRequest</literal>,
<literal>HttpSession</literal> and <literal>ServletContext</literal> to be exposed as injectable beans. If
you really want to be able to inject these objects, it's easy to create a portable extension to expose them
as beans. However, we recommend that direct access to these objects be limited to servlets, servlet filters
and servlet event listeners, where they may be obtained in the usual way as defined by the Java Servlets spec.
The <literal>FacesContext</literal> is also not injectable. You can get at it by calling
<literal>FacesContext.getCurrentInstance()</literal>.
</para>
</note>
<tip>
<para>
Oh, you <emphasis>really</emphasis> want to inject the <literal>FacesContext</literal>? Alright then, try
this producer method:
</para>
<programlisting role="JAVA"><![CDATA[class FacesContextProducer {
@Produces @RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}]]></programlisting>
</tip>
</section>
<section>
<title>Injecting Java EE resources into a bean</title>
<para>
All managed beans may take advantage of Java EE component environment injection using <literal>@Resource</literal>,
<literal>@EJB</literal>, <literal>@PersistenceContext</literal>, <literal>@PeristenceUnit</literal> and
<literal>@WebServiceRef</literal>. We've already seen a couple of examples of this, though we didn't pay
much attention at the time:
</para>
<programlisting role="JAVA"><![CDATA[@Transactional @Interceptor
public class TransactionInterceptor {
@Resource UserTransaction transaction;
@AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}]]></programlisting>
<programlisting role="JAVA"><![CDATA[@SessionScoped
public class Login implements Serializable {
@Inject Credentials credentials;
@PersistenceContext EntityManager userDatabase;
...
}]]></programlisting>
<para>
The Java EE <literal>@PostConstruct</literal> and <literal>@PreDestroy</literal> callbacks are also supported
for all managed beans. The <literal>@PostConstruct</literal> method is called after <emphasis>all</emphasis>
injection has been performed.
</para>
<para>
Of course, we advise that component environment injection be used to define CDI resources, and that typesafe
injection be used in application code.
</para>
</section>
<section>
<title>Calling a bean from a servlet</title>
<para>
It's easy to use a bean from a servlet in Java EE 6. Simply inject the bean using field or initializer method
injection.
</para>
<programlisting role="JAVA"><![CDATA[public class Login extends HttpServlet {
@Inject Credentials credentials;
@Inject Login login;
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
credentials.setUsername(request.getParameter("username")):
credentials.setPassword(request.getParameter("password")):
login.login();
if ( login.isLoggedIn() ) {
response.sendRedirect("/home.jsp");
}
else {
response.sendRedirect("/loginError.jsp");
}
}
}]]></programlisting>
<para>
Since instances of servlets are shared across all incoming threads, the bean client proxy takes care of routing
method invocations from the servlet to the correct instances of <literal>Credentials</literal> and
<literal>Login</literal> for the current request and HTTP session.
</para>
</section>
<section>
<title>Calling a bean from a message-driven bean</title>
<para>
CDI injection applies to all EJBs, even when they aren't managed beans. In particular, you can use CDI
injection in message-driven beans, which are by nature not contextual objects.
</para>
<para>You can even use CDI interceptor bindings for message-driven Beans.</para>
<programlisting role="JAVA"><![CDATA[@Transactional @MessageDriven
public class ProcessOrder implements MessageListener {
@Inject Inventory inventory;
@PersistenceContext EntityManager em;
public void onMessage(Message message) {
...
}
}]]></programlisting>
<para>
Please note that there is no session or conversation context available when a message is delivered to a
message-driven bean. Only <literal>@RequestScoped</literal> and <literal>@ApplicationScoped</literal>
beans are available.
</para>
<para>
But how about beans which <emphasis>send</emphasis> JMS messages?
</para>
</section>
<section id="jms">
<title>JMS endpoints</title>
<para>
Sending messages using JMS can be quite complex, because of the number of different objects you need to deal
with. For queues we have <literal>Queue</literal>, <literal>QueueConnectionFactory</literal>,
<literal>QueueConnection</literal>, <literal>QueueSession</literal> and <literal>QueueSender</literal>. For
topics we have <literal>Topic</literal>, <literal>TopicConnectionFactory</literal>,
<literal>TopicConnection</literal>, <literal>TopicSession</literal> and <literal>TopicPublisher</literal>. Each
of these objects has its own lifecycle and threading model that we need to worry about.
</para>
<para>
You can use producer fields and methods to prepare all of these resources for injection into a bean:
</para>
<programlisting role="JAVA"><![CDATA[public class OrderResources {
@Resource(name="jms/ConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/OrderQueue")
private Queue orderQueue;
@Produces @OrderConnection
public Connection createOrderConnection() throws JMSException {
return connectionFactory.createConnection();
}
public void closeOrderConnection(@Disposes @OrderConnection Connection connection)
throws JMSException {
connection.close();
}
@Produces @OrderSession
public Session createOrderSession(@OrderConnection Connection connection)
throws JMSException {
return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
}
public void closeOrderSession(@Disposes @OrderSession Session session)
throws JMSException {
session.close();
}
@Produces @OrderMessageProducer
public MessageProducer createOrderMessageProducer(@OrderSession Session session)
throws JMSException {
return session.createProducer(orderQueue);
}
public void closeOrderMessageProducer(@Disposes @OrderMessageProducer MessageProducer producer)
throws JMSException {
producer.close();
}
}]]></programlisting>
<para>
In this example, we can just inject the prepared <literal>MessageProducer</literal>,
<literal>Connection</literal> or <literal>QueueSession</literal>:
</para>
<programlisting role="JAVA"><![CDATA[@Inject Order order;
@Inject @OrderMessageProducer MessageProducer producer;
@Inject @OrderSession QueueSession orderSession;
public void sendMessage() {
MapMessage msg = orderSession.createMapMessage();
msg.setLong("orderId", order.getId());
...
producer.send(msg);
}]]></programlisting>
<!--
<programlisting role="JAVA"><![CDATA[@Inject @StockPrices TopicPublisher pricePublisher;
@Inject @StockPrices TopicSession priceSession;
public void sendMessage(String price) {
pricePublisher.send(priceSession.createTextMessage(price));
}]]></programlisting>
-->
<para>
The lifecycle of the injected JMS objects is completely controlled by the container.
</para>
</section>
<section>
<title>Packaging and deployment</title>
<para>
CDI doesn't define any special deployment archive. You can package beans in jars, ejb jars or wars—any
deployment location in the application classpath. However, the archive must be a "bean archive". That means
each archive that contains beans <emphasis>must</emphasis> include a file named <literal>beans.xml</literal> in
the <literal>META-INF</literal> directory of the classpath or <literal>WEB-INF</literal> directory of the web
root (for war archives). The file may be empty. Beans deployed in archives that do not have a
<literal>beans.xml</literal> file will not be available for use in the application.
</para>
<para>
In an embeddable EJB container, beans may be deployed in any location in which EJBs may be deployed. Again, each
location must contain a <literal>beans.xml</literal> file.
</para>
</section>
<!--
vim:et:ts=3:sw=3:tw=120
-->
</chapter>