Archive

Posts Tagged ‘JavaEE 6’

Desenvolvendo uma aplicação Desktop com Weld – Final

May 25th, 2010 2 comments

Depois da parte 1 e parte 2, chegamos à parte final do nosso exemplo. Disponibilizei o código e vou mostrar mais algumas coisas.
Só uma observação sobre o código: é o mesmo utilizado na apresentação de 14 de Novembro de 2009, quando ainda não tínhamos as mesmas versões de hoje. Mas o exemplo é totalmente funcional. Acabei deixando fixa a versão no pom.xml, então para testar a última versão você vai ter que alterá-lo.

Agora voltando ao post…


Alternatives


Alternatives são a forma de trocarmos um objeto por outro. É parecido com um decorator, mas em vez de incrementar funcionalidades, um alternative serve para substituir um bean.

No nosso exemplo, temos o seguinte objeto como alternativa ao nosso CaixaEletronico:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Alternative
public class CaixaEletronicoSubstituto extends CaixaEletronico{
 
 
	public void depositar(float valor)
	{
		System.out.println("@@@@@@ CaixaEletronicoMock.depositar():" + valor);
	}
	public void sacar(float valor)
	{
		System.out.println("@@@@@@ CaixaEletronicoMock.sacar():" + valor);
	}
}


E para habilitar temos que mudar novamente nosso META-INF/beans.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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">
 
	<interceptors>
		<class>br.com.jugms.weldse.intercept.ContaInterceptor</class>
	</interceptors>
 
	<decorators>
		<class>br.com.jugms.weldse.intercept.CaixaDecorator</class>
	</decorators>
 
	<alternatives>
		<class>br.com.jugms.weldse.model.CaixaEletronicoSubstituto</class>
	</alternatives>
 
</beans>


Agora se executarmos nosso código a saída sera:

hello
CaixaDecorator.sacar()
@@@@@@ CaixaEletronicoMock.sacar():200.0
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
2000.0
CaixaDecorator.depositar()
@@@@@@ CaixaEletronicoMock.depositar():300.0
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
2000.0


Como podemos ver, nosso decorator decora o alternative e o interceptor continua funcionando normalmente.
Podemos também declarar uma anotação própria e anotá-la como alternative. Mas em vez de tentar explicar, vou mostrar um outro exemplo que servirá como base para este.


Estereótipos próprios


Podemos criar nossos próprios estereótipos, e dessa forma não só reduzir a quantidade de anotações em cima dos nossos beans, mas também deixar a leitura das anotações mais condizentes com nosso linguajar do dia a dia.

Vamos pegar como exemplo o nosso objeto ContaBancaria:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package br.com.jugms.weldse.model;
 
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Named;
 
import br.com.jugms.weldse.intercept.Seguro;
 
@ApplicationScoped
@Seguro
public class ContaBancaria {
	//o código já foi visto antes
}


Já vimos este código e o corpo da classe não tem relação com o que vamos ver agora. Agora o mais importante é observarmos as anotações. Temos duas, mas poderíamos ter mais. Para deixar isso mais limpo e com mais significado no meu negócio, poderia criar um estereótipo próprio como o seguinte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.com.jugms.weldse.model;
 
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Stereotype;
 
import br.com.jugms.weldse.intercept.Seguro;
 
@ApplicationScoped
@Seguro
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface JavaneirosBean {
}


E depois mudar nosso ContaBancaria deixando ele assim:

1
2
3
4
5
6
7
8
9
10
package br.com.jugms.weldse.model;
 
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Named;
 
@JavaneirosBean
public class ContaBancaria {
	//o código já foi visto antes
}


Com isso o resultado será o mesmo de antes. Nosso objeto ContaBancaria é @Seguro e @ApplicationScoped. Além disso se depois quisermos dizer que nosso @JavaneirosBean é também um @Alternative ou qualquer outro estereótipo pré-existente ou mesmo um outro estereótipo customizado, basta anotar nossa anotação @JavaneirosBean com a anotação desejada.

