Session Bean

Beans de sessão é uma tecnologia de componente projetada para encapsular serviços de negócio. As operações suportadas pelo serviço são geralmente definidos usando uma interface Java, chamada de interface de serviço do Bean de sessão, na qual os clientes usam para interagir com o Bean. Além disso, por fazer parte de um modelo de componente EJB, o Bean tem acesso a um grande número de serviços do container.

Existem três tipos de Bean de sessão: Stateless (sem estado de sessão), Stateful (com estado de sessão) e Singleton (uma instância do Bean compartilhada).

A interação com um Bean sem estado de sessão (stateless session bean) começa com o início de uma chamada a método de negócio e termina quando a chamada do método completa. Não existe um estado que seja levado de uma operação de negócio para outro.

Uma interação com Beans que mantém o estado de sessão (Stateful session bean) torna-se mais como uma conversação em que inicia no momento em que o cliente adquire uma referência para o Bean de sessão e finaliza quando o cliente explicitamente libera de volta o Bean para o servidor. Operações de negócio em Beans com estado de sessão pode manter o estado na instância do Bean através das chamadas.

Outro tipo de Bean é o Singleton. Beans de sessão Singleton foram introduzidos no EJB 3.1, podem ser considerados como um hibrido entre Bean sem estado de sessão e Bean com estado de sessão. Todos clientes compartilham a mesma instância do Bean Singleton, assim torna-se possível compartilhar o estado através de invocações de métodos, porém questões como concorrência também devem ser levados em consideração em Beans do tipo Singleton.

Os clientes nunca interagem diretamente com uma instância de um Bean de sessão. O cliente referencia e invoca uma implementação da interface de negócio provida por um servidor. Esta classe de implementação age como um proxy para a implementação de um Bean que está “abaixo dele”. Este desacoplamento do cliente de um Bean permite o servidor interceptar chamadas de método para prover os serviços requeridos pelo Bean, como gerenciamento de transação. Isto também permite ao servidor otimizar e reusar instancias das classes dos Beans de sessão conforme necessário.

No restante do artigo trataremos dos beans sem estado de sessão, muito utilizados na maioria das aplicações corporativas.

Beans Sem Sessão de Estado

Um bean sem estado de sessão completa uma operação dentro de um ciclo de vida de um único método. Beans sem estado de sessão podem implementar muitas operações de negócio, mas cada método não pode assumir que qualquer outro foi invocado antes dele.

Mesmo que aparentemente isto seja uma limitação, esta é a forma mais comum de implementação de serviços de negócio. Diferente dos beans com estado de sessão que são bons em acumular estado durante a conversação, os beans sem estado de sessão são projetados para ter uma certa independência nas operações de forma bastante eficiente. Beans sem estado de sessão podem ter um grande número de clientes com um mínimo de impacto sobre os recursos do servidor, o que é uma grande vantagem em relação aos outros beans.

Definindo um Bean Sem Estado de Sessão

Um Bean sem estado de sessão é definido em duas partes:

  • Através de zero ou mais interfaces de negócio que define quais métodos um cliente pode invocar no bean. Quando nenhuma interface é definida então o conjunto de métodos públicos na classe de implementação do bean forma uma interface lógica para o cliente.
  • Uma classe que implementa essas interfaces criadas acima, chamada de classe do bean, na qual é marcada com a anotação @Stateless.

A maioria dos beans de sessão possuem uma interface de negócio, mas não existe restrição no número de interfaces que um bean de sessão pode expor aos seus clientes. Quando o servidor encontra a anotação @Stateless, o servidor se encarrega de tratar essa classe do bean como um bean sem estado de sessão. O servidor irá configura-lo no container EJB e faze-lo disponível para uso pelos outros componentes na aplicação. A anotação @Stateless e outras anotações são definidas no pacote javax.ejb ou javax.annotation.

No exemplo abaixo temos uma interface de negócio que será posteriormente implementada por um bean de sessão. Neste exemplo, o serviço consiste de um único método, sayHello(), na qual aceita-se uma String como argumento que corresponde ao nome da pessoa e retorna-se como resposta também uma String com uma frase de boas vindas. Não existe anotação ou interface pai para indicar que esta é uma interface de negócio. Quando implementado pelo bean de sessão, ele será automaticamente tratado como uma interface de negócio local, significando que ele é acessível apenas por clientes dentro de um mesmo servidor de aplicação. Um segundo tipo de interface de negócio para clientes remotos será discutido nas próximas sessões. Para enfatizar que uma interface de negócio é local usa-se a anotação @Local que pode ser opcionalmente adicionada à interface.

Listagem 1: Interface de Negócio para um Bean de Sessão

public interface HelloService {

	public String sayHello(String name);

}

Na Listagem 2 mostramos a implementação. Esta classe Java implementa a interface de negócio definida acima HelloService. A anotação @Stateless marca esta classe como um bean de sessão sem estado. O método de negócio é implementado sem nenhum tipo especial de requisito ou restrição.

Listagem 2: Classe Bean implementando a interface HelloService


@Stateless

public class HelloServiceBean implements HelloService {
	public String sayHello(String name) {

		return "Hello, " + name;

	}
}

EJB 3.1 também define a visão sem interface que torna muito mais simples definir um bean de sessão local e para os clientes acessarem beans de sessão local. Para exemplificar tem-se abaixo o mesmo serviço HelloServiceBean com uma visão sem interface, o desenvolvedor do bean cria apenas uma implementação da classe sem implementar qualquer interface de negócio:

