Novidades do EJB 3.1 do futuro Java EE 6

Por Nico Steppat em 24/03/08

A especificação EJB 3.0 já está no mercado há quase 2 anos e simplificou bastante o desenvolvimento. O uso de anotações (XML opcional) e POJOs/POJIs são as características principais. EJB 3.0 faz parte da Java EE 5.

Ainda esse ano deve sair o Java EE 6 e, com ele, também uma atualização da especificação do EJB. Vamos ver quais são as novidades/melhorias propostas atualmente no rascunho do EJB 3.1:


Facilidades no desenvolvimento

1) Interfaces locais são opcionais.

Um session bean local pode ficar simples assim:


@Stateless
public class PedidoDAO {

  public void cadastra(Pedido pedido) {
    //código para cadastrar um pedido
  }
}

Não precisa mais da interface e da anotação @Local.

2) EJB’s dentro do war

Será possivel colocar um EJB3 num war, facilitando o packaging. Não é preciso criar um jar e ear separado, tudo pode ser dentro de um unico war. As classes ficam na pasta WEB-INF/classes, e se for usado um ejb-jar.xml, se encontra na pasta WEB-INF.


Novidades

1) Singleton Beans

A ideia é que você pode criar session beans que só existem uma única vez na sua aplicação. Assim é possível criar objetos como o ServletContext na aplicação web. Por exemplo:


@Singleton @ReadOnly
public class ApplicationContextBean implements ApplicationContext {

  @PostConstruct
  public void init() {
    //initializa o contexto da aplicação
  }

  //métodos, por exemplo getAttribute(String chave)
}

Repare a anotação @ReadOnly, declarando o EJB imutável. Também vai existir uma anotação @ReadWrite para singletons beans que podem ser alterados.

O método init() será executado quando o container inicializa a aplicação. Singleton components também serão EJBs e podem ser injetados, o que é uma grande vantagem em relação a ter de ficar preso ao método estático de lookup de um singleton, e uma boa prática de inversão de controle.

2) EJB Timer

Terá uma nova anotação @Schedule referente ao EJB timer para facilitar o agendamento. Por exemplo:



@Schedule(hour=”13”, dayOfMonth=”1”)
public void geraRelatorio() {/* …. */}

executa cada primeiro dia no mes as 13 horas. É um modelo bem superior aos atuais timers do EJB, porém ainda não tão completo quanto aos frameworks open source existentes, como o Quartz.

3) Chamadas assíncronas

Parecidos com Web Services, métodos num session beans também podem ser chamados assincronamente. Para isto serve a anotação @Asynchronous:


@Stateless @Remote(PedidoFacade.class)
public class PedidoFacadeBean implements PedidoFacade{

  @Asynchronous
  public void cadastra(Pedido pedido) {
    //código para cadastrar um pedido
  }

  @Asynchronous
  public Future autoriza(Pedido pedido) {
    //autoriza demora …..
  }
}

O segundo método devolve um object do tipo java.util.concurrent.Future que fornece métodos para verificar se o resultado já chegou.

O lançamento da versão 3.1, que teoricamente ocorrerá até o fim deste ano, deve acelerar ainda mais a adoção da plataforma Java EE 5/6 em relação ao uso das versões antigas J2EE.

Testes unitários com JMock 2

Por Lucas Cavalcanti em 17/03/08

Podemos definir teste unitário de uma classe como um teste em que verificamos uma funcionalidade da classe em questão passando o mínimo possível por outras classes do sistema, ou que sejam dependências do sistema.

Por mais desacoplada que seja nossa classe, se ela tiver um mínimo de complexidade, ela vai precisar de funcionalidades de outras classe, ou seja, ela vai ter dependências. E essas dependências sempre nos atrapalham na hora de fazermos os testes unitários da classe.

Por exemplo, se uma das dependências da nossa classe é a interface HttpServletRequest, o que vamos passar pra ela na hora do teste? null, e levar uma NullPointerException? Desenterrar a biblioteca e passar uma implementação de verdade? Claro que não.