Pode parecer estranho usarmos anotações de anotações, mas para exemplificar, se a JPA suportasse isso eu poderia ter uma anotação @Entidade que seria uma @Entity (JPA) e ao mesmo tempo @Named (CDI) e assim poder utilizá-la diretamente nas minhas view JSF com uma única anotação.


Conceitos gerais


Eu disse que ao final do exemplo iria entrar mais na parte teórica de como a CDI trata mais extamente a injeção de dependência, seleção de candidatos etc. Porém por questão de organização, vou deixar isso em um post separado.

Desenvolvendo uma aplicação Desktop com Weld – Parte 2

May 25th, 2010 5 comments

Continuando então no nosso exemplo, vamos comentar mais sobre a “parte prática” do exemplo e depois eu comento mais sobre os tipos de injeção que a CDI faz. E só pra contextualizar, quando eu disse “ejeção” no último post, não quer dizer que a CDI tem um @Out como o Seam, e sim que ele tem uma forma de produzir objetos para um determinado escopo assim como um @Factory do Seam ou Spring.


Interceptors


No final do ultimo post vimos que nossa ContaBancaria estava anotada com @Seguro. Essa é uma anotação da nossa aplicação:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package br.com.jugms.weldse.intercept;
 
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import javax.interceptor.InterceptorBinding;
 
@InterceptorBinding
@Target( { METHOD, TYPE })
@Retention(RUNTIME)
public @interface Seguro {
}


No meio de um monte de anotações percebemos a que define nossa anotação como uma @InterceptorBinding. Agora basta anotar quem queremos interceptar com a mesma anotação usada na definição do interceptor (@Seguro) para “bindar” interceptador e interceptado.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package br.com.jugms.weldse.intercept;
 
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
 
 
@Interceptor @Seguro
public class ContaInterceptor {
 
	@AroundInvoke
	public Object protege(InvocationContext context) throws Exception
	{
		System.out.println("ContaInterceptor.protege(antes) >> " + context.getMethod().getName());
 
		Object object = context.proceed();
 
		System.out.println("ContaInterceptor.protege(depois) >> " + context.getMethod().getName());
 
		return object;
	}
}


Esse é o nosso interceptador. Olhando o código quase não preciso explicar nada. Aqui coloquei Conta no meio do nome porque é uma aplicação de exemplo, mas na prática poderia ter um uso mais genérico. Esse código tem o jeitão de um interceptador comum. O método “protege” está anotado com @AroundInvoke, e isso me dá o poder de envolver, e com isso até mesmo trocar a implementação original do objeto interceptado. É bem parecido com AOP. Mas a regra do tio Ben se aplica aqui também: “Grandes poderes trazem grandes responsabilidades”! Então isso não serve para ficar adicionando regra de negócio na aplicação, senão depois você não vai achar mais nada no sistema e vai falar que viu isso aqui. A idéia de um interceptor é prover funcionalidades ortogonais para o sistema, assim como AOP. Então se você não gosta de AOP ou interceptor é provavelmente porque está colocando código no local errado.

Nesse exemplo usei para prover segurança, protegendo meus objetos marcados com @Seguro. Mas minha implementação simplesmente mostra no console que o nosso método foi chamado.

Além de interceptors, temos decorators, que veremos daqui a pouco. Mas para já ter uma idéia da diferença, o interceptor geralmente é para requisitos não funcionais, enquanto os decorators adicionam funcionalidades em objetos do nosso sistema. Mas o foco aqui não é padrões de projeto, então para saber mais basta dar uma pesquisada. O que importa para o contexto desse post é que tanto interceptors quanto decorators não estão habilitados por padrão. Para colocá-los para rodar precisamos “ligá-los” no arquivo /META-INF/beans.xml. Abaixo vemos como fica nosso arquivo com esse interceptor ligado.


1
2
3
4
5
6
7
8
<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">
 
	<interceptors>
		<class>br.com.jugms.weldse.intercept.ContaInterceptor</class>
	</interceptors>
 
