Mostrando postagens com marcador EJB. Mostrar todas as postagens
Mostrando postagens com marcador EJB. Mostrar todas as postagens

[JavaEE 6] EJB 3.1 no GlassFish V3 e NetBeans

segunda-feira, 15 de setembro de 2008


Esta semana saiu nas bancas a edição 31 da revista Mundo Java com o título "Futuro do Java Corporativo", com um artigo meu sobre o mesmo tema.
Para quem quer saber o que vai rolar na próxima especificação do Java EE 6, está edição está um prato cheio, portanto compre uma edição e aproveite...
Não vou entrar em muitos detalhes da matéria, mas vou descrever aqui melhor a demo que está na revista, onde apresento uma aplicação utilizando Session Bean da especificação de EJB 3.1 no GlassFish V3.

Instalando o GlassFish V3 e o conteiner EJB

No site do GlassFish baixe o arquivo zip e descompacte em um diretório da sua escolha, a partir deste momento vamos chamar apenas de GLASSFISH_HOME\bin e execute o updatetool (Figura 1).
Na opção available addons, selecione glassfishv3-ejb e clique em Install, esta ação irá instalar o container EJB no Glassfish.

Instalando o plugin GlassFish V3 no NetBeans

Agora inicie o NetBeans (de preferência a versão 6.1 ou 6.5) e instale o plugin do GlassFish V3 para o NetBeans em Ferramentas | Plugins, selecione em plugins disponíveis "Glassfish JavaEE Integration" e clique em instalar.
Após instaldo o plugin, na aba Serviços, adicione um novo servidor, selecione a opção GlassFish V3 e siga os passos apontando o diretório GLASSFISH_HOME de instalação e finalizar.



Vamos explorar agora uma funcionalidade no NetBeans para a criação de CRUD, crie uma nova Aplicação Web na categoria Web e clique em Próximo.
Neste passo digite "DEMO_EJB31" e clique em Próximo, na opção servidores selecione o servidor GlassFish V3 T2 recém instalado e clique em Próximo. No último passo selecione o framework JavaServer Faces e clique em Finalizar.

Agora vamos criar uma aplicação CRUD completa baseada em uma entidade de banco de dados, para isso clique em Arquivo | Novo Arquivo, na categoria Persistence selecione a opção "Classes de entidade do banco de dados" e clique em Próximo.
OBS: Antes de fazer o passo abaixo, inicie o banco de dados Derby na guia Serviços do NetBeans, clique com o botão direito do mouse em Java DB e clique em "Iniciar Servidor".

Neste segundo passo, na lista Fonte de Dados selecione a opção "Nova Fonte de Dados", no campo "Nome JNDI" digite jndi/TesteEJB e na lista "Conexão de banco de dados" selecione o banco "jdbc:derby://localhost:1527/vir" já existente e clique em OK.

Se tudo ocorreu de maneira correta será apresentada uma lista de tabelas disponíveis. Selecione a tabela Employee, clique em Adicionar e em seguida clique em Próximo.

No campo nome do pacote digite br.com.netfeijao.entities e por fim clique no botão "Criar unidade de persistência". Mantenha os valores default clique em Criar e depois clique em Finalizar. Esta ação irá criar a classe persistente Employee no pacote informado.

Agora vamos utilizar um recurso no NetBeans para a criação de um CRUD com páginas JSF baseado em entidades JPA, no caso a classe Employee que acabamos de criar. Acesse o menu Arquivo | Novo Arquivo, na pasta categoria Persistence selecione "Páginas JSF de classes de entidade" e clique em próximo. Adicione a única classe persistente (Employee) existente (ver figura 1), clique em Próximo e a seguir clique em Finalizar.
Execute a aplicação pressionando o botão F6 e faça testes, perceba que o NetBeans criou uma aplicação completa "a lá Ruby on Rails" com apenas alguns cliques.