Em testes unitários não estamos interessados no comportamento real das dependências da classe, mas em como a classe em questão se comporta diante das possíveis respostas das dependências, ou então se a classe modificou as dependências da maneira esperada.

Então é comum passarmos implementações falsas (mock objects) das dependências da classe, retornando valores pertinentes para conseguirmos testá-la satisfatoriamente. Esses mocks costumam poluir seu código de testes com várias classes que só são usadas em poucos testes. E o problema fica pior quando a interface da dependência possui muitos métodos mas só usamos um ou dois deles (é o caso do HttpServletRequest). É nessa hora que o JMock vem para facilitar a nossa vida.

O JMock é uma biblioteca que auxilia o Test Driven Development através dos mock objects. É uma biblioteca que vai criar implementações de mentira específicas para o seu teste, de uma maneira rápida e simples, sem ter que se preocupar com os métodos que não vamos usar no teste, sem ao menos ficar criando classes “a toa”. Com o JMock podemos definir o comportamento necessário do objeto de mentira, para criarmos a situação pedida pelo teste.

Para termos uma idéia melhor vamos ver um exemplo prático de como usar o JMock. Vamos supor que temos uma lógica de login no nosso sistema e queremos testá-la. As dependências dessa lógica são recebidas no construtor:

public class LoginLogic {
    private final HttpSession session;
    private final Authenticator auth;
    public LoginLogic (HttpSession session, Authenticator auth) {
        this
.session = session;
        this.auth = auth;
    }
    public void login(User user) {
        //…
    }
}

Vamos testar o método login, que tem duas situações possíveis: se o usuário é válido, entra na sessão, senão não entra. Para testar precisamos de um teste que vai passar um usuário válido, e garantir que o usuário entrou na sessão; e um teste que vai passar um usuário inválido e garantir que o usuário não entrou na sessão.

Para criar esses testes precisamos de uma instância da classe LoginLogic, logo precisamos nos preocupar com as dependências da classe: o HttpSession, que é uma interface do java servlet, e o Authenticator, que é uma interface do nosso projeto contendo um método chamado isValid(User) que recebe um usuário e vê se ele é válido.

Começando nosso teste:

LoginLogic logic = new LoginLogic(/*um httpSession*/, /*um authenticator*/);
logic.login(/*um user válido*/);
assertTrue(/*o usuário está na sessão*/);

Precisamos passar para nossa lógica um objeto que implementa HttpSession, e um que implementa Authenticator. Poderíamos criar implementações falsas dessas interfaces, mas não queremos poluir nosso código de testes com classes “inúteis”. Vamos, então, deixar o JMock fazer esse trabalho sujo para nós.

Para começar a criar essas implementações falsas, precisamos de uma fábrica de objetos falsos (mocks) do JMock:

Mockery mockery = new Mockery();

É comum criarmos essa fábrica no começo de cada teste, ou no setUp da sua classe de testes (se você usa o JUnit). Com a fábrica em mãos, podemos começar a mockar as nossas interfaces. É bem simples:

HttpSession session = mockery.mock(HttpSession.class);
Authenticator auth = mockery.mock(Authenticator.class);

E já podemos passar esses mocks para nosso LoginLogic. Nosso teste ficaria então:

final Mockery mockery = new Mockery();
final HttpSession session = mockery.mock(HttpSession.class);
final Authenticator auth = mockery.mock(Authenticator.class);

LoginLogic logic = new LoginLogic(session, auth);
logic.login(/*um user válido*/);
assertTrue(/*o usuário está na sessão*/);

Se fizermos simplesmente isso, o teste não vai fazer nada. Precisamos dizer para nossos mocks como vai ser o comportamento deles quando forem acessados. A maneira de fazer isso no JMock 2.4 é bem interessante, utiliza uma sintaxe um pouco incomum, mas quando você se acostuma com ela fica bastante legível:

mockery.checking(new Expectations() {{
    //comportamento dos mocks aqui
}});