</beans>


Eu sei que sou repetitivo, mas mais uma vez eu digo: não precisamos habilitar beans injetáveis ou gerenciáveis quando usamos CDI. Basta que os objetos estejam em um bean package para tudo acontecer, e um bean package é um módulo (jar, projeto, etc) que tenha um arquivo /META-INF/beans.xml vazio (só com cabeçalho). Pronto, só precisa disso. As exceções são para interceptors, decorators e alternatives (esse ultimo falo depois). Esses sim precisam ser habilitados.

Agora que já temos tudos os arquivos, executando a aplicação temos a seguinte saída:

hello
ContaInterceptor.protege(antes) >> recebeMovimento
ContaInterceptor.protege(depois) >> recebeMovimento
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
1800.0
ContaInterceptor.protege(antes) >> recebeMovimento
ContaInterceptor.protege(depois) >> recebeMovimento
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
2100.0

Como estamos usando @AroundInvoke, colocamos uma mensagem antes e uma depois de cada método.


Decorators


Agora que vimos o interceptor, fica mais fácil entendermos o decorator. Vamos ao código

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
package br.com.jugms.weldse.intercept;
 
import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;
 
import br.com.jugms.weldse.model.CaixaEletronico;
 
@Decorator
public class CaixaDecorator extends CaixaEletronico {
 
	@Inject
	@Delegate
	private CaixaEletronico delegate;
 
	@Override
	public void sacar(float valor) {
 
		System.out.println("CaixaDecorator.sacar()");
 
		delegate.sacar(valor);
	}
 
	@Override
	public void depositar(float valor) {
 
		System.out.println("CaixaDecorator.depositar()");
 
		delegate.depositar(valor);
	}
}


Um decorator precisa ter condições de substituir o objeto original (extender, implementar mesma interface). Além disso temos o objeto original que é injetado através da anotação @Delegate juntamente com a @Inject. Aqui também podemos utilizar diversos estereótipos para “selecionar” o objeto a ser decorado. Como os demais exemplos dessa nossa aplicação, esse decorator é extremamente complexo ao printar no console que ele foi executado :D .

Agora basta adicionarmos ele no beans.xml:

1
2
3
4
5
6
7
8
9
10
11
12
<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">
 
	<interceptors>
		<class>br.com.jugms.weldse.intercept.ContaInterceptor</class>
	</interceptors>
 
	<decorators>
		<class>br.com.jugms.weldse.intercept.CaixaDecorator</class>
	</decorators>
 
</beans>


E agora a saída no console é a seguinte:

hello
CaixaDecorator.sacar()
ContaInterceptor.protege(antes) >> recebeMovimento
ContaInterceptor.protege(depois) >> recebeMovimento
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
1800.0
CaixaDecorator.depositar()
ContaInterceptor.protege(antes) >> recebeMovimento
ContaInterceptor.protege(depois) >> recebeMovimento
ContaInterceptor.protege(antes) >> getSaldo
ContaInterceptor.protege(depois) >> getSaldo
2100.0


Apesar da saída no console mostrar nosso decorator antes do nosso interceptor, isso é porque estamos decorando e interceptando coisas diferentes, pois decorators são chamados depois dos interceptors.

Em seguida posto como funcionam os alternatives e o que faltou colocar nesses dois primeiros posts.

Desenvolvendo uma aplicação Desktop com Weld – Parte 1

March 17th, 2010 13 comments

Como havia comentado, em Novembro do ano passado eu apresentei uma palestra no Javaneiros, evento anual sobre Java organizado pelo JUGMS. Os slides eu já disponibilizei no post anterior, e agora vou de fato colocar aqui no blog o que mostrei na palestra, pois slides sem explicação não serve para muita coisa né?

Como acho que um post só vai ficar muito grande, vou publicar o conteúdo em partes.


Intradução