Listagem 3: Implementação de HelloService sem interface

@Stateless

public class HelloServiceBean {

	public String sayHello(String name) {

		return “Hello, “ + name;

	}

}

A interface lógica do bean de sessão consiste de métodos públicos, neste exemplo o método sayHello(). Os clientes usam a classe HelloServiceBean como se ela fosse uma interface, e devem desconsiderar qualquer método não público ou detalhes da implementação. Debaixo dos panos, os cliente irão interagir com um proxy que estendem a classe do bean e sobrescrevem o método de negócio para prover os serviços padrão do container.

Vale salientar que a visão sem interface são disponíveis apenas para beans de sessão local.

Beans sem estado de sessão precisam ter um construtor sem argumento, no entanto o compilador normalmente gera um automaticamente quando nenhum outro construtor é definido. Outra obrigação é que campos estáticos não devem ser utilizados. Muitos containers EJB criam um pool de instâncias de bean sem estado de sessão e então selecionam uma instância arbitrária para servir cada requisição de cliente. Portanto, não existe garantia que o mesmo estado será usado entre chamadas, portanto isto não é confiável.

Ciclo de Vida

Diferente de uma classe Java normal de uma aplicação, os servidores gerenciam o ciclo de vida de bean de sessão sem estado. Primeiramente, o servidor decide quando criar e quando remover instâncias do bean. A aplicação não tem controle sobre quando ou mesmo como instâncias de um bean sem sessão de estado particular são criados ou por quanto tempo eles estarão ativos. Além disso, o servidor tem que inicializar os serviços para o bean depois que ele for construído, porém antes da lógica de negócio do bean ser invocada. Igualmente, o bean pode ter de adquirir um recurso como um data source JDBC antes que o método de negócio possa ser usado. Entretanto, para o bean adquirir o recurso, o servidor deve primeiro ter de completar a inicialização destes serviços para o bean. Isto limita a utilidade do construtor para a classe porque o bean não terá acesso a qualquer recurso até que a inicialização do servidor tenha sido completada.

Para permitir que ambos, o servidor e o bean, tenham seus requisitos de inicialização, EJBs suportam métodos do ciclo de vida que são invocados pelo servidor em vários pontos do ciclo de vida de um bean. Para beans sem estado de sessão, existem duas chamadas de métodos do ciclo de vida: PostConstruct e PreDestroy. O servidor invocará PostConstruct tão logo ele tenha completado a inicialização de todos os serviços do container para o bean. Isto sobrescreve o construtor como inicializador da lógica porque é aqui que os serviços do container são garantidos estarem disponíveis. O servidor invoca PreDestroy imediatamente antes do servidor liberar a instancia do bean para ser coletado pelo coletor de lixo (garbage collector). Qualquer recurso adquirido durante o PostConstruct que requeira explicitamente ser fechado deveria ser liberado durante o PreDestroy.

O código abaixo mostra um bean sem estado de sessão que adquire uma referência para uma instância de java.util.logging.Logger durante a chamada a PostConstruct. Um bean pode ter no máximo um método PostConstruct que é identificado pela anotação @PostConstruct. PreDestroy é identificado pela anotação @PreDestroy.

Listagem 4: Usando PostConstruct para adquirir um Logger

@Stateless

public class LoggerBean implements Logger {

	private Logger logger;


	@PostConstruct

	public void init() {

		logger = Logger.getLogger("notificacao");

	}


	public void logMessage(String message) {

		logger.info(message);

	}

}

Interface de Negócio Remota

Até o momento discutimos apenas beans de sessão que usam interfaces de negócio local. Local neste caso significa que uma dependência no bean de sessão pode ser declarado apenas pelo componente Java EE que esta executando na mesma instância do servidor de aplicação. Não é possível usar um bean de sessão com uma interface local através de um cliente remoto, por exemplo.

Para acomodar clientes remotos, beans de sessão podem marcar suas interfaces de negócio com a anotação @Remote para declarar que isto deveria ser remotamente usável. O código abaixo demonstra um exemplo de uma interface remota para a interface HelloService. Declarar a interface como remota é o mesmo que estender a interface java.rmi.Remote.

Listagem 5: Uma Interface de Negócio Remota


@Remote

public interface HelloServiceRemote {

	public String sayHello(String name);

}

Fazer uma interface remota tem consequências principalmente em termos de performance. Interfaces de negócio remotas podem ser usadas localmente dentro de um servidor em execução, mas fazendo isso poderia ainda resultar em sobrecarga na rede se a chamada de método é roteada através de uma camada RMI. Outro problema são os argumentos dos métodos. Argumentos para métodos em interfaces remotas são passadas por valor ao invés de passadas por referência. Isto significa que o argumento é serializado mesmo quando o cliente é local para o bean de sessão. Interfaces locais para clientes locais são geralmente melhores. Interfaces locais preservam a semântica de chamadas a métodos e evita custos associados com rede e RMI.

Conclusão

Vimos neste artigo o que é são Beans sem estado de sessão, como podemos definir um bean sem estado de sessão e como se dá todo o seu ciclo de vida. EJB 3 e os beans de sessão são muito utilizados em aplicações corporativas Java e fornecem diversos benefícios para as aplicações conforme pode ser verificado no artigo. Além disso, vimos as vantagens da utilização de interfaces locais em relação as interfaces remotas.

Bibliografia

Leia também