Repare no truque: uma classe anônima, com um pré construtor (note os dois grupos de chaves). Esse bloco vai ser chamado pelo método checking, e vai adicionar o comportamento pedido aos mocks. Fazemos isso de uma maneira fluente bem interessante. Por exemplo, se quisermos garantir que o usuário foi colocado na sessão após o teste, fazemos:

one(session).setAttribute(“user”, with(any(User.class)));

O que essa linha quer dizer é o seguinte: eu quero que o método setAttribute seja chamado uma vez, com os parâmetros “user” e com qualquer objeto do tipo User.

Se esse método nunca for chamado com esses parâmetros ou for chamado mais de uma vez, o teste vai falhar. Na verdade, tudo que é possível acontecer com os mocks tem que estar descrito em um expectations (pode ter mais de um no teste). Se pro teste não é importante o que acontece com um dos objetos mockados, podemos ignorá-los, escrevendo:

ignoring(mockObject);

Fazendo isso, todo método chamado desse método vai retornar valores padrão (0, “”, null ou, se for possível um outro mockObject marcado como ignoring). Mas para que tudo isso aconteça, precisamos colocar no final do nosso teste a seguinte linha:

mockery.assertIsSatisfied();

Bom, ainda não terminamos o nosso teste, precisamos fazer com que o usuário seja válido, ou seja, precisamos garantir que o método isValid() do authenticator retorne true. Fazemos isso da seguinte maneira, dentro do expectations:

one(auth).isValid(with(any(User.class)));
will(returnValue(true));

Fica bastante legível: o método isValid do mock auth será chamado uma vez, com qualquer User como parâmetro, e vai retornar o valor true.

O nosso teste completo ficaria, então:

final Mockery mockery = new Mockery();
final HttpSession session = mockery.mock(HttpSession.class);
final Authenticator auth = mockery.mock(Authenticator.class)

mockery.checking(new Expectations() {{
    one(session).setAttribute(“user”, with(any(User.class)));
    one(auth).isValid(with(any(User.class)));
    will(returnValue(true));
}});

LoginLogic logic = new LoginLogic(session, auth);
logic.login(new User());

mockery.assertIsSatisfied();

Note que poderíamos garantir que o user passado para os métodos foi o mesmo que passamos para a lógica, apenas colocando ele como parâmetro para o método. E para fazer o teste do usuário inválido só precisamos mudar o conteúdo do expectations, substituindo por:

never(session).setAttribute(“user”, with(any(User.class)));
one(auth).isValid(with(any(User.class)));
will(returnValue(false));

Ou seja, o isValid vai retornar false, e o método setAttibute nunca vai ser chamado. Se isso acontecer, o teste passa.

O roteiro do expectations não precisa estar na ordem em que ele vai acontecer no seu método (por exemplo o isValid provavelmente vai ser chamado antes do setAttribute), mas tem um jeito de você garantir a ordem dos comandos.

Por padrão o JMock só é capaz de mockar interfaces, mas você pode configurá-lo para mockar classes.

Você pode, ainda, usar o JMock para fazer testes de integração. Como o roteiro do teste pode ficar bastante complexo, você pode utilizar uma máquina de estados para adicionar um pouco mais de poder ao roteiro (por exemplo garantir que uma chamada de método sempre ocorra depois de uma outra).

Uma chamada genérica num expectations, então, seria:

invocation-count (mock-object).method(argument-constraints);
inSequence(sequence-name);
when(state-machine.is(state-name));
will(action);
then(state-machine.is(new-state-name));

Se você quiser usar todo o poder do JMock, dê uma olhada na sua documentação. E, claro, não abuse de mocks colocando-os em todas as situações, senão seu teste unitário pode perder o valor de testar uma pequena unidade.

Apostila de Java e Orientação a Objetos revisada e ampliada

Por Sérgio Lopes em 12/03/08

FJ-11
Em nossa constante política de manter nossas apostilas atualizadas, estamos disponibilizando hoje a última versão do FJ-11: Java e Orientação a Objetos. Foram várias correções de bugs, atualizações e melhorias no texto (algumas seções foram inclusives reescritas).