public class EmployeeController {
private Employee employee = null;
private List employees = null;
@Resource
private UserTransaction utx = null;
@PersistenceUnit(unitName = "DEMO_EJB31PU")
private EntityManagerFactory emf = null;

public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public int batchSize = 5;
private int firstItem = 0;
private int itemCount = -1;

public SelectItem[] getEmployeesAvailableSelectMany() {
return getEmployeesAvailable(false);
}

public SelectItem[] getEmployeesAvailableSelectOne() {
return getEmployeesAvailable(true);
}

private SelectItem[] getEmployeesAvailable(boolean one) {
List allEmployees = getEmployees(true);
int size = one ? allEmployees.size() + 1 : allEmployees.size();
SelectItem[] items = new SelectItem[size];
int i = 0;
if (one) {
items[0] = new SelectItem("", "---");
i++;
}
for (Employee x : allEmployees) {
items[i++] = new SelectItem(x, x.toString());
}
return items;
}

public Employee getEmployee() {
if (employee == null) {
employee = getEmployeeFromRequest();
}
if (employee == null) {
employee = new Employee();
}
return employee;
}

public String listSetup() {
reset(true);
return "employee_list";
}

public String createSetup() {
reset(false);
employee = new Employee();
return "employee_create";
}

public String create() {
EntityManager em = getEntityManager();
try {
utx.begin();
em.persist(employee);
utx.commit();
addSuccessMessage("Employee was successfully created.");
} catch (Exception ex) {
try {
if (findEmployee(employee.getId()) != null) {
addErrorMessage("Employee " + employee + " already exists.");
} else {
ensureAddErrorMessage(ex, "A persistence error occurred.");
}
utx.rollback();
} catch (Exception e) {
ensureAddErrorMessage(e, "An error occurred attempting to roll back the transaction.");
}
return null;
} finally {
em.close();
}
return listSetup();
}

public String detailSetup() {
return scalarSetup("employee_detail");
}

public String editSetup() {
return scalarSetup("employee_edit");
}
..
}
Listagem 1 - Parte da Classe EmployeeController gerado pelo NetBeans

Perceba que o NetBeans gerou o código de persistencia em uma classe controller, vamos melhorar um pouco isto, tirando o código de acesso aos dados e isolando isto em uma classe DAO, depois vamos transformar esta classe em um EJB sem interface,

OBS> Cuidado, o uso de um EJB DAO deve ser restrito, pois dependendo do seu uso, isso pode ser um Anti-Pattern

Vamos criar uma nova classe Java acessando o menu Arquivo | Novo Arquivo. Nomeie a classe como EmployeeDAO no pacote br.com.mundojava.dao. Nesta classe vamos colocar todos os métodos de acesso ao banco utilizados na classe EmployeeController e inclui-los na classe recém criada. Veja parte do código na Listagem 18.

Vamos criar uma nova classe Java acessando o menu Arquivo | Novo Arquivo. Nomeie a classe como EmployeeDAO no pacote br.com.mundojava.dao.
Adicionalmente vamos criar uma classe para tratamento de Exceptions, crie uma classe e nomeie de DatabaseException, na classe DAO vamos encapsular os erros de acesso a banco nesta classe.

Criada a classe DAO, vamos colocar todos os métodos de acesso ao banco utilizados na classe EmployeeController. Feito isto, transforme esta classe EmployeeDAO em um EJB colocando a anotação Stateless em cima da declaração da classe. Veja parte da classe criada na Listagem 2.

@Stateless
public class EmployeeDAO {

public static final int PROCESSADO = 1;
public static final int JA_EXISTE = 2;
public static final int ERRO = 3;

@PersistenceUnit(unitName = "DEMO_EJB31PU")
private EntityManagerFactory emf;

private EntityManager getEntityManager() {
  return emf.createEntityManager();
}

  public Employee getEmployeeFromRequestParam(Object employee) {
    EntityManager em = getEntityManager();
     try{
       Employee o = em.merge((Employee) employee);
       return o;
     } finally {
       em.close();
     }
  } 

