25 de out. de 2017

Usando CDI 2.0 em uma aplicação JavaFX

Com o lançamento do CDI 2.0 nós temos um container que pode ser usado em uma aplicação Java SE! Anteriorment se você quisesse fazer uso de CDI em uma aplicação Java SE você teria que usar classes proprietárias do Weld, veja o artigo FXML & JavaFX—Fueled by CDI & JBoss Weld.

Essa feature é bem explicada pelo Adam Bien em um vídeo, veja:


Claro que era meu objetivo tentar isso em uma aplicação javaFX e nesse artigo breve compartilharei com vocês a minha experiência e o código.

Crie o container em uma aplicação JavaFX


Uma aplicação JavaFX é uma classe que estende de javafx.application.Application, que é o ponto de entrada para aplicações JavaFX e onde o stage principal pode ser usado. Para usar CDI devemos criar o SeContainer e certificar-se que ele irá criar todas as classes gerenciadas pelo CDI. Isso deve ser feito no ponto de entrada da Application para que possamos gerenciar todas as classes criadas de lá.

Uma vez criado o container você tem diferente formas de enviar o Stage para a aplicação JavaFX (a que você vai programar e não a que criamos para grudar CDI ao javaFX). Por exemplo, você pode fazer com que users possam estender uma interface e então injetar a classe do usuário dentro da nossa CDI application para invocar por lá.



Hpa uma forma mais elegante que é usando a API de observer do CDI. Nesse caso podemos criar uma anotação que será o qualifier para o evento  javafx.stage.Stage. CDI sabe inteligentemente as classes que observam aquele evento e vai selecionar a classe quando ativarmos o evento com o stage principal. Isso é semelhante ao que você pode ver no artigo que mencionamos FXML & JavaFX—Fueled by CDI & JBoss Weld.



Independente da solução que escolher não "desligue o container" ou isso pode deixar app inconsistente. Na verdade isso não deve afetar muito, mas eu decidi não fazer o shutdown.

Beleza! Daqui pra frente você pode usar CDI na sua app! Vá em frente e injete coisas nas suas classes JavaFX. Exceto, é claro, se você estiver usando FXML. Nesse caso JavaFX cria os controllers para você usando reflection e CDI não estará ciente da classe criada, ou seja, vai tudo ser nulo pois CDI não injetará. Uma solução é criar um FXMLLoader e fazer o CDI criar os controllers invés de deixar o FXML loader criar ele. O código abaixo foi novamente pego de  FXML & JavaFX—Fueled by CDI & JBoss Weld mas com a adição do delicioso lambda do Java 8:






Finalmente você pode criar sua própria aplicação mas NUNCA chame os métodos estáticos do FXMLLoader, use o injetado, por exemplo:



Lembre que você agora pode injetar coisas no seu controller. No nosso caso eu injetei um clássico Greeter, semelhante ao que abordo no post Primeiros Passos com CDI:





Não se esqueça também  do arquivo vazio beans.xml que irá ativar CDI. Essa é a estrutura do projeto que eu usei nos meus testes:




O resultado final foi mostrado abaixo - a diferença é que a mensagem veio de um bean gerenciado por FXML:


O código completo pode ser encontrado no github.

2 comentários:

  1. Hi William

    How could I create a second stage for modal dialogs? I've been trying to do that, but the fields of the fxml controller of the modal stage don't get injected, they remain null

    How could be a strategy to create modal stages CDI compliant?

    ResponderExcluir
    Respostas
    1. Poderia compartilhar seu código no github para vermos?

      Excluir