SeamFramework.orgCommunity Documentation
CDI está plenamente integrada ao ambiente Java EE. Os beans possuem acesso aos recursos Java EE e aos contextos de persistência JPA. Eles podem ser utilizados em expressões EL Unificadas (Unified EL) e em páginas JSF e JSP. Podem até ser injetados em outros componentes da plataforma, tais como servlets e message-driven Beans, que não são bens por si só.
No ambiente Java EE, o contêiner fornece os seguintes beans embutidos, todos com o qualificador @Default
:
o UserTransaction
JTA corrente,
um Principal
representando a identidade do requisitante corrente,
a ValidationFactory
padrão da Bean Validation, e
um Validator
para a ValidationFactory
padrão.
A especificação CDI não requer que os objetos de contexto de servlet HttpServletRequest
, HttpSession
e ServletContext
sejam expostos como beans injetáveis. Se você realmente quer ser capaz de injetar estes objetos, é fácil criar uma extensão portável para expô-los como beans. No entanto, recomendamos que o acesso direto a estes objetos estejam limitados a servlets, servlet filters e servlet event listeners, onde podem ser obtidos da maneira usual, tal como definido pela especificação Java Servlets. O objeto FacesContext
também não é injetável. Você pode obtê-lo chamando FacesContext.getCurrentInstance()
.
Oh, você realmente quer injetar o FacesContext
? Tudo bem então, tente este método produtor:
class FacesContextProducer {
@Produces @RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
Todos os beans gerenciados poder tirar vantagem da injeção de componentes do ambiente Java EE usando @Resource
, @EJB
, @PersistenceContext
, @PeristenceUnit
e @WebServiceRef
. Nós já vimos uma porção de exemplos disto, embora não tenhamos prestado muita atenção no momento:
@Transactional @Interceptor
public class TransactionInterceptor {
@Resource UserTransaction transaction;
@AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}
@SessionScoped
public class Login implements Serializable {
@Inject Credentials credentials;
@PersistenceContext EntityManager userDatabase;
...
}
As chamadas Java EE @PostConstruct
e @PreDestroy
também são suportadas em todos os beans controlados. O método anotado com @PostConstruct
é invocado após todas injeções serem realizadas.
Certamente, aconselhamos que a injeção de componentes do ambiente seja usada para definir recursos CDI, e que injeção typesafe seja usada no código da aplicação.
É fácil usar um bean a partir de uma servlet no Java EE 6. Simplesmente injete o bean usando um campo ou injeção por um método inicializador.
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");
}
}
}
Uma vez que instâncias de servlets são compartilhadas através de todas threads entrantes, o proxy cliente cuida do encaminhamento das invocações dos métodos do servlet para as instâncias corretas de Credentials
e Login
para a requisição e sessão HTTP atuais.
A injeção CDI se aplica a todos EJBs, mesmo quando eles não são beans gerenciados. Em especial, você pode usar injeção CDI em message-driven beans, os quais são por natureza objetos não contextuais.
Você ainda pode usar bindings de interceptação da CDI em message-driven Beans.
@Transactional @MessageDriven
public class ProcessOrder implements MessageListener {
@Inject Inventory inventory;
@PersistenceContext EntityManager em;
public void onMessage(Message message) {
...
}
}
Note que existe nenhuma sessão ou contexto de conversação disponível quando uma mensagem é entregue a um message-driven bean. Apenas benas @RequestScoped
e @ApplicationScoped
estão disponíveis.
Mas como que beans enviam mensagens JMS?
O envio de mensagens usando JMS pode ser bastante complexo, devido à quantidade de objetos diferentes que precisamos utilizar. Para filas, temos Queue
, QueueConnectionFactory
, QueueConnection
, QueueSession
e QueueSender
. Para os tópicos, temos Topic
, TopicConnectionFactory
, TopicConnection
, TopicSession
e TopicPublisher
. Cada um desses objetos tem seu próprio ciclo de vida e modelo de threads, com que temos de nos preocupar.
Você pode usar campos e métodos produtores para preparar todos estes recursos para injeção em um bean:
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();
}
}
Neste exemplo, podemos injetar apenas MessageProducer
, Connection
ou QueueSession
:
@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);
}
O ciclo de vida dos objetos JMS injetados são completamente controlados pelo contêiner.
CDI não define qualquer arquivo de implantação especial. Você pode empacotar beans em jars, ejb jars ou wars—qualquer local no classpath da aplicação em implantação. Entretanto, o arquivo deve ser um "arquivo de beans". Isto significa que arquivos contendo beans deve incluir um arquivo nomeado como beans.xml
no diretório META-INF
do classpath ou no diretório WEB-INF
(para arquivos war). O arquivo pode ser vazio. Os beans implantados em arquivos que não possuam um beans.xml
não estarão disponíveis para uso na aplicação.
Em um contêiner EJB embutido, os beans podem ser implantados em qualquer local em que EJBs podem ser implantados. Novamente, cada local deve conter um arquivo beans.xml
.