  public int create(Employee employee) throws DatabaseException{
    EntityManager em = getEntityManager();
    try {
      em.getTransaction().begin();
      em.persist(employee);
      em.getTransaction().commit();
      return EmployeeDAO.PROCESSADO;
    } catch (Exception ex) {
      try{
       int opt = 0;
       if (getEmployee(employee.getId()) != null) {
         opt = EmployeeDAO.JA_EXISTE;
       } else {
         opt = EmployeeDAO.ERRO;
         throw new DatabaseException("A persistence error occurred.");
       }
       em.getTransaction().rollback();
       return opt;
      }catch(Exception sup){
        throw new DatabaseException("An error occurred attempting to roll back the transaction.");
      } finally {
        em.close();
      }
    }
  }

public void edit(Employee employee) throws DatabaseException {
EntityManager em = getEntityManager();
try {
em.getTransaction().begin();
em.merge(employee);
em.getTransaction().commit();
} catch (Exception ex) {
try {
em.getTransaction().rollback();
throw new DatabaseException(ex.getLocalizedMessage());
} catch (Exception e) {
throw new DatabaseException("An error occurred attempting to roll back the transaction.");
}
} finally {
em.close();
}
}
...
}
Listagem 2 - Parte da classe EmployeeDAO recém criada.

Fica um desafio para o leitor do blog, criar os métodos
public void destroy(Employee employee);
public List getEmployees(boolean all, 
                         int batchSize, 
                         int firstItem); 
public List getEmployees(boolean all,  
                         int batchSize,  
                         int firstItem); 
public Employee getEmployee(Integer id); 
public int getItemCount();
Por fim, na classe EmployeeController vamos fazer algumas alterações para consumir o EJB sem interface. Primeiro declare uma variável do tipo EmployeeDAO, e vamos injetar com a referência do EJB, e troque todas as referências ao código de acesso ao banco para apontar para o nosso EJB DAO, veja como ficou na classe EmployeeController na Listagem 3.

public class EmployeeController {
private Employee employee = null;
private List employees = null;
public int batchSize = 5;
private int firstItem = 0;
private int itemCount = -1;
@EJB
EmployeeDAO dao;

public SelectItem[] getEmployeesAvailableSelectMany() {
return getEmployeesAvailable(false);
}

public SelectItem[] getEmployeesAvailableSelectOne() {
return getEmployeesAvailable(true);
}

private SelectItem[] getEmployeesAvailable(boolean one) {
List allEmployees = getEmployees(true);
int size = one ? allEmployees.size() + 1 : allEmployees.size();
SelectItem[] items = new SelectItem[size];
int i = 0;
if (one) {
items[0] = new SelectItem("", "---");
i++;
}
for (Employee x : allEmployees) {
items[i++] = new SelectItem(x, x.toString());
}
return items;
}

public Employee getEmployee() {
if (employee == null) {
employee = getEmployeeFromRequest();
}
if (employee == null) {
employee = new Employee();
}
return employee;
}

public String listSetup() {
reset(true);
return "employee_list";
}

public String createSetup() {
reset(false);
employee = new Employee();
return "employee_create";
}

public String create() {
int resultado = dao.PROCESSADO;
try {
resultado = dao.create(employee);
if (resultado == dao.PROCESSADO) {
addSuccessMessage("Employee was successfully created.");
} else if (resultado == dao.JA_EXISTE) {
addErrorMessage("Employee " + employee + " already exists.");
}
} catch (Exception ex) {
ensureAddErrorMessage(ex, ex.getLocalizedMessage());
}
return listSetup();
}

public String detailSetup() {
return scalarSetup("employee_detail");
}

public String editSetup() {
return scalarSetup("employee_edit");
}

private String scalarSetup(String destination) {
reset(false);
employee = getEmployeeFromRequest();
if (employee == null) {
String requestEmployeeString = getRequestParameter("jsfcrud.currentEmployee");
addErrorMessage("The employee with id " + requestEmployeeString + " no longer exists.");
String relatedControllerOutcome = relatedControllerOutcome();
if (relatedControllerOutcome != null) {
return relatedControllerOutcome;
}
return listSetup();
}
return destination;
}

public String edit() {
EmployeeConverter converter = new EmployeeConverter();
String employeeString = converter.getAsString(FacesContext.getCurrentInstance(), null, employee);
String currentEmployeeString = getRequestParameter("jsfcrud.currentEmployee");
if (employeeString == null || employeeString.length() == 0 || !employeeString.equals(currentEmployeeString)) {
String outcome = editSetup();
if ("employee_edit".equals(outcome)) {
addErrorMessage("Could not edit employee. Try again.");
}
return outcome;
}
try {
dao.edit(employee);
addSuccessMessage("Employee was successfully updated.");
} catch (DatabaseException ex) {
String msg = ex.getLocalizedMessage();
if (msg != null && msg.length() > 0) {
addErrorMessage(msg);
}else if (getEmployeeFromRequest() == null) {
addErrorMessage("The employee with id " + currentEmployeeString + " no longer exists.");
return listSetup();
} else {
addErrorMessage("A persistence error occurred.");
}
return null;
}
return detailSetup();
}

public String destroy() {
employee = getEmployeeFromRequest();
if (employee == null) {
String currentEmployeeString = getRequestParameter("jsfcrud.currentEmployee");
addErrorMessage("The employee with id " + currentEmployeeString + " no longer exists.");
String relatedControllerOutcome = relatedControllerOutcome();
if (relatedControllerOutcome != null) {
return relatedControllerOutcome;
}
return listSetup();
}
try {
dao.destroy(employee);
addSuccessMessage("Employee was successfully deleted.");
} catch (DatabaseException ex) {
ensureAddErrorMessage(ex, ex.getLocalizedMessage());
return null;
}

String relatedControllerOutcome = relatedControllerOutcome();
if (relatedControllerOutcome != null) {
return relatedControllerOutcome;
}
return listSetup();
}
...
}