Primeiramente eu gostaria de explicar, para quem não está familiarizado, o que é a CDI. Hoje em dia está mais difundido que na época da palestra, mas até para manter a coerência com os slides vou comentar rapidamente alguma coisa. Se seu objetivo é ver código, pode pular esse tópico.

A CDI, ou “Context and Dependency Injection for the Java EE platform” é uma especificação que define uma forma padrão de trabalharmos com DI em aplicações Java. Pelo nome já vemos que ela é voltada para Java EE, mas está seguindo os mesmos passos da JPA, que foi introduzida no Java EE 5 mas é usada sem problemas em aplicações SE.

Talvez a coisa que valha mais a pena comentar antes de entrar na prática é o monte de nomes envolvidos nessa JSR. O primeiro “nome” é a própria identificação da JSR: “JSR-299″. Acho que até quem nunca foi ligado em número de JSR já ouviu falar dessa tal de 299. Para resumir a história, ela já se chamou WebBeans antes de se chamar CDI, e até hoje muita coisa na internet, principalmente as discussões iniciais você vai encontrar esse nome. Além disso tem a implementação de referência dela, que também já chamou WebBeans e agora é Weld. Ou seja, de WebBeans não sobrou nada.

Outra coisa que veio dar uma cofundida nesses nomes foi a JSR-330, “Dependency Injection for Java“, que nada mais é do que a extração das anotações da CDI para uma especificação menor, tornando assim mais fácil que frameworks como Spring e Guice utilizem anotações padrão mesmo não sendo uma implementação da CDI. Isso gerou muita polêmica também, pois em tese a CDI já deveria ser mínima e não faz sentido alguém usar as anotações dela sem ter o mesmo comportamento. Mas isso já é outra história.


Ainda antes de começar…


A CDI sofreu muita influência do Seam e Guice, além é claro de não ser difícil de compreender para quem trabalha com Spring, pois no fim das contas os conceitos são os mesmos.

Uma premissa muito forte da CDI é a injeção de dependência “type safe“, o que já a diferencia bastante do Seam que trabalha muito com Strings. Nesse ponto já fica mais perto para quem trabalha com Spring do que quem tá acostumado com Seam.

Outra coisa que temos que ter em mente é que diferentemente do Spring ou Seam onde uma classe simples não é considerada uma candidata à injeção de dependência a menos que seja marcada (via xml ou anotação), na CDI se a classe está dentro de um bean package então ela automaticamente é elegível. Mas isso nós vamos ver na aplicação de exemplo.

Outra coisa que temos que ter em mente é que o objetivo da CDI não é substituir o Seam. O Seam tem um mundo de coisas como facilitadores para e-mail, pdf, bpm, segurança, jsf, etc. A CDI define apenas o core o que será o core do Seam 3, ou seja, a parte da DI, interceptors e mais algumas coisas. Então não vamos comparar coisas tão diferentes com comentários tipo “O Seam é muito melhor que o Weld. O Weld não faz nada, o Seam faz um monte de coisas”.

A primeira coisa que precisamos saber para trabalhar com a CDI é o que é um bean package. Na prática um bean package vai ser um jar (ou pode estar explodido mesmo) onde temos um arquivo META-INF/beans.xml. Se a CDI encontrar esse cara, ela escaneia tudo e considera todas classes dentro desse “módulo” como beans injetáveis. É análogo ao seam.properties, mas no caso do Seam ainda precisa ter a anotação ou estar no components.xml para a classe ser considerada.

Outra coisa que vamos ver no exemplo é que o mesmo se trata de uma aplicação SE de console. Aí nos perguntamos: mas no nome da especificação não fala que é para Java EE? Pois é, mas a especificação define também a criação de extensões portáveis. Isso quer dizer que você pode fazer uma extensão da CDI e rodar em qualquer implementação dela. Pois bem, o Weld tem uma extensão que permite que rodemos tudo isso num ambiente SE, porém com limitações, claro.


Agora vamos à pratica


O nosso exemplo é bem simples, e consiste em realizarmos um saque e um depósito em uma conta bancária via um caixa eletrônico. Para simplificar o exemplo, temos apenas uma conta e um caixa eletrônico.

