da monografia

Propaganda
UNIVERSIDADE TIRADENTES - UNIT
CENTRO DE CIÊNCIAS FORMAIS E TECNOLOGIA - CCFT
CONSTRUÇÃO DE COMPONENTES PARA ACESSO À
BANCO DE DADOS USANDO ENTERPRISE JAVA BEANS
ALINE SOUTO BEZERRA
PROJETO SUPERVISIONADO
Aracaju (SE) – Brasil
2001
UNIVERSIDADE TIRADENTES - UNIT
CENTRO DE CIÊNCIAS FORMAIS E TECNOLOGIA - CCFT
CONSTRUÇÃO DE COMPONENTES PARA ACESSO À
BANCO DE DADOS USANDO ENTERPRISE JAVA BEANS
Monografia apresentada ao Centro de Ciências Formais
e Tecnologia da Universidade Tiradentes.
Área: Desenvolvimento de Aplicações
Orientador: Prof. Andrés I. Martínez Menéndez
ALINE SOUTO BEZERRA
PROJETO SUPERVISIONADO
Aracaju (SE) – Brasil
2001
DATA 07/12/2001.
BANCA
_________________________________________
1º examinador
_________________________________________
2º examinador
_________________________________________
3º examinador
ii
AGRADECIMENTOS
Inicialmente gostaria de agradecer a meu orientador Andrés Ignácio Martínez
Menéndez que me propôs este trabalho, me incentivando e apoiando em todo o
momento com muita dedicação e paciência. Gostaria de agradecer também a meus
amigos
inseparáveis
Alysson,
Danielle,
Luana
e
Norma
que
estiveram
me
acompanhando não só neste trabalho, mas em toda a minha vida acadêmica, dividindo
comigo minhas alegrias e tristezas.
iii
SUMÁRIO
AGRADECIMENTOS______________________________________________________ iii
LISTA DE FIGURAS _______________________________________________________vi
RESUMO _________________________________________________________________ vii
INTRODUÇÃO _____________________________________________________________ 9
1. ENTERPRISE JAVA BEANS ____________________________________________ 11
1.1 VANTAGENS DO ENTERPRISE JAVA BEANS ___________________ 15
1.2 ARQUITETURA EJB ___________________________________________________ 16
1.2.1 SERVIDOR EJB _____________________________________________________ 17
1.2.2 CONTÊINER EJB ____________________________________________________ 18
1.2.3 TIPOS DE EJB_______________________________________________________ 19
2. COMO CRIAR UM ENTERPRISE JAVA BEAN _________________________ 21
2.1 INTERFACE REMOTA _________________________________________________ 21
2.2 INTERFACE HOME ____________________________________________________ 24
2.3 CLASSE ENTERPRISE BEAN __________________________________________ 25
2.4 DEPLOYMENT DESCRIPTOR __________________________________________ 29
2.5 CLASSE DA CHAVE PRIMÁRIA ________________________________________ 31
3. BEANS DE SESSÃO ____________________________________________________ 33
3.1 TIPOS DE SESSION BEAN _____________________________________________ 33
Session Bean Stateless ___________________________________________________ 35
4. BEANS DE ENTIDADE _________________________________________________ 39
4.1 TIPOS DE ENTITY BEAN _______________________________________________ 40
5. Comparativo entre beans de sessão e beans de entidades. ___________________ 41
6. JDBC (Java DataBase Connectivity) ______________________________________ 44
6.1 TIPOS DE DRIVERS ___________________________________________________ 50
7. SOLUÇÃO PROPOSTA _________________________________________________ 52
8. JSP ( Java server page ) __________________________________________________ 59
9. JBOSS __________________________________________________________________ 61
iv
10. CONCLUSÃO ____________________________________________________________ 63
11. Apêndice 1 – Instalação do JBoss. _______________________________________ 65
12. Apêndice 2 – CLASSES DA API DE ACESSO ___________________________ 68
13. referências bibliográficas _______________________________________________ 82
v
LISTA DE FIGURAS
Arquitetura EJB 1.......................................................................................................................... 16
Modelo Session Bean e Entity Bean 1 ........................................................................................... 20
Interface Remota 1......................................................................................................................... 22
Arquitetura JDBC 1....................................................................................................................... 46
Funcionamento API de Acesso 1 ................................................................................................... 54
Funcionamento API de Acesso 2 ................................................................................................... 55
vi
RESUMO
O desenvolvimento de aplicações sofreu enormes mudanças nos últimos anos e
o grande responsável por este processo foi o rápido movimento e a demanda no mundo
do comércio eletrônico e da tecnologia da informação. Isto fez com que os
desenvolvedores de aplicações focassem suas atenções para essas alterações.
Estamos vivendo em uma era não mais orientada a um processamento
centralizado em computadores de grande porte. Computadores pessoais são as
ferramentas de trabalho de todas as corporações e a necessidade da integração entre
elas em um ambiente de processamento distribuído é uma realidade. O grande
problema atual é a dificuldade de encontrar ferramentas de desenvolvimento capazes
de fornecer tudo isso com pouca complexidade para o desenvolvedor.
Buscando soluções para estes problemas, a Sun Microsystems desenvolveu
uma plataforma de desenvolvimento chamada J2EE (Java 2 Enterprise Edition). Esta
tecnologia fornece um modelo de ambiente distribuído em várias camadas; a habilidade
de reutilização de componentes; um modelo de segurança unificado e a flexibilidade no
controle de transação. Esta plataforma faz uso de APIs (Interface para programação de
aplicação), que são bibliotecas voltadas para o desenvolvimento de aplicações
corporativas.
Porém, muita coisa ainda precisa ser realizada para permitir um desenvolvimento
mais rápido de aplicações multicamadas. Um dos problemas encontrados pelos
desenvolvedores de aplicações é que a linguagem Java disponibiliza uma API de baixo
nível para acesso a dados, elevando o custo e tempo de desenvolvimento do sistema.
Para melhorar o quadro atual, este trabalho propõe criar uma interface de acesso. Isto
tem como objetivo facilitar a tarefa do desenvolvedor. O mesmo ficará responsável
somente pela lógica da aplicação, partindo do princípio que é necessário conhecer
apenas quais métodos devem ser chamados para executar uma determinada tarefa.
Serão construídos componentes, em Java, que podem ser usados pelos
desenvolvedores de software nas suas aplicações de acesso a banco de dados.
vii
INTRODUÇÃO
Para a implementação deste trabalho foi escolhida a plataforma Java por ser um
modelo de computação baseado no poder das redes e na idéia de que o mesmo
software poderia ser executado em diferentes tipos de computadores, aparelhos ou
outros dispositivos. Ela pode ser descrita como uma ferramenta de desenvolvimento de
aplicativos que fornece uma linguagem de programação orientada a objetos simples, de
alta performance, interpretada e portável.
A linguagem Java possui um conjunto de APIs. Estas APIs permitem que os
9
fabricantes de software desenvolvam componentes reutilizáveis que podem ser
incorporados pelos usuários finais nos seus programas, através de ferramentas visuais,
de construção de aplicativos. Beans são classes escritas em Java, qualquer classe
pode ser chamada de Bean, desde que apresente certas propriedades e determinadas
conversões para eventos de interfaces, estas propriedades serão vistas no decorrer
deste trabalho.
Para desenvolver um Bean é disponibilizado pela Sun o BDK (Bean
Development Kit) que é uma aplicação escrita em Java que fornece mecanismos de
suporte para a construção de JavaBeans, além de incorporar um ambiente de teste
para beans desenvolvidos.
Neste trabalho iremos construir componentes em Java que possam ser usados
pelos desenvolvedores de softwares nas suas aplicações de acesso à banco de dados.
Para isso iremos utilizar a API Enterprise Java Bean que estende o modelo JavaBean e
é direcionada para a produção de componentes que possam ser distribuídos,
escaláveis e que possam ser utilizados em aplicações multicamadas.
10
1. ENTERPRISE JAVA BEANS
“Enterprise JavaBeans é uma arquitetura de componentes que visa o desenvolvimento
de aplicações distribuídas, baseando-se em componentes. As aplicações projetadas
para a arquitetura Enterprise JavaBeans são escaláveis, robustas, gerenciam
transações e gerenciam a segurança em ambiente multiusuário. Estas aplicações
podem ser escritas uma vez e distribuídas para qualquer plataforma de servidor que
suporte a especificação Enterprise JavaBeans”. (Sun Microsystems Enterprise
JavaBeansTM specification, v1.1, 1999).
Verificando a definição anterior, sobre a arquitetura Enterprise Java Beans,
11
podemos notar a força e a importância que a sua especificação fornece para os
desenvolvedores de uma forma geral. Nesta sessão será mostrado o que é a
arquitetura EJB e como ela funciona.
Enterprise Java Bean é uma tecnologia de desenvolvimento para aplicações que
utilizam
as
tecnologias
de
desenvolvimento
em
n-camadas.
Ela
ajuda
na
implementação de regras de negócio de uma aplicação empresarial, no acesso à banco
de dados ou ainda a sistemas legados.
Esta
tecnologia
de
desenvolvimento
baseada
em
Java
possibilita
o
desenvolvimento de componentes que permitem que as aplicações se comuniquem por
várias camadas cliente e servidor além de usar Internet e Intranet. Com esses
componentes definidos, o desenvolvedor da aplicação final precisa apenas implementar
a interface com o usuário, que pode ser um site WEB utilizando-se JavaServer Pages
(JSP), Servlets ou mini-aplicativos (Applets); pode ser uma aplicação para dispositivos
móveis (WAP); pode também ser uma aplicação desktop no estilo GUI (Graphical User
Interface) ou ainda pode ser baseada em caracteres.
O EJB é usado quando existe a necessidade de objetos distribuídos
12
comunicarem entre cliente–servidor ou servidor-servidor.
A tecnologia EJB representa a junção entre duas tecnologias: (a) os
processamentos transacionais (TP), que são ambientes onde rodam aplicações escritas
em linguagens procedurais; (b) e os serviços de componentes distribuídos.
Combinando o melhor do “processamento transacional” e dos “componentes
distribuídos”, a tecnologia EJB provê um misto entre o processamento transacional,
com
características
que
reduzem
a
complexidade
no
desenvolvimento
pelo
gerenciamento automático de todo o ambiente programável, incluindo transações,
segurança, concorrência e persistência, com as características de componentes
distribuídos que fornecem maior produtividade ao desenvolvimento de aplicativos na
construção de aplicações a partir de componentes flexíveis e reutilizáveis.
O modelo de componente EJB permite ao desenvolvedor de aplicação trabalhar
nos aspectos de negócio da aplicação sem ter que focalizar em gerenciamento da
transação, segurança, persistência de dados ou a administração do ciclo de vida do
objeto. Quando não usamos EJB, o desenvolvedor precisa tomar conta dos seus dados
“na mão”, isto é:
13
•
Abrir uma conexão com o banco de dados;
•
É necessário solicitar um registro e traduzi-lo para objetos;
•
Deve-se monitorar o desempenho e a transação;
•
Escrever suas rotinas;
•
Fechar a conexão com o banco de dados.
Isso mostra que no passado, os desenvolvedores tinham que escrever suas
próprias rotinas de rollback ou commit1, ou pelo menos conhecer as interfaces para
complexos sistemas transacionais. Com a tecnologia EJB, os desenvolvedores focam
seus esforços na lógica do negócio, ficando as funções de baixo nível a cargo do
servidor de aplicação. Com isso o sistema fica menos sujeito a erros e o desenvolvedor
é mais produtivo.
Enterprise JavaBean roda na camada intermediária de arquitetura em ncamadas. O termo n-camadas é utilizado para denominar uma arquitetura onde
podemos ter várias camadas que fazem trabalhos específicos. Normalmente uma
camada é composta por clientes Java que acessam os “beans” (applets, JSP, entre
outros). Uma outra camada é composta pelos beans propriamente ditos que acessam
uma outra camada de acesso a banco de dados
14ROLLBACK: Aborta a transação corrente
COMMIT: Executa a efetivação da transação corrente e começa uma nova;
(Silberschtz,Abraham;Korth,Henry F.; Sudarshan,S:1999:460)
1
1.1 VANTAGENS DO ENTERPRISE JAVA BEANS
1.1.1 PORTABILIDADE, PERSONALIZAÇÃO E REUTILIZAÇÃO
Os componentes EJB são portáveis entre os servidores de aplicativos
compatíveis com o EJB de qualquer fornecedor e podem ser executados em qualquer
plataforma. Um componente EJB pode ser personalizado para ser executado em um
ambiente específico, além do que, uma vez definidos e empacotados eles podem ser
reutilizados.
1.1.2 ARQUITETURA PERSISTENTE E INDEPENDENTE
As especificações EJB definem um modelo persistente de componente do lado
do servidor, e qualquer aplicativo desenvolvido em uma plataforma pode ser distribuído
em outra.
15
1.1.3 DESENVOLVIMENTO MAIS RÁPIDO DE APLICATIVO
Os provedores de beans concentram-se no desenvolvimento de classes EJB que
implementam a lógica comercial e não mais se preocupa com a implementação de
serviços de infra-estrutura complexos em seus programas.
1.2 ARQUITETURA EJB
A aplicação EJB possui a seguinte arquitetura:
Arquitetura EJB 1
16
JNDI (Java Naming and Directory Interface) fornece uma interface única
padronizada pela indústria para os serviços de nomenclatura de diretórios, gerando o
compartilhamento de uma variedade de informações a respeito de usuários, nas redes,
servidores e aplicativos por toda a rede.
1.2.1 SERVIDOR EJB
O servidor EJB é um aplicativo que gerência os contêineres EJB e provê acesso
aos serviços do sistema, ele é quem executa os beans empresariais2 e fornece objetos
de serviço, como serviços de transação e segurança. Os EJBs são executados dentro
de um contêiner EJB que fica dentro do servidor EJB.
Um servidor EJB pode ser qualquer banco de dados, de aplicativos e de camada
central que possa ter um contêiner EJB e fornecer a ele os serviços necessários, como:
serviços de localização, controle transacional, segurança, serviço de mensagem e
serviços de baixo nível (por exemplo, conectividade de rede).
17
2
Chamo de beans empresariais por que se tratam de beans que representam uma entidade de objeto de negócio
1.2.2 CONTÊINER EJB
A principal responsabilidade do contêiner EJB é responder as pesquisas de
clientes e tornar os objetos EJB acessíveis para os clientes, fornecendo os seus
serviços através de heranças de métodos ou de invocação remota.
Os EJBs são componentes que funcionam em contêineres EJBs. Estes
contêineres apresentam uma interface uniforme que gerencia as interações entre beans
empresariais e servidor. O contêiner EJB gerencia muitas instâncias e muitos
componentes EJBs, consistindo-se em várias classes EJBs.
Serviços de gerenciamentos de transações e recursos como segurança,
gerenciamento de cache e de mensagens, flexibilidade, mobilidade, controle de
versões, persistência e conectividade de banco de dados, são fornecidos pelo contêiner
EJB para o bean empresarial que ele contém.
18
1.2.3 TIPOS DE EJB
Um bean é um componente que pode ser usado independente ou com outro
bean para construir um aplicativo. Existem dois tipos: os Session beans e os Entity
beans. Os Session beans são uma extensão do aplicativo cliente e os Entity beans são
objetos persistentes que representam linhas de uma tabela de banco de dados.
Os Entity Beans armazenam dados permanentes, em algum banco de dados ou
sistemas de arquivos, e métodos associados para manipulação dos mesmos. Na
maioria dos casos, um Entity bean deve ser acessado de alguma forma transacional.
Suas instâncias são exclusivas e elas podem ser acessadas por vários usuários. Por
exemplo, as informações sobre uma conta bancária podem ser armazenadas em uma
instância de um bean, este pode conter uma identificação para a conta, o tipo da conta
(corrente ou poupança) e um balanço.
Os Session beans armazenam uma ou mais tarefas de negócios e dados que
não são permanentes a um cliente em particular. No caso do session bean, como eles
não são armazenados em uma fonte de dados permanentes, não existe mal nenhum
19
em se perder estes dados. Porém, isso não significa dizer que um session bean não
possa atualizar dados em um banco de dados, ele pode fazer isso acessando um Entity
bean ou através de sentenças SQL. Um exemplo para um session bean poderia ser o
armazenamento de uma tarefa associada a uma transferência de fundos entre duas
contas bancárias. Este Session bean pode encontrar duas instâncias de um Entity bean
de conta, que foi o exemplo anterior, e subtrair a quantia especificada de uma conta e
adicionar na outra. Iremos dar mais ênfase a estes beans nas sessões posteriores.
Abaixo está uma figura que representa o modelo de funcionamento do entity
bean e do session bean.
CONTAINER EJB
EB 1
APP 1
SB 1
EB 2
SGBD
APP 2
SB 2
APP 3
EB 3
SB 3
EB 4
Modelo Session Bean e Entity Bean 1
20
2. COMO CRIAR UM ENTERPRISE JAVA BEAN
Para implementar um EJB, seja um Entity bean ou um Session Bean, é preciso
definir algumas classes e interfaces, com métodos que todo o bean deve prover, além
de um arquivo de configuração. Iremos descrever um pouco sobre cada uma delas:
2.1 INTERFACE REMOTA
Define os métodos do bean para que a aplicação cliente utilize. Esta interface
herda de javax.ejb.EJBObject e segue regras de interfaces remotas RMI, tais como:
todos os métodos devem lançar a exceção java.RemoteException; os parâmetros e
21
valores de retorno devem ser tipos primitivos da linguagem; objetos serializáveis ou
objetos remotos. As interfaces remotas duplicam todos os métodos da lógica de
negócio que existem no bean. Veja sua ilustração abaixo:
CLIENTE
EJB
InterFace
Home
Enterprise
Java
Bean
InterF ace
R em ota
Interface Remota 1
O conjunto de métodos de negócios disponíveis ao cliente é definido por esta
interface, ela suporta os métodos de negócio do objeto, obtém a interface Home,
remove a instância do enterprise bean e obtém um tratamento de uma instância
enterprise bean.
22
Para ilustrar como exemplo irei mostrar uma Interface Remota para um Entity
Bean que armazena dados de uma conta bancária. Esta interface terá a assinatura dos
métodos de negócio necessários para a execução do comando SQL que será passado.
package bean.entity;
import javax.ejb.*;
import java.rmi.*;
/**
* Interface Remota do Entity Bean
* Toda interface remota deve estender a classe EJBObject
*/
public interface Conta extends EJBObject
{
/* Definição dos métodos implementados pelo Bean,
* onde todos devem lançar a exceção RemoteException.
*/
public void saque(double valor)
throws RemoteException;
public void deposito(double valor)
throws RemoteException;
public double getSaldo()
throws RemoteException;
public double getSaldoDisponivel()
throws RemoteException;
public String getNumero()
throws RemoteException;
public void setNumeroConta( String conta )
throws RemoteException;
public void setSaldo( double valor )
throws RemoteException;
public String getSenha()
throws RemoteException;
23
public void setSenha( String senha )
throws RemoteException;
}
2.2 INTERFACE HOME
Esta Interface possibilita que o cliente tenha uma referência para o bean,
também define os métodos do ciclo de vida de um bean. Ela herda de
Javax.ejb.EJBHome. Através dela é possível que um cliente crie e remova uma
instância de um Enterprise Bean e tenha um tratamento que suporte um mecanismo de
persistência.
Está Interface deve definir alguns métodos para criar o bean:
•
O nome do método deve ser obrigatoriamente "create";
•
O retorno deve ser a interface remota do Bean;
•
O método deve lançar as exceções javax.ejb.CreateException.
A Interface Home para o nosso exemplo será construído da seguinte forma:
24
package bean.entity;
import
import
import
import
javax.ejb.*;
java.rmi.*;
java.util.Collection;
bean.entity.Conta;
/**
* Interface home do Entity Bean
*/
public interface ContaHome extends EJBHome
{
public Conta create(String numero)
throws CreateException, RemoteException;
/**
* Método find para retornar um registro especifico
*/
public Conta findByPrimaryKey(ContaPK pk)
throws FinderException, RemoteException;
/**
* Método find para todos os registros
*/
public Collection findAll ()
throws RemoteException, FinderException;
2.3 CLASSE ENTERPRISE BEAN
É na classe do bean que se encontra a implementação dos métodos de negócio
definidos na interface remota. O container chama essa classe quando o cliente invoca
qualquer um dos métodos especificados.
25
Todo bean deve implementar a interface javax.ejb.EnterpriseBean. Dependendo
do tipo será implementada uma interface específica (javax.ejb.SessionBean ou
Javax.ejb.EntityBean) que herda de Enterprise Bean.
Esta classe deve implementar os métodos de criação e localização listados na
interface home e todos os métodos definidos na interface remota, para cada método
Create listado na interface Home, deve herdar na classe bean a implementação de um
método ejbCreate correspondente.
É importante mencionar que uma das provas que o desenvolvedor do bean não
tem que se preocupar com aspectos ligados a comunicação entre objetos é que o Bean
não deve implementar a interface remota em si, apesar de ter que prover a
implementação dos métodos nela declarados. Quem cria a classe que implementa a
interface remota é o servidor EJB na criação do container e não o desenvolvedor.
Veja exemplo abaixo:
package bean.entity;
import javax.ejb.*;
import java.rmi.*;
26
/**
* Classe Bean do Entity Bean
*/
public class ContaBean implements EntityBean
{
/** Contexto da classe */
// private Context ctx;
//Atributos do bean (são os campos da tabela)
public String numeroConta;
public double saldo;
public String senha;
public ContaPK ejbCreate(String numeroConta)
throws CreateException, RemoteException
{
setNumeroConta( numeroConta );
setSaldo( 0 );
return null;
}
//Métodos declarados na interface do bean
public void saque(double valor)
throws RemoteException
{
if (valor > saldo)
throw new RemoteException("Saldo Insuficiente");
saldo -= valor;
}
public void deposito(double valor)
throws RemoteException
{
if (saldo < 0)
throw new RemoteException("Valor inválido para depósito");
saldo += valor;
}
public double getSaldo()
throws RemoteException
{
return saldo;
}
public double getSaldoDisponivel()
throws RemoteException
{
27
return saldo - 0.38;
}
public String getNumero()
throws RemoteException
{
return numeroConta;
}
public void setNumeroConta( String conta )
throws RemoteException
{
this.numeroConta = conta;
}
public void setSaldo( double valor )
throws RemoteException
{
this.saldo = valor;
}
public String getSenha()
throws RemoteException
{
return senha;
}
public void setSenha( String senha )
throws RemoteException
{
this.senha = senha;
}
public void ejbPostCreate(String conta)
throws RemoteException,CreateException { }
public void unsetEntityContext()
{ }
public void setEntityContext( EntityContext ejb)
public void ejbStore()
{
{ }
public void ejbRemove()
}
{
}
public void ejbPassivate()
{
}
public void ejbLoad()
}
public void ejbActivate()
{
28
{
}
2.4 DEPLOYMENT DESCRIPTOR
É um arquivo XML (Extensible Markup Language) que contém a identificação do
bean e todas as propriedades necessárias durante o seu processamento no servidor.
Eles permitem que certos componentes sejam personalizados sem alterar a classe do
bean ou suas interfaces.
Quando a classe do bean e suas interfaces são modificadas, um deployment
descriptor para o bean é gerado e preenchido com dados sobre o bean. Geralmente,
IDEs (ambientes de desenvolvimento integrado) como o JBuilder da Borland, suportam
o desenvolvimento de Enterprise JavaBeans permitindo a geração do deployment
descriptor utilizando componentes visuais.
Abaixo está um deployment descriptor. Este exemplo contém as definições do
Session Bean, as suas classes Remota, Home e do bean, junto com o tipo do bean que
neste caso será um Stateless ( que será visto na sessão 3.1). As mesmas definições
são aplicadas para o Entity bean só que para eles devem ser declarados todos os
campos da tabela e seus métodos.
29
<?xml version="1.0" encoding="Cp1252"?>
<ejb-jar>
<enterprise-beans>
<session>
<display-name>Processar</display-name>
<ejb-name>ProcessarConta</ejb-name>
<home>mono.ProcessarHome</home>
<remote>mono.Processar</remote>
<ejb-class>mono.ProcessarBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<entity>
<display-name>Recurso</display-name>
<ejb-name>RecursoConta</ejb-name>
<home>mono.RecursoHome</home>
<remote>mono.Recurso</remote>
<ejb-class>mono.RecursoBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>mono.RecursoPk</prim-key-class>
<reentrant>False</reentrant>
<cmp-field>
<field-name>codigo</field-name>
</cmp-field>
<cmp-field>
<field-name>descricao</field-name>
</cmp-field>
<cmp-field>
<field-name>comentario</field-name>
</cmp-field>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<description>Processar</description>
<method>
<ejb-name>ProcessarConta</ejb-name>
<method-name>*</method-name>
</method>
<method>
<ejb-name>RecursoConta</ejb-name>
<method-name>*</method-name>
30
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
2.5 CLASSE DA CHAVE PRIMÁRIA
Esta classe só é usada na construção do Entity bean, nela deve-se definir
também uma classe que contem métodos construtor cujos parâmetros são os atributos
que compõem a chave primária da tabela. Ela será utilizada para identificar uma
determinada instância do bean pelo cliente e servidor. Veja abaixo um exemplo para
esta classe:
package bean.entity;
/**
* Classe com a chave primaria do Entity Bean
*/
public class ContaPK implements java.io.Serializable
{
//Os atributos que compõem a chave devem ser públicos
public String numeroConta;
/**
* Construtor padrão - Obrigatório para implementação CMP
*/
public ContaPK()
{
}
/**
* Construtor
31
*/
public ContaPK(String numeroConta)
{
this.numeroConta = numeroConta;
}
/**
* Redefinição obrigatória do método herdado de Object
*/
public boolean equals (Object pk)
{
if ( pk instanceof ContaPK ) {
ContaPK obj = (ContaPK) pk;
return obj.numeroConta.equals(numeroConta);
}
return false;
}
/**
* Redefinição obrigatória do método herdado de Object
*/
public int hashCode ( )
{
return numeroConta.hashCode();
}
}
32
3. BEANS DE SESSÃO
Um bean de sessão é um objeto usado por um único cliente e não pode ser
compartilhado entre vários. Eles representam uma conversação transitória com um
único cliente e são executados exclusivamente para ele. Os beans de sessão têm vida
relativamente curta, ou seja, sua duração está associada à duração do cliente que os
utiliza. Eles podem ser transacionais, dessa forma permitem a manipulação de dados
de um banco de dados.
3.1 TIPOS DE SESSION BEAN
Existem dois tipos de beans de sessão:
Session Bean Stateful
O session bean stateful possui um estado (atributos do bean que serão
preservados ao longo do seu ciclo de vida). Session beans stateful não representam
33
dados diretamente em um armazenamento persistente, mas eles podem acessar e
atualizar dados do cliente. Como o nome sugere, o tempo de vida do session bean
stateful é o mesmo que o tempo de vida do cliente. Esta característica é útil quando se
quer preservar dados a respeito de um cliente enquanto ele estiver utilizando a
aplicação. Um exemplo prático é o carrinho de compras de uma loja virtual. Para cada
pessoa que visita o site é criado e mantido um carrinho de compras exclusivo, contendo
suas respectivas compras.
As seguintes características auxiliam na decisão de utilizar objetos de negócio
como session beans stateful:
•
Manutenção do estado de um cliente específico.
•
Session beans stateful são projetados para manter o estado de um cliente,
portanto objetos de negócio representando a lógica de negócio do cliente
devem ser modelados como session beans stateful. Já que instâncias de
session beans stateful são presas a um cliente, recursos do sistema utilizados
pelos session beans stateful não podem ser compartilhados por múltiplos
clientes.
•
Representação de objetos não-persistentes.
•
O estado de um session bean stateful não é armazenado persistentemente e
não pode ser recriado depois que a sessão do cliente for finalizada. Portanto,
objetos de negócio que possuem vida relativamente curta e não persistente
34
devem ser modelados como session beans stateful.
•
Representação do fluxo de trabalho entre objetos de negócio.
Os objetos de negócio que gerenciam a interação dos vários objetos de negócio
em um sistema são excelentes candidatos para serem modelados como session beans
stateful. Tais objetos geralmente exibem algumas das características citadas
anteriormente.
Para obter uma melhor performance é utilizado um mecanismo conhecido como
Pool de objetos. Um pool é um repositório de instâncias de objetos que permite a
reutilização dos objetos sem que seja necessária a criação de novas instâncias. Isso é
possível pois nada impede que um session bean stateful, apesar de ser utilizado por um
único cliente em um dado momento, possa ser reutilizado por outro cliente após o
primeiro encerrar sua sessão.
Session Bean Stateless
No session bean stateless não há estado a ser preservado ao longo do seu ciclo
35
de vida. Quando o cliente invoca mais de uma vez métodos de uma mesma referência
de um bean do tipo stateless, é bastante provável que não seja o mesmo bean no
servidor que realizará o processamento em cada método chamado. Como o stateless
não possui estado, não haverá nenhum problema se a mesma instância estiver
respondendo a vários clientes ao mesmo tempo. Essa diferença de tipos existe apenas
para aproveitar melhor a memória da máquina, uma vez que não é necessário ter um
número tão grande de objetos stateless no pool quanto os stateful.
É importante destacar que constitui um erro se a interface home de um bean
stateless possuir um método create com parâmetros, porque não há nenhuma garantia
que esses dados passados serão preservados quando for chamado um método desse
bean criado.
As seguintes características auxiliam na decisão de utilizar objetos de negócio
como session beans stateless:
•
Modelagem de objetos reutilizáveis.
•
Um objeto de negócio que fornece algum serviço genérico para todos os
clientes pode ser modelado como session beans stateless. Tal objeto não
36
necessita manter qualquer informação específica do estado do cliente, assim
a mesma instância do bean pode ser reutilizada para outros clientes.
•
Fornecimento de alta performance.
•
Um session bean stateless pode ser muito eficiente, pois requer poucos
recursos do sistema por não estar preso a nenhum cliente. Com isso,
dependendo do servidor EJB, aplicações que usam session beans stateless
podem ser mais escaláveis que aplicações que utilizam session beans
stateful. Por outro lado, esse benefício pode ser equiparado ao aumento da
complexidade da aplicação cliente que usa session beans stateless, porque o
cliente tem que executar as funções de gerenciamento do estado.
•
Operação sobre múltiplas linhas de cada vez.
•
Um objeto de negócio que manipula múltiplas linhas em uma tabela de banco
de dados e representa uma visão compartilhada dos dados é um session
bean stateless ideal. Já que todos usuários poderiam estar interessados em
tais informações, o session bean stateless que representa isto poderia ser
compartilhado.
•
Fornecimento de visão procedural dos dados .
•
Em uma visão procedural dos dados, métodos do objeto de negócio não
operam sobre variáveis de instância. Em vez disso, eles comportam-se como
procedimentos em uma linguagem procedural.
37
A tabela abaixo ilustra as diferenças entre os dois tipos de Session Beans
Característica
Stateful Session Bean
Stateless Session Bean
•
Não há estado a
ser gerenciado
•
Bean pode sair da
memória sem
•
Gerência de estado
Gerenciado
salvar qualquer
automaticamente pelo
coisa
Container
•
Beans são
intercambiáveis e
podem ser
alocados de um
"pool"
•
•
O cliente tem que
Estado conversacional
Responsabilidades
manter qualquer
pode ser mantido no Bean
estado
•
Performance
•
Extremamente
Mais pesado
lightweight
38
4. BEANS DE ENTIDADE
Um bean de entidade é um objeto de longa duração que pode ser acessado de
uma sessão para outra e permite o compartilhamento por vários clientes. Eles
representam dados de dispositivos de armazenamento persistentes, como um banco de
dados.
Existem várias vantagens em usar entity beans em lugar de acessar o banco de
dados diretamente. Usar entity beans para transformar os dados em objetos fornece ao
desenvolvedor um mecanismo simples para acessar e modificar estes dados. É mais
simples chamar um método membro.setComando() do que executar o comando SQL
39
equivalente. Além disso, transformando os dados em objetos, o software poderá ser
mais reutilizável. Uma vez definido o conceito de um entity bean Cliente, ele pode ser
reaproveitado em várias situações, porém existe uma limitação no que diz respeito à
flexibilidade na manipulação dos dados, pois esta fica restrita aos métodos existentes,
além de serem extremamente pesados já que cuidam da persistência no banco de
dados.
Quando um novo bean é criado, um novo registro é inserido no banco de dados
e uma instância do bean é associada com o registro. Assim, quando o estado do bean
muda, essa mudança é sincronizada com os dados no banco de dados.
4.1 TIPOS DE ENTITY BEAN
CMP (Container - Managed Persistence): para este tipo de entity bean não é
necessário escrever o código para acessar o banco de dados, este fica a critério do
servidor utilizado.
BMP (Bean - Managed Persistence): utilizando este bean o desenvolvedor deve
implementar o acesso ao banco de dados. É necessário definir métodos de localização
e os de alteração dos dados, estes deverão conter comandos SQL através de JDBC.
40
5. COMPARATIVO ENTRE BEANS DE SESSÃO E BEANS DE
ENTIDADES.
Abaixo está uma tabela que mostra em detalhes as características de cada bean
Característica
Session Bean
Entity Bean
41
•
•
BD
Uma conversação
transiente com um cliente
•
Dão uma visão OO de um
•
Representam dados em
Pode ser considerado uma
um banco de dados e os
O que o Bean
extensão do cliente que o
métodos que agem sobre
representa
criou
os dados
•
Pode acessar um banco de
•
Em um SGBDR, cada
dados usando JDBC ou
Bean poderia representar
acessando um Entity Bean
um registro de uma tabela,
por exemplo
•
Igual ao tempo de vida do
cliente. Existe somente
Tempo de vida
•
Persiste tanto quanto os
durante uma sessão
dados do banco de dados
cliente/servidor
(longo espaço de tempo)
(curto espaço de tempo)
•
Representam o estado da
•
Representam dados de um
conversação. Este estado é
banco de dados (colunas
Atributos
mantido entre chamadas a
de uma tabela, por
métodos, mas não depois
exemplo)
que a sessão acaba
42
•
Persistência
•
Gerenciada
O Bean deve gerenciar sua
automaticamente pelo
(além da sessão)
própria persistência
Container
•
•
Acesso compartilhado
entre clientes
Um único Bean por cliente
Compartilhamento
(sem compartilhamento)
•
Container gerencia a
concorrência
•
Identificado usando uma
chave primária
Criação
•
No início de uma sessão
•
A criação de um novo
Bean insere dados num
banco de dados
•
Não sobrevive a um crash
•
Sobrevive a um crash de
Durabilidade
de servidor
servidor
43
6. JDBC (JAVA DATABASE CONNECTIVITY)
JDBC é uma API desenvolvida pela Sun para acesso a SGBD (Sistemas
Gerenciadores de Banco de Dados) relacionais por meios de comando SQL (Structured
Query Language). Esta API é a mesma para qualquer SGBD, fazendo com que as
aplicações necessitem de pouca adaptação para diferentes bancos de dados. Além
disso, a API mantém a independência de plataforma da linguagem Java, rodando em
qualquer sistema operacional e acessando qualquer banco de dados através do SQL.
Estas características são o principal motivo da linguagem Java e do JDBC ter uma
vantagem fundamental sobre outros ambientes de programação de banco de dados.
Existem também drivers ODBC que possuem os mesmos propósitos do JDBC
44
rodando em várias plataformas. Porém, eles são normalmente escritos em C, o que
limita a portabilidade e a auto-instalação dos programas Java, o ODBC tem que ser
instalado e configurado na máquina do cliente o que pode se tornar mais trabalhosa a
tarefa de uma implantação de um sistema. Entretanto, bancos de dados que utilizam
ODBC podem ser utilizados em qualquer aplicação Java via a ponte JDBC-ODBC.
JDBC é uma API que representa uma abordagem robusta e orientada a objetos
para acesso a banco de dados relacionais. A API implementa a maioria das
funcionalidades do ODBC, só que ela foi criada de uma forma consistente em contraste
com a coleção de funções e estruturas complexas do ODBC.
O JDBC é uma solução orientada a objeto que encapsula as funcionalidades aos
banco de dados em um conjunto de classes. Estas classes são utilizadas para
instanciar objetos que são então utilizadas para interagir com o banco e dados. Esta
API fornece uma interação com a linguagem Java através de uma interface natural de
programação.
A figura abaixo representa a arquitetura JDBC:
45
Arquitetura JDBC 1
O Driver Manager é uma classe que seleciona o Driver apropriado para a
conexão com o banco de dados. Ela é responsável pela interface entre a aplicação e os
drivers JDBC, e também exige que os drivers JDBC sejam registrados. Também efetua
a conexão com o banco de dados a partir da seleção de um driver registrado.
Os
Drivers
podem
ser
registrados
e
carregados
dinamicamente
(DriverManager.registerDriver e class.forName ), as querys (consultas) e fetches (
captura do resultado da consulta ) são realizadas diretamente através do driver JDBC.
46
A estrutura de endereçamento é semelhante ao esquema de URLs (Uniform
Resource Locators) por exemplo : jdbc:oracle:thin:@serverhostname:1521:ORCL
Algumas classes API do JDBC são destacadas a seguir:
•
Java.sql.DriverManager: carrega os drivers de acesso a banco de dados e
gerencia as conexões.
•
Java.sql.Connection: representa uma conexão com um banco de dados.
•
Java.sql.Statement: é responsável pela execução de sentenças SQL
durante uma conexão com o banco de dados, que podem ser précompiladas ou mesmo stored procedures.
•
Java.sql.ResultSet: controla a manipulação dos dados resultantes de uma
sentença.
Abaixo estão dois exemplo de uma classe feita para conexão através do JDBC
diretamente, uma executando uma query que retorna parâmetros e a outra executando
um store procedure:
package jdbc;
47
import java.sql.*;
import java.util.*;
public class Pure extends Thread
{
public static void main(String[] args)
{
try
{
// fazendo uma consulta simples passando parâmetros
String driver = "com.inet.tds.TdsDriver";
String url = "jdbc:inetdae7:servLine2";
String user = "usr_servLine";
String pass = "usr_servLine";
String query = "select * from tb_cashStatus where
CP_CE_CD_Agencia = ?";
Class.forName( driver );
Connection con = DriverManager.getConnection(url,user,pass);
PreparedStatement pstm = con.prepareStatement( query );
pstm.setString(1,"15");
ResultSet rs = pstm.executeQuery();
while ( rs.next() )
{
System.out.println( "ag = " + rs.getString( 1 ) );
System.out.println( "ps = " + rs.getString( 2 ) );
System.out.println( "tr = " + rs.getString( 3 ) );
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
package jdbc;
48
import java.sql.*;
import java.util.*;
public class StoredProcedure extends Thread
{
public static void main(String[] args)
{
try
{
// chamando uma stored Procedure
String
String
String
String
driver = "com.inet.tds.TdsDriver";
url = "jdbc:inetdae7:servLine2";
user = "usr_servLine";
pass = "usr_servLine";
Class.forName( driver );
Connection con = DriverManager.getConnection(url,user,pass);
CallableStatement cstm = con.prepareCall( "{ call SP_ALine }" );
cstm.setString(1,"254");
ResultSet rs = cstm.executeQuery();
while ( rs.next() )
{
System.out.println( "ag = " + rs.getString( 1 ) );
System.out.println( "ps = " + rs.getString( 2 ) );
System.out.println( "tr = " + rs.getString( 3 ) );
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
49
6.1 TIPOS DE DRIVERS
Existem quatro tipos de Drivers:
•
Ponte com ODBC: Este já foi mencionado anteriormente, e utiliza uma ponte
JDBC-ODBC para manter compatibilidade com os bancos de dados
existentes do tipo ODBC. Ele requer que o Driver ODBC esteja disponível na
máquina cliente.
•
Acesso ao Driver Nativo: É um driver parcialmente escrito na linguagem de
programação Java e parcialmente em código nativo que se comunica com a
API cliente de um banco de Dados. Quando esse driver é usado, deve-se
instalar algum código específico da plataforma além de uma biblioteca Java.
•
Driver escrito em Java com protocolo de rede: É uma biblioteca cliente
Java pura que usa um protocolo independente de banco de dados para
comunicar pedidos do banco de dados para um componente servidor. A
biblioteca cliente é independente do banco de dados real, simplificando assim
a distribuição.
50
•
Driver escrito em Java com protocolo nativo: É uma biblioteca Java pura
que transforma pedidos em um protocolo específico do banco de dados, para
realizar solicitações.
51
7. SOLUÇÃO PROPOSTA
Foi proposto o desenvolvimento de uma Interface de acesso a banco de dados,
com o objetivo de facilitar as tarefas do desenvolvedor.
Utilizando esta Interface o desenvolvedor possui uma grande flexibilidade nas
suas consultas, ela pode exercer um poder sobre o banco, o mesmo acontece se o
acesso ao banco for diretamente através do JDBC. Porem, existe um diferencial onde o
desenvolvedor não precisa conhecer o banco, já que é o nosso componente que irá
interagir com a API JDBC.
52
O nossa proposta vai parcialmente de encontro com o uso de Entity bean pelo
desenvolvedor já que não é necessário conhecer o banco de dados. A utilização do
Entity Bean, também tem uma série de vantagens, porém como foi mencionado
anteriormente, no capítulo onde se falou do Entity Bean (sessão 4.1), eles não possuem
flexibilidade na manipulação dos dados, além de serem muito pesados, já que são eles
que cuidam da persistência dentro do banco de dados.
Note que o desenvolvimento desta Interface encapsula as vantagens que
existem nos métodos atuais de acesso a banco de dados, herdando o que tem de
melhor no acesso ao banco via JDBC diretamente e na utilização dos Entity bean.
Primeiramente mostrarei um exemplo que ilustra o mecanismo básico para uma
aplicação Java acessar um banco de dados, utilizando a API que foi proposta no nosso
trabalho.
53
Aplicação Java
API DE ACESSO
API JDBC
SGBD
Funcionamento API de Acesso 1
Na figura acima, a aplicação Java corresponde a qualquer aplicativo que irá
utilizar a nossa API de acesso, É na API de acesso que estão englobadas todas as
características do EJB que foram citadas. É através da API JDBC que a API de acesso
irá fazer a conexão com o banco de dados.
O exemplo a seguir mostra mais detalhadamente o funcionamento da API de
acesso.
54
Funcionamento API de Acesso 2
No passo 1, a aplicação obtém uma instância para o Session bean que por sua
vez, através do JDBC no passo 2, obtém a conexão. No passo 3 o banco de dados
retorna um conjunto de linhas com o resultado, no passo 4 o JDBC devolve esse
resultado para a API de acesso que pega esse conjunto de linhas reescreve, armazena
e devolve para a aplicação no passo 5. A API de acesso reescreve o conjunto de linhas
recebidos para evitar que a aplicação faça qualquer acesso ao banco.
55
Abaixo estão dois exemplos de como uma aplicação utiliza para acessar o
banco de dados através da nossa API, o exemplo está executando uma query que
retorna parâmetros e o outro executando um store procedure.
package monografia;
import
import
import
import
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
monografia.ComandoSql;
monografia.ComandoSqlHome;
public class TestaProcedure
{
public static void main(String[] args)
{
try
{
InitialContext jndiContext = new InitialContext();
// Pegando
Object ref
reference para o Bean ComandoSql
= jndiContext.lookup("ComandoSql");
// Pegando reference para a Interface Home do Bean
ComandoSqlHome home = (ComandoSqlHome)
PortableRemoteObject.narrow(ref, ComandoSqlHome.class);
// Criando o Objeto para o Bean ComandoSql
ComandoSql comandoSql = home.create("Oracle");
Resultado r = comandoSql.executeStoredProcedure("{ call SP_Aline
}");
while (r.temMaisLinhas())
{
System.out.println( r.getString("nome"));
}
}
catch(Exception e)
56
{
e.printStackTrace();
}
}
package monografia;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import monografia.ComandoSql;
import monografia.ComandoSqlHome;
public class ComandoSqlClient
{
public static void main(String[] args)
{
try
{
// Pegando contexto
InitialContext jndiContext = new InitialContext();
// Pegando
Object ref
reference para o Bean ComandoSql
= jndiContext.lookup("ComandoSql");
// Pegando reference para a Interface Home do Bean
ComandoSqlHome home = (ComandoSqlHome)
PortableRemoteObject.narrow(ref, ComandoSqlHome.class);
// Criando o Objeto para o Bean ComandoSql
ComandoSql comandoSql = home.create("Oracle");
comandoSql.setClausula("select * from Aluno where matricula =
:matricula");
comandoSql.setParamametro("matricula","5000");
Resultado r = comandoSql.executeQuery();
while (r.temMaisLinhas())
{
System.out.println( r.getString("nome"));
57
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
58
8. JSP ( JAVA SERVER PAGE )
Para demonstrar as classes desenvolvidas neste trabalho iremos usar o JSP que
é uma tecnologia desenvolvida pela Sun baseada em servlets. Servlets são programas
Java executados dentro de um servidor web, atendendo as requisições por informação
na forma de páginas HTML (Hyper Text Markup Language). JSP são páginas HTML
que incluem códigos Java e outras Tags específicas.
Veja abaixo um exemplo de um JSP:
<html>
<head>
<title>Exemplo JSP</title>
59
</head>
<body>
<%
String x= “ Ola mundo !“
%>
<%=x%>
</body>
<html>
Desta maneira as partes estáticas da página não precisam ser geradas por
println. Elas são fixadas na próxima página. A parte dinâmica é gerada pelo código JSP,
desta maneira a parte estática pode ser gerada por pessoas que não entendem de
Java.
A primeira vez que uma página JSP é carregada pelo container JSP o código
Java é compilado gerando um Servlet que é executado, gerando uma página HTML que
é enviada para o navegador.
60
9. JBOSS
Existem vários tipos de servidores EJB a venda no mercado, como o WebLogic
da empresa chamada BEA ou o WebSphere
da
IBM. Eles não são iguais, mas
seguem determinados padrões definidos pela Sun. Estes produtos custam na faixa de
50 a 300 mil reais, mas para nossa facilidade existe o JBoss que talvez não tenha
recursos tão sofisticados como os citados acima mas é gratuito e pode ser baixado pela
Internet.
Além do custo, o JBoss é um servidor que exige pouco espaço em disco e roda
muito bem em uma máquina de 64MB, apesar dele não ser um servidor web ele possui
61
pacotes que incluem Tomcat ( que é um servidor de páginas com as características de
interagir com os servlets e JSP), a sua instalação e configuração é rápida e prática. No
apêndice 1 podemos encontrar como é realizada a instalação do JBoss.
62
10. CONCLUSÃO
É notória a evolução da informática nos últimos anos, a forma de como os
sistemas são desenvolvidos sofreu uma enorme mudança, tornando muitas vezes o
desenvolvimento de aplicações mais complexos para o desenvolvedor. Hoje existe uma
necessidade de se trabalhar com uma arquitetura em n-camadas e para isso foi
desenvolvida a tecnologia Enterprise JavaBean , porém muita coisa precisa ser feita
para melhorar este trabalho, principalmente com relação ao acesso a dados.
Este projeto facilita o desenvolvimento de aplicações usando EJB, construindo
uma interface padronizada e fácil de ser utilizada provendo ao programador recursos na
63
implementação de suas aplicações, diminuindo o tempo e o custo das mesmas, pois o
desenvolvedor se concentra nos seus objetivos específicos sem ter que ficar
procurando constantemente a API do Java para encontrar os comandos para acessar o
banco de dados.
Foi mostrado neste trabalho a importância da tecnologia Enterprise JavaBeans,
que surgiu para facilitar o desenvolvimento de sistemas distribuídos, além de ter sido
explanado várias características fundamentais desta tecnologia, pois foi com base nela
que desenvolvemos a nossa API de acesso.
Foram vistas também as dificuldades existentes para acessar o banco de dados
via JDBC e as vantagens que a nossa API fornece para os desenvolvedores.
64
11. APÊNDICE 1 – INSTALAÇÃO DO JBOSS.
A instalação do servidor de aplicação JBoss é muito simples. Após obter uma
cópia dos arquivos binários no site
http://www.jboss.org deve-se descompactar os
arquivos em um diretório.
Em seguida é necessário configurar a conexão com o SGBD. Para isso teremos
que copiar o driver JDBC para diretório lib\ext do diretório da distribuição do JBoss. No
nosso exemplo vamos usar o banco de dados Oracle.
O arquivo Jboss.jcml deve ser editado para informar alguns dados sobre o SGBD
a ser utilizado. A primeira coisa a ser feita é informar o nome completo do Driver JDBC
para que o mesmo possa ser carregado. Veja a seguir como fazê-lo:
<mbean code="org.jboss.jdbc.JdbcProvider"
name="DefaultDomain:service=JdbcProvider">
<attribute
name="Drivers">org.hsql.jdbcDriver,org.enhydra.instantdb.jdbc.idb
Driver</attribute>
</mbean>
65
No nosso caso, como iremos usar o banco de dados Oracle, é necessário que
acrescentemos o nome do driver, como é mostrado no exemplo abaixo:
< mbean code="org.jboss.jdbc.JdbcProvider"
name="DefaultDomain:service=JdbcProvider">
<attribute
name="Drivers">oracle.jdbc.driver.OracleDriver</attribu>
</mbean>
Também precisamos informar a URL do SGBD, o nome do usuário e a senha
que será utilizada, como mostrado no exemplo abaixo:
<mbean code="org.jboss.jdbc.XADataSourceLoader"
name="DefaultDomain:service=XADataSource,name=OracleDB">
<attribute name="PoolName">OracleDB</attribute>
<attribute
name="DataSourceClass">org.jboss.pool.jdbc.xa.wrapper.XADataSourc
eImpl</attribute>[JBoss 2.4]
<attribute
name="URL">jdbc:oracle:thin:@serverhostname:1521:ORCL</attribute>
<attribute name="JDBCUser">scott</attribute>
<attribute name="Password">tiger</attribute>
</mbean>
Assim que iniciarmos o JBoss, saberemos que o Driver foi carregado se aparecer
a seguinte mensagem na tela de output do servidor de aplicação:
66
[JDBC] Loaded JDBC-driver:oracle.jdbc.driver.OracleDriver
Caso o Driver não tenha sido carregado irá aparecer a seguinte mensagem:
[JDBC] Could not load driver: oracle.jdbc.driver.OracleDriver
67
12. APÊNDICE 2 – CLASSES DA API DE ACESSO
/**
* @author Aline Souto Bezerra
* [email protected]
*/
package monografia;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
/**
* Implementação da Inteface home do Session Bean
* Está Interface possibilita que o cliente tenha uma referência
para o bean
*/
public interface ComandoSqlHome extends EJBHome
{
public ComandoSql create(String poolName) throws
RemoteException, CreateException;
}
68
/**
* @author Aline Souto Bezerra
* [email protected]
*/
package monografia;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.sql.*;
/**
* Implementação da Interface remota
* Está classe Define os métodos do bean para que a aplicação
cliente
* a utilize
*/
public interface ComandoSql extends EJBObject
{
public Resultado executeQuery() throws RemoteException;
public void setClausula(String str);
public int executeUpdate();
public void setParametro(String paramName, Object value);
public int executarProcedimento() throws RemoteException;
public Resultado executarFuncao() throws RemoteException;
public int executeUpdateProcedure() throws RemoteException;
}
69
/**
* @author Aline Souto Bezerra *
*
[email protected]
*/
package monografia;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.*;
import javax.sql.*;
import java.sql.*;
import java.util.HashMap;
/**
* Interface do Session bean que serve para executar sentenças SQL
* (consultas e atualizações) genéricas.
*
*/
public class ComandoSqlBean implements SessionBean
{
protected String
clausula;
protected HashMap
params;
protected String poolName;
/**
* Este método cria a conexão com o banco.
* @param poolName - nome do pool que é usado no banco.
*/
public void ejbCreate(String poolName)
{
params = new HashMap();
this.poolName = poolName;
}
/**
* Este método é usado para setar os parâmetros
* @param paramName - é o nome do campo da tabela
* @param value valor do campo
* @exception RemoteException - Exceção lançada caso o
* parametro seja passado incorretamente
*/
public void setParametro(String paramName, Object value)
throws RemoteException
{
paramName = paramName.toLowerCase();
if (clausula.toLowerCase().indexOf(":" + paramName) < 0)
throw new IllegalArgumentException(paramName);
if (value == null)
70
throw new IllegalArgumentException("Valor nulo para " + paramName);
params.put(paramName, value);
}
private String getComandoSql(HashMap params)
{
String newComando = clausula;
int aux = newComando.indexOf(':');
while (aux > 0)
{
int aux1 = aux;
while (aux1 < newComando.length() && newComando.charAt(aux1) != ' ' &&
newComando.charAt(aux1) != ',' && newComando.charAt(aux1) != '\'' &&
newComando.charAt(aux1) != '%' && newComando.charAt(aux1) != ')')
aux1++;
String paramName = newComando.substring(aux + 1, aux1);
Object paramValue = params.get(paramName.toLowerCase());
if (paramValue == null)
paramValue = ":" + paramName;
newComando = newComando.substring(0, aux) + paramValue.toString() +
newComando.substring(aux1);
aux += paramValue.toString().length();
aux = newComando.indexOf(':', aux);
}
return newComando;
}
/**
* Este método obtem o Comando SQL que vai ser executado.
* param str - sentença do comando que será executado.
*/
public void setClausula(String str)
{
clausula = str;
}
/**
* Executa uma sentença SQL de consulta retornando o resultado da consulta.
* @return Resultado conjunto de linhas retornadas do BD
* @exception RemoteException Ocorre quando o acesso ao banco de dados
* não pode ser feito ou se a senetença está incorreta.
*/
public Resultado executeQuery()
throws RemoteException
{
try {
Connection con = getConexao();
Resultado r = new Resultado(con.createStatement().executeQuery(
getComandoSql(params) ));
con.close();
return r;
}
catch (Exception ex)
{
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
71
}
}
/**
* Executa uma sentença SQL de insert ou update.
* @return int - número de linhas afetadas no banco de dados
* @exception RemoteException Ocorre quando o acesso ao banco de dados
* não pode ser feito ou se a senetença está incorreta.
*/
public int executeUpdate()
throws RemoteException
{
try {
Connection con = getConexao();
int cont = con.createStatement().executeUpdate( clausula );
con.commit();
con.close();
return cont;
}
catch (Exception ex) {
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
}
}
/**
* Executa uma sentença SQL de alteração.
* @return int - número de linhas afetadas no banco de dados
* @exception RemoteException Ocorre quando o acesso ao banco de dados
* não pode ser feito ou se a senetença está incorreta.
*/
public int executeUpdateProcedure()
throws RemoteException
{
try {
Connection con = getConexao();
clausula = "{ call " + clausula + " }" ;
System.out.println(clausula);
int cont = con.prepareCall(getComandoSql(params)).executeUpdate();
con.close();
return cont;
}
catch (Exception ex) {
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
}
}
public int executarProcedimento()
throws RemoteException
{
try {
Connection con = getConexao();
clausula = "{? = call " + clausula + " }" ;
CallableStatement stm = con.prepareCall(clausula);
72
stm.registerOutParameter(1,Types.NUMERIC) ;
stm.executeQuery();
int i = stm.getInt(1);
con.close();
return i;
}
catch (Exception ex)
{
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
}
}
public Resultado executarFuncao()
throws RemoteException
{
try {
Connection con = getConexao();
int i =0;
String retorno = new String (" ");
i = clausula.indexOf(' ');
retorno = clausula.substring(0,i);
int aux = clausula.length();
clausula = clausula.substring(i,aux);
clausula = "{ " + retorno + " = call " + clausula + " }"
Resultado r = new Resultado(
con.prepareCall(getComandoSql(params)).executeQuery() );
con.close();
return r;
}
catch (Exception ex)
{
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
}
}
;
private Connection getConexao() throws Exception
{
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/" + poolName);
return ds.getConnection();
}
public
public
public
public
void
void
void
void
ejbRemove(){}
ejbActivate(){}
ejbPassivate(){}
setSessionContext(SessionContext sc){}
}
73
/**
* @author Aline Souto Bezerra *
*
[email protected]
*/
package monografia;
import
import
import
import
import
import
import
import
import
java.util.ArrayList;
java.util.Collection;
java.sql.ResultSet;
java.sql.ResultSetMetaData;
java.sql.Types;
java.sql.Date;
java.sql.Time;
java.sql.Timestamp;
java.rmi.RemoteException;
/**
* Resultado
* Classe utilizada para encapsular o resultado do banco de
dados, nela é
* criado um array e cada índice do array aponta para um outro
array,
* o array de índice 0 representa o cabeçalho da tabela e os
demais representam
* uma linha de uma coluna.
*
*/
public class Resultado implements java.io.Serializable
{
protected ArrayList linhas;
protected int posicao;
/**
* Construtor padrão da classe Resultado.
* Na construção de um objeto Resultado o ResultSet é percorrido
e todos os dados são
* passados para um ArrayList.
* @param ResultSet - Usado para passar as linhas do resultado
74
*/
public Resultado(ResultSet rs)
throws RemoteException
{
try {
// cabecalho - nome das colunas
linhas = new ArrayList();
ResultSetMetaData rsmd = rs.getMetaData();
int qtdColunas = rsmd.getColumnCount();
ArrayList cabecalho = new ArrayList();
for (int i = 1; i <= qtdColunas; i++)
{
cabecalho.add( rsmd.getColumnName( i ).toLowerCase() );
}
posicao = 0;
linhas.add(cabecalho);
// dados
while ( rs.next() )
{
ArrayList novaLinha = new ArrayList();
for (int i = 1; i <= qtdColunas; i++)
{
novaLinha.add( rs.getObject( i ) );
}
linhas.add( novaLinha );
}
}
catch (Exception ex) {
ex.printStackTrace();
throw new RemoteException( ex.getMessage() );
}
}
/**
* Método usado para saber se existe mais inhas na tabela
retornando um valor
* falso ou verdadeiro.
75
* @return boolean - retorna verdade até existir mais linhas.
*/
public boolean temMaisLinhas()
{
return ++posicao < linhas.size();
}
/**
* getString - Este metodo é utilizado para se obter uma coluna
do conjunto
* resultado na forma de string. Independente de qual seja o
tipo do dado no
* SGBD ele será convertido para uma string.
* @param indice - Indice usado para localizar a coluna
* @return string - string representando a coluna
* @exception RemoteException - Exceção lançada caso o índice
esteja fora dos limites
*/
public String getString(int indice)
throws RemoteException
{
validaIndice( indice );
Object str = ((ArrayList)linhas.get(posicao)).get( indice );
if( str == null )
return null;
if( str instanceof String )
return ( String ) str;
else
return str.toString();
}
/**
* getInteger - Este metodo é utilizado para se obter uma coluna
do conjunto
* resultado na forma de Inteiro. Independente de qual seja o
tipo do dado no
* SGBD ele será convertido para um Inteiro.
* @param indice - Indice usado para localizar a coluna
* @return Inteiro - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o índice
esteja fora dos limites
*/
public Integer getInteger(int indice)
throws RemoteException
76
{
validaIndice( indice );
Object value = ((ArrayList)linhas.get(posicao)).get( indice
);
if( value == null )
return null;
if( value instanceof Integer )
return ( Integer ) value;
if( value instanceof Number )
return new Integer( ( ( Number )value ).intValue() );
else
return new Integer( value.toString() );
}
/**
* getBoolean - Este metodo é utilizado para se obter uma coluna
do conjunto
* resultado na forma de Boolean. Independente de qual seja o
tipo do dado no
* SGBD ele será convertido para Boolean.
* @param indice - Indice usado para localizar a coluna
* @return Boolean - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o índice
esteja fora dos limites
*/
public Boolean getBoolean(int indice)
throws RemoteException
{
validaIndice( indice );
Object value = ((ArrayList)linhas.get(posicao)).get( indice
);
if( value == null )
return null;
if( value instanceof Boolean )
return ( Boolean ) value;
if( value instanceof Number )
return new Boolean( ( ( Number )value ).intValue() != 0 );
else
return new Boolean( value.toString() );
}
/**
* getDate - Este metodo é utilizado para se obter uma coluna do
77
conjunto
* resultado na forma de Data. Independente de qual seja o tipo
do dado no
* SGBD ele será convertido para Data.
* @param indice - Indice usado para localizar a coluna
* @return Date - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o índice
esteja fora dos limites
*/
public Date getDate(int indice)
throws RemoteException
{
validaIndice( indice );
Object value = ((ArrayList)linhas.get(posicao)).get( indice
);
if( value == null )
return null;
if( value instanceof Date )
return ( Date ) value;
if( value instanceof Number )
return new Date( ( ( Number )value ).longValue() );
if( value instanceof Time )
return new Date( ( ( Time )value ).getTime() );
if( value instanceof Timestamp )
return new Date( ( ( Timestamp )value ).getTime() );
else
try
{
return new
Date(java.text.DateFormat.getInstance().parse(value.toString()).g
etTime());
}
catch( java.text.ParseException e )
{
throw new RuntimeException( "Tipo inesperado na conversão
para Date: " + value.getClass().getName() );
}
}
/**
* getString - Este metodo é utilizado para se obter o índice da
coluna que se
* deseja obter o conjunto do resultado, o nome da coluna é
passado como
* parâmetro
78
* @param nomeColuna - Nome da coluna usado para localizar o
índice da coluna
* que se deseja obter o conjunto de resultados
* @return String - String retornando a coluna
* @exception RemoteException - Exceção lançada caso o nome da
coluna esteja
* inválido.
*/
public String getString(String nomeColuna)
throws RemoteException
{
try {
return getString(
((ArrayList)linhas.get(0)).indexOf(nomeColuna.toLowerCase()) );
}
catch (Exception e)
{
e.printStackTrace();
throw new RemoteException("Nome de coluna invalido.");
}
}
/**
* getInteger - Este metodo é utilizado para se obter o índice
da coluna que se
* deseja obter o conjunto do resultado, o nome da coluna é
passado como
* parâmetro
* @param nomeColuna - Nome da coluna usado para localizar o
índice da coluna
* que se deseja obter o conjunto de resultados
* @return Integer - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o nome da
coluna esteja
* inválido.
*/
public Integer getInteger(String nomeColuna)
throws RemoteException
{
try {
return getInteger(
((ArrayList)linhas.get(0)).indexOf(nomeColuna.toLowerCase()) );
}
79
catch (Exception e)
{
e.printStackTrace();
throw new RemoteException("Nome de coluna invalido.");
}
}
/**
* getBoolean - Este metodo é utilizado para se obter o índice
da coluna que se
* deseja obter o conjunto do resultado, o nome da coluna é
passado como
* parâmetro
* @param nomeColuna - Nome da coluna usado para localizar o
índice da coluna
* que se deseja obter o conjunto de resultados
* @return Boolean - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o nome da
coluna esteja
* inválido.
*/
public Boolean getBoolean(String nomeColuna)
throws RemoteException
{
try {
return getBoolean(
((ArrayList)linhas.get(0)).indexOf(nomeColuna.toLowerCase()) );
}
catch (Exception e)
{
e.printStackTrace();
throw new RemoteException("Nome de coluna invalido.");
}
}
/**
* getDate - Este metodo é utilizado para se obter o índice da
coluna que se
* deseja obter o conjunto do resultado, o nome da coluna é
passado como
* parâmetro
* @param nomeColuna - Nome da coluna usado para localizar o
índice da coluna
80
* que se deseja obter o conjunto de resultados
* @return Date - valor encontrado na coluna
* @exception RemoteException - Exceção lançada caso o nome da
coluna esteja
* inválido.
*/
public Date getDate(String nomeColuna)
throws RemoteException
{
try {
return getDate(
((ArrayList)linhas.get(0)).indexOf(nomeColuna.toLowerCase()) );
}
catch (Exception e)
{
e.printStackTrace();
throw new RemoteException("Nome de coluna invalido.");
}
}
public Collection nomeDasColunas()
{
return (ArrayList)linhas.get(0);
}
public int quantidadeLinhas()
{
return linhas.size() - 1 ;
}
public int quantidadeColunas()
{
return ((ArrayList)linhas.get(0)).size();
}
protected void validaIndice(int indice) throws RemoteException
{
if ( posicao < 0 || posicao >= linhas.size() )
throw new RemoteException("Linha inválida");
if ( indice < 0 || indice >=
((ArrayList)linhas.get(0)).size() )
throw new RemoteException("Indice invalido. " + indice);
}
}
81
13. REFERÊNCIAS BIBLIOGRÁFICAS
MONSON-HAEFEL, Richard. Enterprise JavaBeansTM. 2.ed. Sebastopol, CA, EUA: O’Reilly
& Associates, Inc, 2000. 471p.
KASSEN- Nicolas. Designing Enterprise Applications with the JavaTM Platform, Enterprise
Edition. Addison Wesley,2000.113p.
SILBERSCHTZ, Abrahan; KORTH, Henry; SUDARSHAN, S. Sistemas de Banco de dados,:
Makron Books, São Paulo, 1999.460p.
SZYPERSKI, Clemens. Component Software :Addison-Wesley, Great Britain, 1999.
Enterprise JavaBeansTM Technology. Encontrado em:
http://java.sun.com/products/ejb
JDBC Technology. Encontrado em:
http://java.sun.com/products/jdbc/
Enterprise JavaBeans Tutorial. Encontrado em:
http://developer.java.sun.com/developer/onlinetraining/beans/ejbtutorial index.html
82
JBoss 2.2+ Documentation. Encontrado em:
http://www.jboss.org/online-manual/HTML/index.html
Interface entre Java e Bancos de dados relacionais. Encontrado em:
http://www.dca.fee.unicamp.br/courses/PooJava/javadb/jdbc.html
Servlets e Enterprise Javabeans. Encontrado em:
http://www.dmu.com/ejw1.html
JAVA - Integrando Banco de Dados Via JDBC. Encontrado em:
http://www.pr.gov.br/celepar/celepar/batebyte/edicoes/1996/bb58/java.htm
83
Download