Listagem 3 - Classe EmployeeController refatorada para utilizar o EJB DAO sem interface

Perceba que na expressão "@EJB EmployeeDAO dao" estamos referenciando ao EJB, sem interface para atrapalhar, claro que não é possível criar uma instância utilizando a palavra reservada new ainda, na verdade estamos trabalhando com um proxy, mas se quisermos podemos fazer um lookup utilizando JNDI também.
Vou deixar o restante dos métodos para o leitor resolver, é apenas trocar a referencia pela classe dao conforme os métodos acima.


Compile e faça o deploy, rode a aplicação, se tudo deu certo você irá ver a sua aplicação rodando (ver figura 2) com um EJB sem interface, e o melhor, o EJB está dentro de um arquivo .war, já estamos implementando o empacotamento simplificado.






Veja como ficou o empacotamento do nosso projeto na Figura 3.



Para maiores informações sobre o futuro do Java Corporativo, leia a edição 31 da Mundo Java, que ainda traz ótimos artigos como:

  • EJB 3.1:Conheça as Novidades do Futuro do Java Corporativo.
  • Autor:Wagner Roberto dos Santos
  • Grizzly e Comet - Ajax Reverso com Escalabilidade.
  • Autor: Pedro Cavalero
  • Usando o Mavem para melhorar a Qualidade dos seus Projetos.
  • Autor:Márcio Varchavsky
  • Criando Software mais próximo do Cliente com Domain-Drivgen Design.
  • Autor:Sérgio Lopes
  • Setembro: Mês de Java.
  • Autor:Mauricio Leal
  • Testes de unidades Avançadas com JMock 2
  • Autor:Eduardo Guerra
  • Gerenciamento de Conteúdo Web com OpemCMS -Customização de Sites.
  • Autor:Rodrigo Cunha de Paiva
  • Tirando o Máximo dos Interceptors no Struts2.
  • Autor: José Yoshiriro Ajisaka Ramos
  • Tendências em Foco:Ganhando com Open Source
  • Autor:Cezar Taurion
  • Jogo Rápido
  • Autor:Charbel Symanski e Rodrigo Barbosa Cesar
  • Mundo OO: Requisitos Executáveis com FIT
  • Autor:Rodrigo Yoshima
  • SOA na Pratica:Iniciando Projetos SOA.
  • Autor:Ricardo Ferreira









Diversão Garantida !!!

[EJB 3.1] Novidades na especificação - Parte 2

sexta-feira, 2 de maio de 2008

Continuando o artigo sobre as novidades na Especificação EJB 3.1, nesta segunda parte vamos abordar o invoções assíncronas e EJB sem interface.

Na nova especificação um cliente pode invocar um session bean de maneira síncrona ou assíncrona. Invocações assíncronas que é a novidade nos permite efetuar uma chamada a um método remoto (assíncrono) e não precisamos esperar o seu retorno, neste caso a assinatura do método deve ser void, ou o método pode retornar um objeto Future que retorna o resultado para o cliente após o processamento, o que permite verificar as exceções ou até mesmo cancelar a invocação ao método no meio da execução.


