Sim, você pode misturar livremente CDI e EJB e obter ótimos resultados. Parece que você está usando @WebServicee @Schedule, que são boas razões para adicionar EJB ao mix.
Há muita confusão por aí, então aqui estão algumas informações gerais sobre EJB e CDI, pois elas se relacionam entre si.
EJB> = CDI
Observe que os EJBs são beans CDI e, portanto, têm todos os benefícios do CDI. O inverso ainda não é verdadeiro. Portanto, definitivamente, não adquira o hábito de pensar "EJB vs CDI", pois essa lógica realmente se traduz em "EJB + CDI vs CDI", que é uma equação ímpar.
Nas versões futuras do Java EE, continuaremos alinhando-os. O que significa alinhar está permitindo que as pessoas façam o que eles já podem fazer, apenas sem o @Stateful, @Statelessou @Singletonanotação no topo.
EJB e CDI em termos de implementação
Por fim, o EJB e o CDI compartilham o mesmo design fundamental de serem componentes de proxy. Quando você obtém uma referência a um bean EJB ou CDI, não é o bean real. Em vez disso, o objeto que você recebe é falso (um proxy). Quando você invoca um método nesse objeto falso, a chamada vai para o contêiner que enviará a chamada por interceptadores, decoradores etc., além de cuidar de qualquer transação ou verificação de segurança. Feito tudo isso, a chamada finalmente vai para o objeto real e o resultado é passado de volta pelo proxy para o chamador.
A diferença ocorre apenas em como o objeto a ser chamado é resolvido. Por "resolvido", queremos dizer simplesmente onde e como o contêiner procura a instância real para invocar.
No CDI, o contêiner procura um "escopo", que basicamente será um hashmap que dura um período específico de tempo (por solicitação @RequestScoped, por sessão HTTP @SessionScoped, por aplicativo @ApplicationScoped, conversação JSF @ConversationScopedou por sua implementação de escopo personalizado).
No EJB, o contêiner também pesquisará um hashmap se o bean for do tipo @Stateful. Um @Statefulbean também pode usar qualquer uma das anotações de escopo acima, fazendo com que ele viva e morra com todos os outros beans no escopo. No EJB @Statefulé essencialmente o bean "qualquer escopo". O @Statelessbasicamente é um pool de instâncias - você obtém uma instância do pool pela duração de uma chamada. O @Singletoné essencialmente@ApplicationScoped
Portanto, em um nível fundamental, qualquer coisa que você possa fazer com um bean "EJB", deverá poder fazer com um bean "CDI". Sob as cobertas, é muito difícil diferenciá-los. Todo o encanamento é o mesmo, com exceção de como as instâncias são resolvidas.
Atualmente, eles não são os mesmos em termos de serviços que o contêiner oferecerá ao fazer esse proxy, mas como eu disse, estamos trabalhando nele no nível de especificação do Java EE.
Nota de desempenho
Desconsidere qualquer imagem mental "leve" ou "pesada" que você possa ter. Isso é tudo de marketing. Eles têm o mesmo design interno para a maior parte. A resolução da instância CDI é talvez um pouco mais complexa porque é um pouco mais dinâmica e contextual. A resolução da instância EJB é relativamente estática, burra e simples em comparação.
Posso dizer a você, do ponto de vista da implementação no TomEE, que há uma diferença de desempenho zero entre invocar um EJB e invocar um CDI bean.
Padrão para POJOs, CDI e EJB
Obviamente, não use CDI ou EJB quando não houver benefício. Coloque o CDI quando começar a querer injeção, eventos, interceptadores, decoradores, rastreamento do ciclo de vida e coisas assim. Essa é a maior parte do tempo.
Além desses princípios, há uma série de serviços de contêiner úteis que você só tem a opção de usar se você fizer seu bean CDI também um EJB, adicionando @Stateful, @Statelessou @Singletonsobre ele.
Aqui está uma pequena lista de quando eu desmembrar os EJBs.
Usando JAX-WS
Expondo um JAX-WS @WebService. Sou preguiçosa. Quando @WebServicetambém é um EJB, você não precisa listá-lo e mapeá-lo como um servlet no web.xmlarquivo. Isso é trabalho para mim. Além disso, tenho a opção de usar qualquer outra funcionalidade mencionada abaixo. Portanto, é um acéfalo para mim.
Disponível para @Statelesse @Singletonsomente.
Usando JAX-RS
Expondo um recurso JAX-RS via @Path. Eu ainda sou preguiçoso. Quando o serviço RESTful também é um EJB, você obtém novamente a descoberta automática e não precisa adicioná-lo a uma Applicationsubclasse JAX-RS ou algo assim. Além disso, posso expor exatamente o mesmo bean que um @WebServicese eu quiser ou usar qualquer uma das excelentes funcionalidades mencionadas abaixo.
Disponível para @Statelesse @Singletonsomente.
Lógica de inicialização
Carregar na inicialização via @Startup. Atualmente, não há equivalente a isso no CDI. De alguma forma, perdemos a adição de algo como um AfterStartupevento no ciclo de vida do contêiner. Se tivéssemos feito isso, você simplesmente poderia ter um @ApplicationScopedbean que o ouviu e que seria efetivamente o mesmo que um @Singletoncom @Startup. Está na lista do CDI 1.1.
Disponível @Singletonapenas para .
Trabalhando em Paralelo
@Asynchronousinvocação de método. Iniciar threads é um não-não em qualquer ambiente do lado do servidor. Ter muitos threads é um sério problema de desempenho. Essa anotação permite paralelizar as coisas que você faz usando o conjunto de encadeamentos do contêiner. Isso é incrível.
Disponível para @Stateful, @Statelesse @Singleton.
Agendamento de trabalho
@Scheduleou ScheduleExpressioné basicamente um cron ou Quartzfuncionalidade. Também é incrível. A maioria dos contêineres usa apenas quartzo sob as tampas para isso. A maioria das pessoas não sabe, no entanto, que o trabalho de agendamento no Java EE é transacional! Se você atualizar um banco de dados, agende algum trabalho e um deles falhará, ambos serão limpos automaticamente. Se a EntityManagerchamada persistir falhar ou houver um problema na liberação, não há necessidade de cancelar o agendamento do trabalho. Yay, transações.
Disponível para @Statelesse @Singletonsomente.
Usando EntityManagers em uma transação JTA
A nota acima sobre transações, é claro, exige que você use um JTAgerenciado EntityManager. Você pode usá-los com "CDI" simples, mas sem as transações gerenciadas por contêiner, pode ser realmente monótono duplicar a UserTransactionlógica de confirmação / reversão.
Disponível para todos os componentes Java EE, incluindo CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter, etc. A @TransactionAttributeanotação, no entanto, está disponível para @Stateful, @Statelesse @Singletonúnica.
Mantendo o JTA gerenciado EntityManager
O EXTENDEDgerenciado EntityManagerpermite manter uma EntityManagerabertura entre as JTAtransações e não perder os dados em cache. Bom recurso para a hora e o local certos. Use com responsabilidade :)
Disponível @Statefulapenas para .
Fácil sincronização
Quando você precisa de sincronização, as anotações @Lock(READ)e @Lock(WRITE)são excelentes. Ele permite que você obtenha gerenciamento de acesso simultâneo gratuitamente. Ignore todo o encanamento ReentrantReadWriteLock. No mesmo depósito @AccessTimeout, você pode dizer quanto tempo um encadeamento deve esperar para obter acesso à instância do bean antes de desistir.
Disponível @Singletonapenas para beans.