Nossa aplicação inicia com a classe MovimentacaoControl.

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
package br.com.jugms.weldse.control;
 
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
 
import org.jboss.weld.environment.se.events.ContainerInitialized;
 
import br.com.jugms.weldse.model.CaixaEletronico;
import br.com.jugms.weldse.model.ContaBancaria;
 
/**
* @author http://gilliard.eti.br
*/
@ApplicationScoped
public class MovimentacaoControl{
 
    @Inject private ContaBancaria contaBancaria;
    @Inject private CaixaEletronico caixaEletronico;
 
    public void executar(@Observes ContainerInitialized init) {
 
        System.out.println("hello");
 
        caixaEletronico.sacar(200.0f);
 
        System.out.println(contaBancaria.getSaldo());
 
        caixaEletronico.depositar(300.0f);
 
        System.out.println(contaBancaria.getSaldo());
 
    }
}

Como podemos ver essa classe possui a anotação @ApplicationScoped, mas essa anotação não serve para habilitar o gerenciamento dos objetos dessa classe, pois como eu disse anteriormente, isso é automático já que estamos em um bean package.

Essa classe também não possui um método main. Para executar o exemplo executamos a classe org.jboss.weld.environment.se.StartMain, e essa sim possui um método main, que inicializa todo o framework e quando termina de inicializar o container ele avisa lançando um evento do tipo org.jboss.weld.environment.se.events.ContainerInitialized. Para iniciarmos nossa aplicação, basta escutarmos esse evento como é feito no método “executar“. Deu para perceber que escutar um evento é algo muito complicado :) . Nesse caso não faremos nada com o objeto init que é o que representa o evento, mas no decorrer do exemplo veremos como isso funciona.

No nosso exemplo, nós realizamos um saque de 200, depois olhamos o saldo, depositamos 300 e olhamos o saldo de novo. Parece bobo (e não vou negar isso), mas é útil para testarmos os diferentes escopos. Pois quando mudamos os scopos para stateless (default, sem a anotação @ApplicationScoped) percebemos que a conta sempre volta a ter o valor inicial.

Nesse exemplo estou trabalhando com classes, mas para trabalhar com interfaces o procedimento é o mesmo, ao ver que você pediu para injetar um objeto tipado por uma determinada interface a CDI vai procurar por uma implementação da mesma, e encontrando injeta. Agora se ela encontrar nenhuma ou mais de uma, aí será lançada uma excessão. “Poxa, mas e se eu tiver mais de uma implementação no bean package”? Palma, palma, palma, não priemos cânico, vamos chegar a ver isso.


Manipulação de eventos


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package br.com.jugms.weldse.model;
 
import javax.enterprise.event.Event;
import javax.inject.Inject;
 
/**
* @author http://gilliard.eti.br
*/
public class CaixaEletronico {
 
    @Inject private Event<Movimentacao> eventMovimentacao;
 