Exemplo:

@Asynchronous
public Future executarMetodo() {
String resultado = "Executando Método";
return new AsyncResult(resultado);
}

Outra novidade é o que todos já esperavam "O Fim das Interfaces", ou pelo menos agora elas são opcionais. Antes que alguém se empolgue é bom deixar claro que isso só funciona para objetos LOCAIS, ou seja, o cliente que irá chamar o método deve estar na mesma JVM. :-(Na verdade um session bean sem interface é uma variação do EJB local, mas expõe os métodos públicos da classe bean sem utilizar uma interface de negócio separada.
A referência para o Bean sem interface pode ser passada como um parâmetro, como valor de retorno de qualquer interface de negócio local ou como método de uma classe ejb sem interface.
A implementação do contêiner para Beans sem interface é o mesmo que nós fazemos quando acessamos um método qualquer de uma classe qualquer pela referência, o método de negócio da instancia do session bean e seus interceptors são invocados conforme a necessidade.
Somente os métodos públicos da classe bean (e qualquer super-classe) pode ser invocado através do Bean sem interface. Qualquer tentativa de invocação a métodos com modificadores de acessos diferente de público, irá lançar um javax.ejb.EJBException.
Vejamos a evolução da especificação EJB, dando o mesmo exemplo nas versões 2.1, 3.0 e finalmente 3.1.

Versão 2.*

Até a versão 2.* a comunidade reclamava muito da complexidade dos EJBs, para a criação de um método simples era preciso criar as interfaces (remota e local), a interface home e finalmente a classe de negócio...

Interface Local

import javax.ejb.EJBLocalObject;

public interface SayHelloRemote extends EJBLocalObject{
public void hello();
}

Interface Home

import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;

public interface SayHelloHome extends EJBLocalHome {
SayHello create() throws CreateException;
}

Session Bean

import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class SayHelloBean implements SessionBean {
public void sayHello() {
System.out.println("Hello");
}

public SayHelloBean() {}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sc) {}
}


Cliente Session Bean 2.1

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