Essa apostila já vinha sendo usada aqui na Caelum nos nossos treinamentos há alguns meses. Nesse período, aproveitamos para corrigir bugs e finalizar o material. Entre as novidades, estão algumas discusões sobre design patterns ao longo do curso, atualização para Java 6, novos assuntos (como fluent interfaces) e mais texto. Os capítulos de Threads e Sockets foram reescritos e ampliados. Há também um novo capítulo sobre JARs e bibliotecas, que mostra a famosa ferramenta JFreeChart para desenvolvimento de gráficos em Java.

Muitos exercícios foram reelaborados e estendidos, além de alguns novos que foram incluídos. Há também muitos links para outros materiais, como artigos do nosso blog e outras referências ao longo do texto.

Além disso, a partir dessa versão, estamos usando o Latex (do Donald Knuth) para escrever a apostila e conseguir um resultado final graficamente mais profissional. Aliás já usamos também na apostila de Estruturas de Dados e Algoritmos em Java e logo também nas outras apostilas. (criamos um projeto para ajudar na escrita do latex e gerenciamento das apostilas; mais detalhes em breve)

Acesse a nova versão da apostila na página do treinamento FJ-11. Ou entre em contato conosco para mais informações sobre o treinamento.

Screencast - Hibernate e Concorrência Otimista na Web com VRaptor

Por Fabio Kung em 04/03/08

É com prazer, depois de tanto tempo, que anuncio o segundo screencast da Caelum.

Assim como o screencast anterior (Primeiros Passos para a JPA), o segundo screencast da Caelum vem em dois sabores. Flash vídeo (.flv), que é a mesma tecnologia usada pelo YouTube e pelo Google Video e pode ser assistido pelo navegador. O outro formato disponível é o famoso AVI (DivX), suportado pela grande maioria dos players.

O vídeo trata de um dos recursos pouco explorados no Hibernate: Controle de Concorrência Otimista, para lidar com problemas de edição simultânea (concorrência) nos registros. O fato curioso é que tenho observado em diversos projetos a preferência por Locks Pessimistas, que em grande parte dos casos não são a melhor escolha. Da própria documentação do Hibernate:

The only approach that is consistent with high concurrency and high scalability is optimistic concurrency control with versioning.

(…)

It is not intended that users spend much time worring about locking strategies. Its usually enough to specify an isolation level for the JDBC connections and then simply let the database do all the work.

Como podemos nos beneficiar do controle de concorrência otimista (também conhecido como lock otimista)? Para explorar o assunto, durante o screencast vamos enriquecendo uma aplicação Web existente, adicionando funcionalidades de edição simples de registros e resolvendo o problema de edição simultânea.

A aplicação Web utilizada usa e abusa do VRaptor como controlador MVC e várias dicas sobre o framework são abordadas durante o vídeo. Porém, a mensagem vale para qualquer aplicação Web. Mesmo as que não usam VRaptor.

Como sempre, o screencast mostra apenas uma das alternativas para solução do problema. Fica como lição de casa, testar outras possibildades:

1) Para não fazer o controle transacional dentro do Dao e forçar a checagem de versão (version check), no lugar do transaction.commit() poderia ter sido usado o session.lock(objeto, LockMode.READ). O método lock serve principalmente para a abordagem pessimista, porém LockMode.READ serve justamente para forçar a checagem de versão no caso otimista.

2) No lugar de tirar a entidade do cache de primeiro nível com session.evict(entidade) e consultá-la novamente para ter a versão mais nova do banco, bastaria usar o método session.refresh(entidade) que atualiza a instancia, passando direto pelos caches.

Não deixe de colocar o seu comentário com outras alternativas!

Hibernate e Concorrência Otimista na Web com VRaptor - duração: 48 min

Assista pelo Navegador: Flash Video (.flv): 52 MB, 800×600
Faça o download: AVI, codificação DivX (.avi): 70,1 MB, 800×600
Código Fonte: Código Fonte produzido durante o Screencast. Você vai precisar baixar as dependências (jars) do projeto separadamente. Por favor, leia o arquivo README.txt.