    public void depositar(float valor)
    {
        eventMovimentacao.fire(new Movimentacao(valor));
    }
    public void sacar(float valor)
    {
        eventMovimentacao.fire(new Movimentacao(-1 * valor));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package br.com.jugms.weldse.model;
 
/**
* @author http://gilliard.eti.br
*/
public class Movimentacao {
 
    private float valor;
 
    public Movimentacao(float valor) {
        this.valor = valor;
    }
 
    public float getValor() {
        return valor;
    }
}

Como podemos ver, a classe CaixaEletronico não tem nenhuma anotação para “ativá-la” como injetável, e ainda assim ela é injetada no nosso objeto da classe MovimentacaoControl. Podemos ver também que nossa classe CaixaEletronico não debita diretamente da nossa conta (que nesse exemplo simplista só existe uma). O CaixaEletronico envia uma mensagem que é representada pela classe Movimentacao. Para disparar esse evento nosso CaixaEletronico pede para que seja injetado nele um ‘cara’ que sabe disparar eventos do tipo Movimentacao. E então no depósito ele dispara uma movimentação com valor positivo e no saque uma com valor negativo. Bem simples.

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
package br.com.jugms.weldse.model;
 
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Named;
 
import br.com.jugms.weldse.intercept.Seguro;
 
/**
* @author http://gilliard.eti.br
*/
@ApplicationScoped
@Seguro
public class ContaBancaria {
 
    @Inject @Named
    private float saldoInicial = 1000.0f;
 
    public void recebeMovimento(@Observes Movimentacao movimentacao)
    {
        saldoInicial += movimentacao.getValor();
    }
 
    public float getSaldo() {
        return saldoInicial;
    }
 
}

Agora na classe ContaBancaria vemos como consumir um evento. Na verdade já tinhamos visto na classe MovimentacaoControl, mas agora vamos de fato utilizar o objeto do evento. Como na MovimentacaoControl, para escutarmos um evento basta termos um método com um parâmetro do tipo do objeto do evento anotado com @Observes. Além disso podemos ver o escopo desse objeto, que é de aplicação. Comente esse escopo e você vai perceber que serão criadas várias contas bancárias, e dessa forma vamos debitar em uma e creditar na outra.

Podemos ver também a injeção de um ‘cara’ do tipo float, mas além de @Inject usamos um @Named para isso. O @Named é um qualificador. Nós também podemos, em vários casos vamos “precisar”, criar nosso próprios qualificadores. Um qualificador serve para especificar melhor qual candidato à injeção queremos que seja escolhido. Seria como uma cláusula “where” na pesquisa por injetáveis. No caso desse float, obviamente algém vai ter que colocá-lo no contexto para que possamos recuperá-lo, e podemos ver isso na classe Produtores.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package br.com.jugms.weldse.model;
 
import javax.enterprise.inject.Produces;
import javax.inject.Named;
 
/**
* @author http://gilliard.eti.br
*/
public class Produtores {
 
    @Produces @Named
    public float getSaldoInicial()
    {
        return 2000.0f;
    }
}

Essa classe agrega todos os métodos produtores da nossa aplicação (que por ser extremamente complexa tem exatamente um :) ). Um método produtor (anotado com @Produces) é o oposto do consumidor (@Inject), logo em vez de pegar, ele joga um obejto no contexto, usando como qualificador o @Named que permite darmos um nome ao componente. Só temos que tomar cuidado para não usarmos demais isso e acabarmos tendo tudo ligado via Strings. Nesse exemplo, o nome usado para registrar esse componente é “saldoInicial”, pois segue o padrão java bean.

Podemos ver também que que na classe ContaBancaria deixei um saldo inicial de 1000, e depois mandei injetar nessa propriedade o valor de um componente do tipo float chamado “saldoInicial” que está com valor 2000. Na prática ficará valendo o 2000, pois o 1000 só vai valer antes que as injeções sejam executadas.

Nos próximos posts eu faço uma sessão específica para comentar as possibilidade de injeção e “ejeção” que a CDI provê. E também vou explicar o funcionamento dos interceptadores como podemos ver através da anotação @Seguro da classe ContaBancaria, e também como especificarmos qual implementação de uma interface vamos querer que seja selecionada. Como dá para perceber esse assunto vai longe. Então até o próximo post.

Apresentacao sobre CDI (JSR-299) no Javaneiros2009

February 25th, 2010 1 comment

Estou a um bom tempo sem postar, mas nesse tempo fiz bastante coisa que acabei não postando aqui. Uma delas foi uma palestra no Javaneiros2009, falando sobre a JSR-299.

Ainda vou postar aqui o exemplo, mas como pretendo explicar cada parte, e isso vai levar mais tempo, já vou postando os slides até para tirar a poeira do blog.

Update:
Desenvolvendo uma aplicação Desktop com Weld – Parte 1
Desenvolvendo uma aplicação Desktop com Weld – Parte 2
Desenvolvendo uma aplicação Desktop com Weld – Final