public class SayHelloClient {

public static void main(String[] args) {
try {
Context initial = new InitialContext();
Context myEnv = (Context)initial.lookup("java:comp/env");
Object objref = myEnv.lookup("ejb/SayHello");
SayHelloHome home = (SayHelloHome) PortableRemoteObject.narrow(objref,
SayHelloHome.class);
SayHello papagaio = home.create();
papagaio.sayHello();
papagaio.remove();
System.exit(0);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Versão 3.0

Vemos que até a versão 2.1 era muito trabalho criar um simples Hello World com EJB, a Sun vendo que o EJB estava perdendo espaço para frameworks comunitários, como Hibernate para persistência e outras alternativas para Session Beans, decidiu fazer uma mudança radical na especificação, descontinuando os Entity Beans e apresentando o JPA, e tirando a obrigatoriedade de criar a classe Home, eliminando a criação de deployment descriptors, usando e abusando da IoC com o uso extensivo de annotations. A especificação facilitou muito o desenvolvimento e a especificação EJB voltou a ser o supra sumo do Java, vejamos um exemplo

Interface de Negócio Local

import javax.ejb.Local;

@Local
public interface SayHelloLocal {
void hello();
}

Session Bean

import javax.ejb.Stateless;

@Stateless
public class SayHelloBean implements SayHelloRemote, SayHelloLocal{
public void hello() {
System.out.println("Hello");
}
}

Cliente que executa o EJB

public class SayHelloClient {
private static Properties prop = new Properties();
private static Context c;
public SayHelloClient(){
prop.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
prop.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
prop.put("java.naming.provider.url","localhost");
}
public static void main(String[] args) {
SayHelloClient main = new SayHelloClient();
SayHelloRemote remote = main.lookupSayHelloBean();
remote.sayHello();
}
private SayHelloRemote lookupSayHelloBean() {
try {
c = new InitialContext(prop);
return (SayHelloRemote) c.lookup("SayHelloBean/remote");
} catch (NamingException ne) {
throw new RuntimeException(ne);
}
}
}

Versão 3.1 Draft

Com a eliminação da classe home não precisamos mais fazer o narrow no código cliente. Agora basta efetuar um lookup na classe Bean.

Classe de implementação de negócio
// Sem Interfaces Remota ou Local
import javax.ejb.Stateless;

@Stateless
public class SayHelloBean implements SayHelloRemote, SayHelloLocal{
public void hello() {
System.out.println("Hello");
}
}

Cliente que executa o EJB

public class SayHelloClient {
// Se o cliente estiver no conteiner, Injeção nele !!!
// Veja que estamos referenciando ao session bean
// SayHelloBean e não SayHelloRemote.

@EJB SayHelloBean falaAi;
@Resource SessionContext c;
public SayHelloClient(){}
public static void main(String[] args) {
falaAi.hello();
SayHelloClient main = new SayHelloClient();
SayHelloBean sayAgain = main.lookupSayHelloBean();
sayAgain.hello();
}

// Ou podemos fazer via JNDI
private SayHelloRemote lookupSayHelloBean() {
try {
return (SayHelloBean) c.lookup("sayHello");
} catch (NamingException ne) {
throw new RuntimeException(ne);
}
}
}

Podemos observar que esta muito mais simples criar EJBs, sem as interfaces o código fica muito mais limpo e temos uma programação muito próximo de objetos POJO, entretanto, por motivos já conhecidos não é possível instanciar um objeto com o operador new, somente via injeção ou jndi. Para a especificação 2.1 por exemplo, tínhamos que criar 4 objetos para um simples hello world (local), na especificação 3.0 não é obrigatório implementar a interface SessionBean na classe session bean ou a interface Serializable, assim como as classes Interceptors. Viva a injeção de dependência !!!
Veja que ainda precisamos de 3 objetos (sai a interface home) mas o processo já simplifica com a entrada das annotations. Agora na versão 3.1 foi eliminada a necessidade de interfaces (lembre-se, apenas para objetos locais)..
Para criar um EJB sem utilizar a interface, ela deve seguir algumas seguintes regras, ela deve expor os métodos sem interface via definição de classe ou pelo deployment descriptor. E ... :
  • Se o bean não expor nenhuma outra interface(s) e não implementar nenhuma interface, então o bean define uma EJB sem interface.
  • As seguintes interfaces são excluídas quando implementamos um EJB sem interface : java.io.Serializable, java.io.Externalizable; E qualquer outra interface definida no pacote javax.ejb.
  • Todos os métodos da classe bean e qualquer superclasse são expostos como métodos de negócios através de um bean sem interface. E isto inclui os métodos de callback (muito cuidado !!!).
  • Os métodos expostos da classe bean sem interface não devem lançar a exceção java.rmi.RemoteException.

Ainda tem várias coisas legais para discutir, provavelmente será possível rodar EJB no TomCat :D, com o pacote light do EJB, no próximo post vou cobrir o calendário para o Timer e concorrência !!!

[EJB 3.1] Novidades na especificação - Parte 1

quarta-feira, 30 de abril de 2008

O mercado brasileiro ainda nem assimilou direito a especificação de EJB 3.0 e a JSR-318 - Enterprise JavaBeans 3.1 já foi aprovado pela maioria dos membros do comit executivo para as especificações SE / EE do Java. O único membro que reprovou a JSR foi a Apache.


Isso porque a Apache Software Foundation diz que a spec lead (SUN) esta em desacordo com a JSPA. O que foi explicado pela própria Sun.

The spec lead of the EJB 3.1 specification has confirmed that the TCK would contain no "field of use restrictions", as originally raised by Apache with regard to another JSR (i.e. the SE TCK licensing). That is a good thing.

However, in the absence of an explicit JSPA rule that would forbid such field-of-use restrictions, we will remain worried that a similar issue might resurface anytime, for any JSR.

Consequently, in the future, for any submitted JSR (by SUNW or not), we will specifically expect the spec lead to provide clear information on that aspect and take the answer in account when casting our vote.

As novidades na especificação 3.1 visou simplificar a já fácil especificação 3.0 dos EJBs, aumento o uso de annotations e consequentemente o uso ioc, conforme segue:

  • Uma visão Local simplificada que forneça acesso ao Session Bean sem a necessidade de uma interface de negócio local.

  • Empacotamento e o deployment de componentes EJB diretamente de uma arquivo .war sem a necessidade de um ejb-jar.

  • Um componente Session Bean Singleton que forneça um acesso fácil para estado compartilhado, assim como callbacks de startup/shutdown da aplicação.

Isso quer dizer que agora temos um novo tipo de Session Bean, diferente de um Session Beans Stateful ou Stateless, o Session Bean Singleton é um componente que é instanciado apenas uma vez por aplicação. Em casos onde o conteiner é distribuído para várias JVMs, cada aplicação irá possuir uma instância de um bean Singleton para cada JVM. O Session Bean Singleton é compartilhado e suporta acessos concorrentes.
Uma vez instanciado, o tempo de duração da instância do Session Bean Singleton é o mesmo do Contêiner onde ele foi criado. O que mantêm o estado entre as invocações do cliente mas o conteiner não é obrigado a preservar o estado do bean em um suposto crash ou shutdown no conteiner. Resumindo, Singleton Session Beans NÃO são passivados (é assim que se traduz ?).
Outra coisa, um Session Bean Singleton pode ser utilizado como um cliente web service. Somente um Session Bean Stateless ou Single podem fornece uma visão cliente de web service.

Eis o ciclo de vida de Singleton Session View.




  • O ciclo de vida de um session bean singleton inicia quando o conteiner invoca o método newInstance da classe Session Bean para uma instância do Singleton. A seguir, o conteiner realiza as injeções de dependência especificado pelas anotações na classe bean ou pela DD. O conteiner chama o método callback PostConstruct para o bean, se houver.

  • A instancia do SB Singleton esta agora pronta para delegar a chamada do método de negócio para qualquer cliente ou a chamada do conteiner para método callback disparado por timeout.

  • Quando a aplicação esta em shutdown, o conteiner invoca o método callback PreDestroy do Singleton, se houver. Isto finaliza o ciclo da instancia do session bean singleton.

Inicialização do Singleton

O conteiner decide o momento de instanciar o bean Singleton. Se o conteiner encontrar a anotação Startup na classe Singleton ou se o deployment descriptor estiver especificado startup na classe bean o conteiner DEVE instanciar durante o startup da aplicação. O exemplo abaixo inicializa a classe Singleton com estado compartilhado:

@Startup
@Singleton
public class SharedBean implements Shared {
private SharedData state;
@PostConstruct
void init() {
// initialize shared data
...
}
...
}



Outra novidade, é a possibilidade de criar uma cadeia de dependência entre múltiplos componentes Singleton em uma aplicação, através da anotação DependsOn.

@Target(value=TYPE)
@Retention(value=RUNTIME)
public @interface DependsOn


Esta anotação é utilizada quando precisamos iniciar uma instancia de um bean Singleton antes de instanciar outro objeto. Se um Singleton precisa invocar outro Singleton a partir do método PostConstruct, não é necessário uma ordenação via metadados (DD). Exemplo:

@Singleton
public class B { ... }
@DependsOn("B")
@Singleton
public class A { ... }


Essa anotação diz para o conteiner para garantir que o Singleton B é inicializado antes do Singleton A.
É possível incluir um ou mais valores no atributo value de DependensOn, onde cada valor especifica o ejb-name do Singleton destino utilizando a mesma sintaxe do atributo beanName() de @EBJ. Exemplo:

@Singleton
public class B { ... }
@Singleton
public class C { ... }
@DependsOn({"B", "C"}) // A só será iniciado após B e C serem iniciados
@Singleton
public class A { ... }



Isso garante que A só será iniciado após B e C serem iniciados. No caso de múltiplos valores, a ordem que os valores foram informados em value não garante a ordem de execução em runtime.

Ex,: Se o Singleton B possui uma dependência na ordenação no Singleton C, é a responsabilidade do Singleton B de capturar o que está explicito em seu metadado. Exemplo:

// 2 componentes Singleton empacotados em ejb-jars diferentes
// mas no mesmo arquivo .ear
// empacotado no arquivo b.jar
@Singleton
public class B { ... }
// packaged in a.jar
@DependsOn("b.jar#B")
@Singleton
public class A { ... }


Isto demonstra o uso do nome totalmente qualificado da sintaxe do ejb-name para referencia ao componente Singleton empacotado em um módulo diferente na mesma aplicação.

Lembra no EJB 3.0 para evitarmos nomes ambíguos
@EJB(beanName="netfeijao-ejb.jar#NetFeijaoEJB")

Em breve vou publicar mais sobre a nova especificação, para saber mais leia o artigo publicado no server-side, e a página da JSR..

  1. JSR 318: Enterprise JavaBeans 3.1
  2. Artigo na Server Side

Certificação SCBCD 5 (CX-310-091) - Guia de Estudo

sexta-feira, 15 de fevereiro de 2008

Recentemente tive a felicidade de passar a prova da certificação SCBCD 5.0 com o score de 75%.. não fui muito bem em JPA, pois acabei subestimando a esta parte por conta da experiência que tenho com persistência, enfim ao todo foram 61 perguntas tive e fui avaliado nas seguintes seções:
---------------------------------------------------------------

  • EJB 3.0 Overview
  • General EJB 3.0 Enterprise Bean Knowledge
  • EJB 3.0 Session Bean Component Contract & Lifecycle
  • EJB 3.0 Message-Driven Bean Component Contract
  • Java Persistence API Entities
  • Java Persistence Entity Operations
  • Persistence Units and Persistence Contexts
  • Java Persistence Query Language
  • Transactions
  • Exceptions
  • Security Management
---------------------------------------------------------------

Como fiquei alguns meses me preparando para esta prova, tive a oportunidade de conhecer as melhores fontes na Web para a preparação desta certificação tão almejada.

Mocks (Simulados):

JavaBeat - http://www.javabeat.net/javabeat/scbcd5/mocks/

Esse site possui 4 mocks bem interessantes,..

Existem também softwares comerciais ($$) de simulados conforme os links que segue, mas o 3 possuem uma versão demo para download, com várias questões, vale a pena baixar pelo menos a versão demo pois as questões são bem similares ao exame real.


Resumos (Notes) de estudo

Esse site (Java Boot) é ótimo pois oferece um material completo de cada tópico abordados nos objetos, ALTAMENTE RECOMENDADO.

Java Boot -http://java.boot.by/scbcd5-guide/

Livros:

Bom eu li todo o livro Enterprise JavaBeans 3.0 (5th.Edition)


Outro otimo livro para estudo é o Mastering Enterprise JavaBeans 3.0 que pode ser baixado FREE neste link no site ServerSide.com

E li alguns capítulos do Java EE Tutorial 5 da Sun, mais precisamente os capítulos:

Capítulo 1 - Overview.
Leitura que fornece um overview da arquitetura de servidores Java EE, os tipos de serviços que os servidores que são certificados devem implementar, e conceitos de aplicações distríbuidas, os papéis do devenvolvimento (Bean Provider, Application Assemblem, Deployer, etc...) é bom conhecer bem estes papéis, pois caiu na prova não uma, mas várias questões que exigem o conhecimento dos papéis no desenvolvimento de software corporativo. Depois vamos pular para o Capítulo 20, que aborda o assunto de EJBs em uma visão macro, é interessante estudar também o Capítulo 21, que ensina como iniciar o desenvolvimento em EJB, o Capítulo 22 que apresenta códigos de exemplo para Session Beans, o Capítulo 23 que aborda de maneira prática Message Driven Beans, os Capítulos 24, 25, 26 e 27 que aborda Java Persistence API, é bom estudar também segurança nos Capítulos 28 e 29 se você não conhece JMS, não é prioritário saber para o exame mas como o exame aborda MDB recebendo mensagens de JMS é bom ler o capítulo 31 e 32 que é feito um pente fino, outro capítulo muito importante é o Capítulo 33 que aborda transações (Transactions) , e por fim os Capítulos 34 e 35 que abordam JNDI ENC e Conectores respectivamente..


Segue o link que pode ser baixado no site da Sun ou pode ser navegado online neste link: Tutorial Java EE 5.

Outro site muito importante para quem deseja tirar qualquer certificação é o JavaRanch, o link para SCBCD 5 é o http://faq.javaranch.com/java/ScbcdLinks#scbcd50


É isso aí, Boa Sorte e com todo esse material, com certeza a diversão é garantida !!!!