Escolar Documentos
Profissional Documentos
Cultura Documentos
Utilização de tecnologias JPA (Java Persistence API) e EJB (Enterprise JavaBeans), Descrição
das tecnologias e sua organização em uma arquitetura MVC (Model, View e Controller),
Construção de um exemplo completo observando o padrão Front Controller, com utilização das
tecnologias estudadas.
PROPÓSITO
Ao final dos estudos, o aluno estará apto a construir sistemas na arquitetura MVC, com base
nas tecnologias JPA e JEE, adotando interface Java para Web. O conhecimento adquirido será
de grande utilidade para a inserção do aluno no mercado corporativo, tendo como base
arquiteturas e componentes robustos. Também serão observados os métodos de
automatização do NetBeans, visando a obter maior produtividade.
PREPARAÇÃO
Antes de iniciar o conteúdo deste tema, é necessário configurar o ambiente, com a instalação
do JDK e Apache NetBeans, definindo a plataforma de desenvolvimento.
Sugere-se configurar a porta do servidor Tomcat como 8084, de forma a evitar conflitos com o
GlassFish na porta 8080.
OBJETIVOS
MÓDULO 1
MÓDULO 2
MÓDULO 3
MÓDULO 4
Empregar padrão Front Controller em sistema MVC, com interface Java Web
INTRODUÇÃO
A tecnologia JPA (Java Persistence API), para o mapeamento objeto-relacional, e o uso de
componentes do tipo EJB (Enterprise Java Bean), elemento central do JEE (Java Enterprise
Edition), para implementar regras de negócio, são conhecimentos essenciais para o
profissional de desenvolvimento Web.
MÓDULO 1
MAPEAMENTO OBJETO-RELACIONAL
Nos bancos de dados relacionais, temos uma estrutura baseada em tabelas, que comportam
valores em registros, e que se relacionam a partir de campos identificadores ou chaves
primárias. A manutenção dos relacionamentos, por sua vez, é implementada através de chaves
estrangeiras e estruturas de índices.
Fonte: Shutterstock
Temos duas filosofias distintas, com peculiaridades inerentes a cada ambiente de execução, e
como o ambiente de programação deve lidar com toda a lógica, ocorre um esforço natural para
minimizar o uso de tabelas e registros, com a substituição por classes e objetos. A abordagem
fica clara quando utilizamos o padrão de desenvolvimento DAO (Data Access Object) , onde
temos uma classe de entidade, e as consultas e operações sobre o banco de dados são
concentradas em uma classe gestora, com a conversão para objetos e coleções, a partir da
qual não utilizamos mais o enfoque relacional no sistema.
Fonte: O autor
Com base nas configurações, indicando qual atributo da classe é refletido em determinado
campo do registro, além da especificação de chaves e relacionamentos, o framework de
persistência cria todos os comandos SQL (Structured Query Language) necessários, de
modo transparente, e transmite os comandos gerados para o banco de dados através de uma
biblioteca de middleware.
SAIBA MAIS
No ambiente Java, os primeiros exemplos de tecnologias para ORM que obtiveram sucesso
foram os Entity Beans e o Hibernate. As duas tecnologias adotaram o mapeamento baseado
em XML, mas utilizaram padrões funcionais bastante distintos.
Os Entity Beans fazem parte do J2EE (Java 2 Enterprise Edition) , e trabalham de acordo
com o padrão Active Record, no qual cada leitura de propriedade equivale a um comando de
seleção no banco de dados, a alocação de um objeto inicia um comando de inserção, e quando
alteramos o valor da propriedade, temos uma alteração no registro. Podemos chegar
facilmente à conclusão de que o padrão é ineficiente, pois temos uma grande demanda de
comandos SQL desnecessários, que poderiam ser executados em blocos.
No fragmento de código, temos o início da definição de um Entity Bean, onde o objeto concreto
é gerado pelo servidor de aplicativos, e as classes de entidade apresentam apenas as
propriedades, definidas a partir de getters e setters abstratos, além de alguns métodos de
gerência do ciclo de vida, aqui omitidos. O mapeamento do Entity Bean para a tabela deve ser
feito com base na sintaxe XML, como no trecho apresentado a seguir, para o servidor JBoss.
Já no framework Hibernate, temos o padrão DAO, de forma implícita, com os comandos sendo
gerados a partir dos métodos de um gestor de persistência, com base no conjunto de
elementos de mapeamento, e os dados presentes nas entidades.
public class Produto {
public Produto(){}
As entidades, para o Hibernate, são apenas classes comuns, sem métodos de negócios, com
um conjunto de propriedades e um construtor padrão. Todo o mapeamento deve ser efetuado
através da sintaxe XML, como no trecho apresentado a seguir.
Um dos maiores avanços do Java foi a criação do JPA (Java Persistence API) , pois permitiu
unificar os frameworks de persistência em uma arquitetura padrão, com apenas um arquivo de
configuração, o persistence.xml. Não é apenas uma biblioteca, mas uma API que define a
interface comum, configurável através de anotações, que deve ser seguida pelos frameworks
de persistência da plataforma Java, como Hibernate, Eclipse Link e Oracle Toplink.
Fonte: Shutterstock
Trabalhando no mesmo estilo do Hibernate, através do JPA temos um padrão DAO implícito,
trazendo grande eficiência nas tarefas de persistência, o que ainda é otimizado com base em
recursos de cache de entidades em memória. Não é por menos que, na plataforma JEE atual,
temos a substituição dos Entity Beans, presentes no J2EE, pelo JPA.
Da mesma forma que no Hibernate clássico, para definir uma entidade JPA devemos criar um
POJO (Plain Old Java Object), ou seja, uma classe sem métodos de negócios, mas com
atributos definidos de forma privada e métodos de acesso públicos, além de um construtor
padrão e alguns métodos utilitários, como hash. A entidade definida deve receber anotações,
que serão responsáveis pelo mapeamento efetuado entre a classe e a tabela, ou seja, o
mapeamento objeto-relacional.
@Entity
@Table(name = "PRODUTO")
@NamedQueries({
@NamedQuery(name = "Produto.findAll",
@Id
@Basic(optional = false)
@Column(name = "COD_PRODUTO")
public Produto() {
this.codigo = codigo;
}
@Override
int hash = 0;
return hash;
@Override
return false;
this.codigo.equals(other.codigo);
@Override
A anotação Entity define a classe Produto como uma entidade para o JPA, enquanto Table
especifica a tabela para a qual será mapeada no banco de dados, com base no parâmetro
name. Temos ainda uma anotação NamedQueries, agrupando um conjunto de anotações
NamedQuery, as quais são utilizadas para criar consultas através de uma sintaxe própria do
JPA, denominada JPQL (Java Persistence Query Language).
DICA
Após configurar a tabela que será representada pela entidade, precisamos completar as
informações de mapeamento ao nível dos atributos, com o uso da anotação Column e o
nome do campo definido no parâmetro name. Com o uso de Id definimos qual atributo
representará a chave primária, e tornamos um atributo obrigatório através da anotação Basic,
tendo o parâmetro optional configurado com valor false.
Anotação Utilização
As entidades JPA devem conter dois construtores, sendo um vazio e outro baseado na chave
primária, como podemos verificar no código de Produto, além dos métodos equals e
hashCode.
Para a entidade Produto, os dois métodos utilitários são baseados no atributo codigo, o que é
natural, já que ele recebe o valor da chave primária, tendo a capacidade de individualizar a
instância da entidade em meio a uma coleção.
Além dos elementos descritos até aqui, utilizados na definição da estrutura de nossa entidade,
precisamos do atributo serialVersionUID, referente à versão da classe, algo que será
relevante para os processos de migração da base de dados. Temos ainda uma implementação
de toString, que não é obrigatória, mas nos dá controle sobre a representação da entidade
como texto em alguns componentes visuais, ou na impressão para a linha de comando.
Além das anotações nas entidades, precisamos de um arquivo de configuração, com o nome
persistence.xml, onde serão definidos os aspectos gerais da conexão com o banco de dados.
O arquivo deve ser criado na pasta META-INF, e os parâmetros podem incluir elementos como
a classe de conexão JDBC (Java Database Connectivity) ou o pool de conexões do servidor,
estando sempre presente a especificação do framework de persistência que será utilizado.
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" >
transaction-type="RESOURCE_LOCAL">
org.eclipse.persistence.jpa.PersistenceProvider;
value="jdbc:derby://localhost:1527/bancoJPA"/>
value="org.apache.derby.jdbc.ClientDriver"/>
value="bancoJPA"/>
value="bancoJPA"/>
O controle transacional pode ocorrer a partir de um gestor próprio, para uso no ambiente JSE
(Java Standard Edition) ou pelo JEE (Java Enterprise Edition) no modelo não gerenciado, mas
também permite o modo gerenciado, através da integração com JTA (Java Transaction API).
Tipo de Transação
RESOURCE_LOCAL
JTA
RESOURCE_LOCAL
JTA
Ativa a integração com JTA, para utilizar o gerenciamento de transações pelo JEE.
Em seguida, é definido o provedor de persistência no elemento provider, em nosso caso a
classe PersistenceProvider do Eclipse Link. As classes de entidade englobadas devem ser
especificadas nos elementos class, para o modelo de acesso local, e as propriedades da
conexão são definidas no grupo properties, o que inclui o driver JDBC utilizado, a URL de
conexão, bem como o usuário e a senha do banco de dados.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
lista.forEach((e) -> {
System.out.println(e.getNome());
});
em.close();
PASSO 1
PASSO 2
PASSO 3
PASSO 1
PASSO 2
Com o gestor instanciado, obtemos um objeto do tipo Query, com a chamada para
createNamedQuery, tendo como base uma anotação do tipo NamedQuery com name
valendo Produto.findAll, a qual está anexada à classe Produto. As consultas nomeadas
devem apresentar nomes diferentes, pois a busca é feita em todas as entidades, o que
poderia gerar dualidades durante a execução.
PASSO 3
ATENÇÃO
Após receber a coleção de produtos, nós podemos percorrê-la através de um loop no estilo
foreach, ou operador funcional equivalente, com a impressão do nome para cada produto
encontrado.
Note que o JPA não elimina o uso de JDBC, pois o que temos é a geração dos comandos
SQL, de forma automatizada, a partir das informações oferecidas pelas anotações.
Agora podemos verificar como é feita a inclusão de um produto em nossa base de dados.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
}catch(Exception e){
em.getTransaction().rollback();
}finally{
em.close();
Devido ao fato de uma inclusão poder gerar erros durante a execução, o ideal é que seja
efetuada dentro de uma transação. Na verdade, qualquer manipulação de dados efetuada a
partir do JPA irá exigir uma transação, podendo ser local ou via JTA.
Após obtermos uma instância de EntityManager na variável em, é definido um bloco de código
protegido, onde a transação é iniciada com begin, seguida da inclusão do produto na base de
dados através do método persist, e temos a confirmação da transação com o uso de commit.
Caso ocorra um erro, todas as alterações efetuadas são desfeitas com o uso de rollback, e
ainda temos um trecho finally, onde fechamos a comunicação com o uso de close,
independente da ocorrência de erros.
Para efetuar a alteração dos dados de um registro, temos um processo muito similar, trocando
apenas o método persist por merge.
public static void alterar(Produto p){
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.merge(p);
em.getTransaction().commit();
}catch(Exception e){
em.getTransaction().rollback();
}finally{
em.close();
Na exclusão de um registro, inicialmente deve ser feita a busca, com base na classe da
entidade e o valor da chave primária, através do método find. Será retornada uma entidade,
como resultado da consulta, e nós a utilizaremos como parâmetro para a chamada ao método
remove, efetuando a exclusão no banco de dados.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.remove(em.find(Produto.class, codigo));
em.getTransaction().commit();
}catch(Exception e){
em.getTransaction().rollback();
}finally{
em.close();
EXECUÇÃO DO APLICATIVO
Quando executamos um aplicativo com elementos JPA no servidor, temos todas as bibliotecas
necessárias disponíveis, mas a execução local irá necessitar da inclusão de algumas
bibliotecas ao projeto.
Fonte: Shutterstock
Trabalharemos com o banco de dados Derby, também chamado de Java DB, exigindo a
inclusão da biblioteca JDBC correta. É interessante observar que o Derby é um banco de
dados implementado em Java, que faz parte da distribuição padrão da plataforma, e que pode
ser executado de forma local ou no servidor.
Para adicionar a biblioteca JDBC do Derby ao projeto, vamos clicar com o botão direito sobre a
divisão Libraries, e escolher a opção Add Library. Na janela que se abrirá, selecionaremos
apenas a opção Java DB Driver e clicaremos no botão Add Library.
O Autor
Precisamos acrescentar o framework JPA escolhido, no caso, o Eclipse Link, disponível para
download na seção “Explore +”.
Após efetuar o download da versão mais recente do Eclipse Link, no formato zip, e extrair
para algum diretório de fácil acesso, crie uma biblioteca através da opção de menu
Tools.Libraries, seguido do clique sobre o botão New Library. Daremos a ela o nome
EclipseLink2.7, e adicionaremos o arquivo eclipselink.jar, presente no diretório jlib, além de
todos os arquivos no formato jar do subdiretório jpa.
Fonte: O Autor
autor
Após a definição da nova biblioteca, vamos adicionar ao projeto, da mesma forma que fizemos
para o driver JDBC, clicando com o botão direito sobre a divisão Libraries, e escolhendo a
opção Add Library. Ao final, teremos a configuração de bibliotecas para o projeto como a que
é apresentada a seguir.
autor
Agora só precisamos de um banco de dados Derby, que será criado de forma simples, através
da aba Services do NetBeans, na divisão Databases.
Para criarmos um banco de dados, precisamos clicar com o botão direito sobre o driver Java
DB, selecionável com a abertura da árvore de Databases, seguido da escolha da opção
Create Database, no menu de contexto. Na janela que será aberta, efetuaremos o
preenchimento do nome de nosso novo banco de dados com o valor "bancoJPA", bem como
usuário e senha, onde podemos também utilizar o valor "bancoJPA" para ambos.
Fonte: Autor
Ao clicar no botão de confirmação, o banco de dados será criado e ficará disponível para
conexão, através do driver JDBC. A conexão é identificada por sua Connection String, tendo
como base o endereço de rede (localhost), a porta padrão (1527) e a instância (bancoJPA).
A conexão é aberta com o duplo-clique sobre o identificador, ou o clique com o botão direito e
escolha da opção Connect. Com o banco de dados aberto, vamos executar os comandos SQL
necessários para a criação e alimentação da tabela, clicando com o botão direito sobre a
conexão e escolhendo a opção Execute Command.
Veremos que a janela de edição de SQL será aberta, permitindo que seja digitado o script
apresentado a seguir. Para executar nosso script, devemos pressionar CTRL+SHIFT+E, ou
clicar sobre o botão de execução de SQL, disponibilizado na parte superior do editor.
NOME VARCHAR(50),
QUANTIDADE INTEGER);
Fonte:Autor
VERIFICANDO O APRENDIZADO
1. O USO DE MAPEAMENTO OBJETO-RELACIONAL SE TORNOU UMA
NECESSIDADE BÁSICA PARA OS SISTEMAS CADASTRAIS MODERNOS,
E DIVERSOS MODELOS FORAM ADOTADOS, NORMALMENTE COM O
USO DE XML OU ANOTAÇÕES. ENTRE AS TECNOLOGIAS UTILIZADAS,
TEMOS OS ENTITY BEANS, DO J2EE, QUE BASEIAM SUA
FUNCIONALIDADE NO PADRÃO DE DESENVOLVIMENTO:
A) Active Record
B) DAO
C) Facade
D) Adapter
E) Front Controller
A) Persistence
B) EntityManager
C) Query
D) Transaction
E) EntityManagerFactory
GABARITO
Ao utilizar os Entity Beans, qualquer operação efetuada sobre as entidades causa um efeito
diretamente no banco de dados, ou seja, a criação gera um comando de INSERT, a remoção
define o comando DELETE, e as alterações dos valores de atributos geram múltiplos
comandos UPDATE, caracterizando o padrão Active Record.
A classe Query apresenta diversos métodos para consulta e manipulação de dados, com base
na sintaxe JPQL, como getResultList, para a obtenção do resultado através de uma coleção,
getSingleResult, para receber uma entidade simples, ou ainda, executeUpdate, para efetuar
alterações e exclusões de entidades.
MÓDULO 2
VOCÊ SABIA
O acesso aos serviços oferecidos pelo pool de EJBs deve ser solicitado a partir de uma
interface local (EJBLocalObject) ou remota (EJBObject), onde as interfaces são geradas a
partir de componentes de fábrica, criadas com a implementação de EJBLocalHome, para
acesso local, ou EJBHome, para acesso remoto. Como é padrão na plataforma Java, as
fábricas são registradas e localizadas via JNDI (Java Naming and Directory Interface).
Fonte: Autor
SERVICE LOCATOR
Para acesso aos componentes registrados via JNDI.
ABSTRACT FACTORY
Na definição da fábrica de interfaces.
PROXY
Na comunicação com clientes remotos e, como citado anteriormente.
FLYWEIGHT
Na concepção do pool de objetos.
O acesso ao banco de dados, no ambiente JEE, também ocorre de forma diferenciada, pois ao
invés de uma conexão JDBC simples, obtida a partir do DriverManager, temos um pool de
conexões JDBC, representado por um objeto do tipo DataSource, que assim como os EJBs, é
registrado via JNDI. Quando solicitamos uma conexão ao DataSource, não estamos abrindo
uma nova conexão, mas reservando uma das disponíveis no pool, e quando invocamos o
método close, não ocorre a desconexão, mas, sim, a liberação da conexão para a próxima
requisição.
HttpServletResponse response)
response.setContentType("text/html;charset=UTF-8");
try {
Statement st = c1.createStatement();
while(rs.next())
out.println(rs.getString("NOME")+"
");
c1.close();
out.println("");
Como utilizamos JPA, não é necessário efetuar toda essa codificação para localização e
utilização do pool, ficando a cargo do framework de persistência. No fluxo normal de execução,
o cliente faz uma solicitação para a interface de acesso, que é repassada para o pool de EJBs,
sendo disponibilizado um deles para responder, e na programação do EJB, utilizamos o JPA
para obter acesso ao banco de dados a partir do DataSource, com o controle transacional
sendo efetuado através do JTA (Java Transaction API).
SAIBA MAIS
No J2EE, existia um EJB para persistência, denominado Entity Bean, que seguia o padrão
Active Record, mas ele se mostrou inferior, em termos de eficiência, quando comparado a
alguns frameworks de persistência, sendo substituído pelo JPA no JEE5.
SESSION BEANS
Quando trabalhamos com os componentes do tipo EJB, estamos preocupados com as regras
de negócio de nosso aplicativo, ou seja, visamos à implementação da lógica do sistema, com
base nas entidades e nos requisitos definidos, sem qualquer preocupação com a estrutura de
persistência que será utilizada. Também devemos observar que as regras de negócio devem
ser totalmente independentes das interfaces do sistema, não devendo ser direcionadas para
nenhum ambiente específico.
O primeiro tipo de EJB que deve ser observado é o de sessão, responsável por efetuar
processos de negócios de forma síncrona, e configurável de três formas distintas, como
podemos observar no quadro seguinte.
Comportamento Descrição
Stateless Não permite a manutenção de estado, ou seja, não guarda
valores entre chamadas sucessivas.
Antes de definir um Session Bean, devemos definir sua interface de acesso, com base na
anotação Local, para acesso interno, ao nível do servidor, ou Remote, permitindo que o
componente seja acessado remotamente. Em nossos estudos, o uso de acesso local será
suficiente, já que teremos o acionamento dos EJBs a partir dos Servlets.
@Local
Ao criarmos o EJB, ele deverá implementar a interface de acesso, além de ser anotado como
Stateless ou Stateful, dependendo da necessidade do negócio. Para uma calculadora
simples, não precisaríamos de gerência de estados.
@Stateless
@Override
return a + b;
Quanto ao EJB do tipo Singleton, ele é utilizado quando queremos compartilhar dados entre
todos os usuários conectados, mesmo na execução sobre múltiplas máquinas virtuais, em
ambientes distribuídos. Não podemos esquecer que os EJBs são uma tecnologia corporativa, e
que a execução de forma clusterizada não é uma exceção em sistemas de missão crítica.
COMENTÁRIO
Para utilizar um componente do tipo Session Bean a partir de um Servlet, o processo é trivial,
como podemos observar a seguir.
@WebServlet(name = "ServletSoma",
urlPatterns = {"/ServletSoma"})
@EJB
CalculadoraLocal facade;
HttpServletResponse response)
response.setContentType("text/html;charset=UTF-8");
Tudo que precisamos fazer é anotar um atributo, do tipo da interface local, com EJB, e no
código de resposta à chamada HTTP, invocamos os métodos da interface, como se fossem
chamadas locais. No exemplo, temos a interface CalculadorLocal referenciada no atributo
facade, o que permite invocar o método somar, sendo executado pelo pool.
DICA
Fonte: Shutterstock
Para criar filas ou tópicos no GlassFish, é necessário utilizar o comando asadmin, como no
exemplo seguinte, para a criação de uma fila denominada jms/SimpleQueue.
jms/SimpleConnectionFactory
jms/SimpleQueue
Fonte: Autor
Existe um tipo de EJB denominado MDB (Message Driven Bean) , que tem como finalidade a
comunicação com mensagerias via JMS (Java Message Service) , possibilitando o
processamento assíncrono no JEE. Através do MDB é possível trabalhar nos dois domínios de
mensagerias, com o tratamento de mensagens sendo feito através do pool de EJBs, a partir de
um único método, que tem o nome onMessagerepresentando os eventos de recepção de
mensagens.
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup",
propertyValue = "jms/SimpleQueue"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public Mensageiro001() {
@Override
try {
((TextMessage)message).getText());
System.out.println("Erro: "+ex.getMessage());
No código de exemplo, temos uma anotação MessageDriven, para a definição do MDB, com a
configuração para acesso a jms/SimpleQueue, do tipo javax.jms.Queue, através de
anotações ActivationConfigProperty. Também é possível utilizar canais internos do projeto,
mas o uso de canais do servidor viabiliza o comportamento B2B, com acesso a partir de
qualquer plataforma que dê suporte ao uso de mensagerias.
SAIBA MAIS
Algo importante, acerca do MDB, é que ele foi projetado exclusivamente para receber
mensagens, a partir de filas ou tópicos, o que faz com que não possa ser acionado
diretamente, como os Session Beans. Para sua ativação, basta que um cliente poste uma
mensagem.
@WebServlet(name = "ServletMessage",
urlPatterns = {"/ServletMessage"})
@Resource(mappedName = "jms/SimpleConnectionFactory")
@Resource(mappedName = "jms/SimpleQueue")
try {
Connection connection =
connectionFactory.createConnection();
Session session =
connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer =
session.createProducer(queue);
messageProducer.send(message);
HttpServletResponse response)
response.setContentType("text/html;charset=UTF-8");
out.println("");
out.println("");
putMessage();
out.println("");
O processo é um pouco mais complexo que o adotado para os Session Beans, porém
apresenta menor acoplamento.
PASSO 1
PASSO 2
PASSO 3
PASSO 1
PASSO 2
Com os recursos mapeados, definimos o método putMessage, para envio da mensagem, onde
devemos criar uma conexão (Connection) a partir da fábrica, a sessão (Session) a partir da
conexão, e o produtor de mensagens (MessageProducer) a partir da sessão. Na inicialização
do MessageProducer, utilizamos o recurso de fila mapeado, indicando que ele deve apontar
para a fila (Queue) destinada ao MDB.
PASSO 3
Fonte: Shutterstock
APLICATIVO CORPORATIVO
Para que possamos trabalhar com EJBs, através do ambiente do NetBeans, devemos definir
um projeto corporativo. A sequência de passos para criar o Aplicativo Corporativo pode ser
observada nas figuras seguintes:
Escolher o servidor (GlassFish) e versão do JEE (Java EE7), além de marcar as opções de
criação para os módulos EJB e Web.
Fonte:Autor
Projeto Característica
Quando trabalhamos com um projeto corporativo, devemos implantar o projeto principal, com
extensão ear (Enterprise Archived), cujo ícone é um triângulo, pois qualquer tentativa de
implantar os dois projetos secundários irá impedir a execução correta do conjunto, exigindo que
seja feita a remoção manual dos projetos anteriores pela aba de Serviços.
Fonte: Autor
Agora, vamos criar nosso primeiro Session Bean, configurado como Stateless, no projeto
secundário ExemploEJB-ejb, adicionando um novo arquivo e seguindo os seguintes passos:
Definir o nome (Calculadora) e pacote (ejbs) do novo Session Bean, escolher o tipo como
Stateless e marcar apenas a interface Local.
Em diversas situações, a IDE mostra um erro de compilação, decorrente da importação dos
componentes da biblioteca javax.ejb. Caso o problema ocorra, a solução é simples, com a
inclusão da biblioteca Java EE 7 API no projeto.
Fonte: Autor
Com o componente ServletSoma criado, utilizamos o código de exemplo definido antes, com a
chamada para o EJB, executamos o projeto principal (ExemploEJB), e efetuamos a chamada
apropriada.
http://localhost:8080/ExemploSimplesJPA-war/ServletSoma
Fonte: Shutterstock
Quanto ao EJB do tipo MDB, para criá-lo, devemos adicionar, no projeto ExemploEJB-ejb, um
novo arquivo do tipo Message Driven Bean, na categoria Enterprise Java Beans.
Fonte: Shutterstock
http://localhost:8080/ExemploSimplesJPA-war/ServletMessage
Após efetuar a chamada, será apresentada a página com a informação de que ocorreu o envio
da mensagem, o que poderá ser verificado no console de saída do GlassFish, conforme
descrito anteriormente.
VERIFICANDO O APRENDIZADO
A) Stateless
B) Stateful
C) Singleton
D) Asynchronous
E) Synchronous
B) JDBC
C) JMS
D) JAAS
E) JTS
GABARITO
Os três modelos para gerência de estados, nos Session Beans, podem ser descritos de forma
resumida como: Sem estado (Stateless), com estado para a conexão (Stateful), e estado global
compartilhado (Singleton).
MÓDULO 3
Descrever a utilização da arquitetura MVC na plataforma Java
PADRÕES DE DESENVOLVIMENTO
A orientação a objetos representou um grande avanço na implementação de sistemas, pois
aproximou a modelagem da codificação, mas o uso incorreto da metodologia levou à perda de
diversas vantagens. Os padrões de desenvolvimento, que definem a formalização de
soluções reutilizáveis, com nome, descrição da finalidade, modelagem UML e modo de
utilização, permitiram recuperar as vantagens, baseando-se na adoção de soluções eficazes
para a construção de sistemas orientados a objetos.
Quando abordamos a tecnologia JPA, ficou claro que ocorre uma divisão entre os dados da
entidade e o mapeamento objeto-relacional, já que, ao contrário dos atributos, as anotações
não são serializáveis, impedindo a sua repercussão para outras camadas, o que é semelhante
ao padrão DAO, no qual temos os comandos para acesso ao banco de dados agrupados em
uma classe específica, separados da classe de entidade e de todo o restante do sistema.
COMENTÁRIO
Temos a descrição formal dos padrões de desenvolvimento citados, além de alguns outros,
comuns em sistemas criados para o ambiente JEE, no quadro seguinte.
Padrão de Desenvolvimento
Singleton Strategy
ABSTRACT FACTORY
Definição de uma arquitetura abstrata para a geração de objetos, muito comum em
frameworks.
COMMAND
FACADE
FLYWEIGHT
ITERATOR
PROXY
Definição de um objeto para substituir a referência de outro, utilizado nos objetos remotos
para deixar a conexão transparente para o programador.
SERVICE LOCATOR
STRATEGY
PADRÕES ARQUITETURAIS
A arquitetura de um sistema define a estrutura de alto nível do software, ou seja, formaliza a
organização em termos de componentes e interações entre eles. Um dos objetivos é aproximar
a visão de projeto da implementação do sistema, impedindo que ocorra a previsão de
funcionalidades inviáveis para a fase de codificação.
Fonte:Shutterstock
Note que existem diversos perfis de sistemas, como aplicativos de linha de comando,
ambientes baseados em janelas, ou até serviços sem interações diretas com o usuário, além
da possibilidade de execução remota ou local, e cada perfil de execução traz algumas
exigências estruturais.
VOCÊ SABIA
Um modelo arquitetural define uma arquitetura de forma abstrata, com foco apenas no
objetivo ou característica principal, enquanto o estilo ou padrão arquitetural define o perfil dos
componentes estruturais, modelo de comunicação e, até mesmo, quais são os padrões de
desenvolvimento mais adequados na implementação.
EXEMPLO
Por exemplo, o modelo de Objetos Distribuídos define apenas atributos essenciais para
delimitar um ambiente com coleções de objetos respondendo a requisições remotas, enquanto
o padrão arquitetural Broker define as regras de implementação, como o uso de Proxy na
comunicação, ou a definição de pools de objetos no padrão Flyweight.
Fonte: Autor
Para utilizar uma arquitetura, é necessário compreender sua finalidade, de acordo com o
padrão arquitetural adotado. Sistemas de baixa complexidade podem basear a arquitetura nos
paradigmas adotados para a codificação, como a orientação a objetos, enquanto arquiteturas
com maior complexidade seguem uma padronização mais robusta para os elementos
estruturais, como a forma de comunicação em rede, a gerência de pools de objetos, ou a
utilização de processos assíncronos.
COMENTÁRIO
Ambientes de execução remota, como RPC (Remote Procedure Call) e Web Services, são
baseados em arquiteturas no padrão de processos comunicantes, onde servidores e clientes
podem ser criados utilizando plataformas de desenvolvimento distintas, e o único fator de
acoplamento é o protocolo de comunicação adotado.
MODEL (MODELO)
CONTROLLER (CONTROLE)
VIEW (VISUALIZAÇÃO)
Uma regra fundamental para a arquitetura MVC é a de que os elementos da camada View não
podem acessar a camada Model. Somente os objetos de negócio da camada Controller podem
acessar os componentes da Model, e os elementos da View devem fazer suas requisições
exclusivamente para os objetos de negócio.
ATENÇÃO
A arquitetura MVC é baseada em camadas, onde cada camada enxerga apenas a camada
imediatamente abaixo.
Em uma arquitetura MVC, as entidades são as unidades de informação para trânsito entre as
camadas, e todos os comandos SQL ficam concentrados nas classes do padrão DAO. Como
apenas a camada Controller pode acessar a Model, e nela estão as classes DAO, nós
garantimos que as interfaces não acessem o banco de dados diretamente.
A camada Controller precisa ser definida sem que seja voltada para algum ambiente
específico, como interfaces SWING ou protocolo HTTP. A única dependência aceitável para os
objetos de negócio deve ser com relação à camada Model, e como a gerência do uso dos
componentes DAO ocorre a partir deles, uma das características observadas é a diminuição da
complexidade nas atividades cadastrais que foram iniciadas na View, o que justifica dizer que
temos a aplicação do padrão Facade.
COMENTÁRIO
Da mesma forma, a camada Controller é o melhor local para definir as regras de autorização
para o uso de funcionalidades do sistema, tendo como base o perfil de um usuário autenticado.
Com relação à autenticação, ela pode ser iniciada por uma tela de login na camada View, com
a efetivação na camada Controller, e nos modelos atuais é comum a geração de um token,
mantendo a independência entre as camadas.
Fonte: Autor
DICA
Utilizar as ferramentas oferecidas pelo fabricante da linguagem pode ser uma boa opção
quando desejamos garantir a continuidade da evolução do sistema.
Em nosso contexto, a camada Model utiliza JPA, e como deve ser utilizada apenas pela
camada Controller, é definida no mesmo projeto em que estão os componentes do tipo EJB.
Note que a camada Controller oferece apenas as interfaces para os EJBs, com os dados sendo
transitados na forma de entidades, sem acesso ao banco de dados, já que anotações não são
serializáveis.
Com a abordagem adotada, definimos o núcleo funcional e lógico de nosso sistema, sem a
preocupação de satisfazer a qualquer tipo de tecnologia para construção de interfaces de
usuário.
A independência do núcleo garante que ele possa ser utilizado por diversas interfaces
simultâneas, como SWING, HTTP ou Web Services, sem que ocorra qualquer modificação nos
componentes do tipo JPA ou EJB.
Um erro comum, nos sistemas Java para Web, é definir os controladores no formato de
Servlets, pois as regras de negócio se confundem com as rotinas de conversão utilizadas entre
o protocolo HTTP e as estruturas da linguagem Java.
A abordagem errônea faz com que qualquer nova interface, como SWING, Web Services, ou
até linha de comando, seja obrigada a solicitar os serviços através do protocolo HTTP, algo que
não é uma exigência das regras de negócio dos sistemas, de forma geral.
Considere que a entidade Produto, definida anteriormente, com uso de tecnologia JPA, seja
criada no projeto ExemploEJB-ejb, onde codificamos nosso Session Bean de teste, com o
nome Calculadora. Com a presença da entidade no projeto, podemos adicionar outro Session
Bean do tipo Stateless, com o nome ProdutoGestor e uso de interface Local, para as
operações cadastrais.
@Local
@Stateless
@Override
createEntityManagerFactory("ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
em.close();
return lista;
@Override
createEntityManagerFactory("ExemploSimplesJPAPU");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
} catch (Exception e) {
em.getTransaction().rollback();
} finally {
em.close();
Como podemos observar, nossos códigos de exemplos anteriores foram aproveitados aqui,
com leves adaptações. Não há nada de novo no que se refere ao uso de JPA, ocorrendo
apenas uma reorganização em termos das classes e anotações, para que as operações sejam
disponibilizadas através do Session Bean.
Com nossas camadas Model e Controller completamente codificadas, podemos definir um
Servlet, no projeto ExemploEJB-war, com o nome ServletListaProduto, o qual será parte da
camada View do sistema, no modelo Web.
O objetivo do novo componente será a exibição da listagem dos produtos presentes na base de
dados.
@WebServlet(name = "ServletListaProduto",
urlPatterns = {"/ServletListaProduto"})
@EJB
ProdutoGestorLocal facade;
HttpServletResponse response)
response.setContentType("text/html;charset=UTF-8");
facade.obterTodos().forEach(p -> {
out.println("
" + p.getNome());
});
out.println("");
http://localhost:8080/ExemploEJB-war/ServletListaProduto
Estando tudo correto, teremos uma saída similar à seguinte, na tela do navegador.
Fonte: Autor
VERIFICANDO O APRENDIZADO
B) MVC
C) PAC
D) Batch
E) Pipes/Filters
BODY {
__________ EMF =
PERSISTENCE.CREATEENTITYMANAGERFACTORY("PU");
__________ EM = EMF.CREATEENTITYMANAGER();
EM.GETTRANSACTION().BEGIN();
EM.__________(C);
EM.GETTRANSACTION().COMMIT();
GABARITO
1. Os programas que executam sobre sistemas operacionais baseados no UNIX utilizam
amplamente um padrão arquitetural específico, no qual efetuamos o direcionamento do
fluxo de saída do primeiro programa para o fluxo de entrada do segundo. O texto faz
referência a qual padrão arquitetural?
Um exemplo de comando comum, no UNIX, seria "ls -s | more", onde temos a listagem de um
diretório, obtida no primeiro comando, sendo direcionada para um comando que efetua a
paginação do resultado. Os comandos representam os Filters (filtros), que são concatenados
pelo símbolo de Pipe.
body {
__________ em = emf.createEntityManager();
em.getTransaction().begin();
em.__________(c);
em.getTransaction().commit();
MÓDULO 4
Empregar padrão Front Controller em sistema MVC, com interface Java Web
PADRÃO FRONT CONTROLLER
O objetivo do padrão Front Controller é a concentração das chamadas efetuadas em um
único ponto de acesso, centralizando a orquestração dos serviços oferecidos a partir da
camada Controller, e direcionando os resultados para a interface correta. A implementação do
padrão Front Controller deve ocorrer ao nível da camada View, pois lida apenas com a
conversão de formatos, o fluxo de chamadas e os redirecionamentos, sem interferir com regras
de negócio.
RAZAO_SOCIAL VARCHAR(50));
NOME VARCHAR(50),
REFERENCES EMPRESA(CODIGO);
VALOR_CHAVE INT);
Para a interface de nosso sistema, utilizaremos cinco páginas, as quais são descritas no
quadro apresentado a seguir.
Página Descrição
Agora vamos definir os fluxos das chamadas, que ocorrerão a partir do HTTP, o que pode ser
representado através de uma Rede de Petri, um ferramental que permite expressar os
estados de um sistema, físico ou virtual, e definir as transições que ocorrem, efetuando a
ligação entre estados e transições através de arcos. Ao modelar um sistema Web, os estados
definem páginas e as transições são chamadas HTTP.
Fonte: Autor
Em nossa Rede de Petri, temos as páginas dentro de figuras elípticas, que representam os
estados do sistema, e as transições expressas através de figuras retangulares. A alternância
entre páginas, ou estados, sempre ocorrerá com a passagem por uma transição, através de um
Front Controller.
Como as chamadas HTTP utilizam parâmetros, com valores do tipo texto, vamos adotar um
parâmetro para identificação da transição requerida, onde teremos o nome acao e o valor
correspondente a um dos valores de nosso diagrama. Podemos observar, no quadro seguinte,
os valores utilizados e operações que devem ser realizadas.
Ação Operações
listaDep - Obter a lista de departamentos
Nos aplicativos Java para Web, o padrão Front Controller pode ser implementado com base
em um Servlet. O processo envolve a recepção de uma chamada HTTP, através dos métodos
doGet ou doPost, execução de operações que envolvam chamadas aos EJBs, relacionadas
às atividades de consulta ou persistência, e redirecionamento, ao final, para uma página,
normalmente do tipo JSP, para a construção da resposta.
PASSO 1
Adicionar novo arquivo, escolhendo Entity Classes from Database, na categoria Persistence.
autor
PASSO 2
Na configuração de Data Source, escolha New Data Source, com a definição do nome JNDI
(jdbc/cadastro), e escolha da conexão para o banco de dados.
autor
PASSO 3
Escolha as tabelas DEPARTAMENTO e EMPRESA, deixando marcada a opção de inclusão
das tabelas relacionadas.
autor
PASSO 4
Na tela seguinte, defina o nome do pacote como model, deixando marcada apenas a opção de
criação da unidade de persistência.
autor
PASSO 5
Escolha, ao chegar na última tela, o tipo de coleção como List, além de desmarcar todas as
opções.
autor
Teremos a geração das entidades Departamento e Empresa, no pacote model, embora com
possíveis erros de compilação, que serão resolvidos com o acréscimo da biblioteca Java EE 7
API ao projeto CadastroEJB-ejb. As entidades geradas irão precisar apenas de uma pequena
modificação, para configurar o uso de autoincremento.
@Entity
@Table(name = "DEPARTAMENTO")
@NamedQueries({
@NamedQuery(name = "Departamento.findAll",
@Id
pkColumnName = "NOME_TABELA",
pkColumnValue = "DEPARTAMENTO",
valueColumnName = "VALOR_CHAVE")
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "DeptoTabGen")
@Basic(optional = false)
@NotNull
@Column(name = "CODIGO")
@Entity
@NamedQueries({
@NamedQuery(name = "Empresa.findAll",
@Id
pkColumnName = "NOME_TABELA",
pkColumnValue = "EMPRESA",
valueColumnName = "VALOR_CHAVE")
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "EmpTabGen")
@Basic(optional = false)
@NotNull
@Column(name = "CODIGO")
Com a camada Model pronta, vamos criar a camada Controller, usando componentes do tipo
EJB, de acordo com os seguintes passos:
PASSO 1
Adicionar arquivo, escolhendo Session Beans For Entity Classes, na categoria Persistence.
autor
PASSO 2
Selecionar todas as entidades do projeto.
autor
PASSO 3
Definir o nome do pacote (control), além de adotar a interface Local.
autor
Será gerada uma classe abstrata, com o nome AbstractFacade, que concentra todos os
processos de acesso e manipulação de dados, com o uso de elementos genéricos.
this.entityClass = entityClass;
getEntityManager().persist(entity);
getEntityManager().merge(entity);
getEntityManager().remove(getEntityManager().merge(entity));
javax.persistence.criteria.CriteriaQuery cq =
getEntityManager().getCriteriaBuilder().createQuery();
return getEntityManager().createQuery(cq).getResultList();
javax.persistence.criteria.CriteriaQuery cq =
getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q =
getEntityManager().createQuery(cq);
q.setFirstResult(range[0]);
return q.getResultList();
javax.persistence.criteria.CriteriaQuery cq =
getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root< T > rt =
cq.from(entityClass);
cq.select(
getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q =
getEntityManager().createQuery(cq);
Observe que a classe é iniciada com um construtor, onde é recebida a classe da entidade
gerenciada, e um método abstrato para retornar uma instância de EntityManager, ao nível dos
descendentes, elementos utilizados pelos demais métodos da classe.
Os métodos create, edit e remove, voltados para as ações de inclusão, edição e exclusão da
entidade, são implementados através da invocação dos métodos de EntityManager,
semelhante aos nossos exemplos anteriores, com tecnologia JPA, bem como find, que retorna
uma entidade a partir de sua chave primária.
Quanto aos métodos findAll e findRange, eles utilizam o JPA no modo programado, com
base em CriteriaQuery, que apresenta métodos para substituir o uso de comandos na sintaxe
JPQL. A chamada ao método from, tendo como parâmetro a classe da entidade, combinado
com o método select, permite efetuar uma consulta que retorna todas as entidades do tipo
gerenciado a partir do banco de dados, mas em findRange temos ainda o recurso de
paginação, sendo definidos o índice inicial (setFirstResult) e a quantidade de entidades
(setMaxResults).
No método count, que obtém a quantidade total de entidades, também temos a adoção de
CriteriaQuery, agora de uma forma mais complexa, com a definição de um elemento Root,
envolvendo o conjunto completo de entidades, e aplicação do operador count sobre o
conjunto.
Com a definição do modelo funcional genérico, a construção dos Session Beans se torna
muito simples, com base na herança e uso de anotações.
@Stateless
DepartamentoFacadeLocal {
@PersistenceContext(unitName = "CadastroEJB-ejbPU")
@Override
return em;
public DepartamentoFacade() {
super(Departamento.class);
@Stateless
EmpresaFacadeLocal {
@PersistenceContext(unitName = "CadastroEJB-ejbPU")
@Override
return em;
public EmpresaFacade() {
super(Empresa.class);
Em todos os três EJBs temos o mesmo tipo de programação, onde ocorre a herança com base
em AbstractFacade, passando o tipo da entidade. O método getEntityManager retorna o
atributo em, e no construtor a superclasse é chamada, com a passagem da classe da entidade.
Os EJBs seguem o padrão Facade, e enquanto a anotação Stateless configura a classe para
se tornar um Stateless Session Bean, o uso da anotação PersistenceContext, com a
definição da unidade de persistência, instancia um EntityManager no atributo em.
Ainda são necessárias as interfaces de acesso ao pool de EJBs, o que deve ser feito sem o
uso de elementos genéricos.
@Local
List findAll();
int count();
@Local
int count();
Note que as interfaces apresentam métodos equivalentes aos que foram definidos em
AbstractFacade, mas com a especificação da entidade, o que faz com que a herança ocorrida
nos Session Beans implemente, de forma natural, as interfaces relacionadas.
COMENTÁRIO
Não foram utilizadas instruções para o controle transacional, o que decorre do fato de que o
contêiner EJB será o responsável por gerenciar as transações, via JTA, dentro do modelo
conhecido como CMP (Container Managed Persistence).
Para que o controle transacional ocorra da forma indicada, temos o atributo transaction-type
com valor JTA, no arquivo persistence.xml, mas, há uma discrepância entre o NetBeans e o
GlassFish, em termos da convenção de nomes, invalidando o identificador JNDI.
value="jdbc:derby://localhost:1527/bancoJPA"/ >
value="org.apache.derby.jdbc.ClientDriver"/ >
object-type="user"
pool-name="derby_net_bancoJPA_bancoJPAPool"/ >
transaction-type="JTA" >
Caso ocorra erro na implantação, mesmo após alterar os arquivos, execute o programa
asadmin, invocando, em seguida, o comando add-resources, com a passagem do nome
completo do arquivo glassfish-resources.xml.
Fonte:Autor
Fonte: Autor
CAMADA VIEW
A construção da camada View ocorrerá no projeto CadastroEJB-war, e será iniciada com a
geração das páginas JSP consideradas na Rede de Petri do sistema, começando pela página
DadosEmpresa.jsp, que não apresenta conteúdo dinâmico.
O cadastro de um departamento será mais complexo, pois envolverá a escolha de uma das
empresas do banco de dados. Vamos adicionar o arquivo DadosDepartamento.jsp, com o
conteúdo apresentado a seguir.
Empresa:
<%
request.getAttribute("listaEmp");
for(Empresa e: lista){
%>
< %=e.getRazaoSocial()%>
< /option>
< % } %>
Agora vamos criar o primeiro arquivo para listagem, com o nome ListaEmpresa.jsp.
< html>
< body>
< tr>< td>Código< /td>< td>Razão Social< /td>< td>Opções< /td>< /tr>
<%
request.getAttribute("lista");
for(Empresa e: lista){
%>
< td>
< a href="CadastroFC?acao=excEmpExec&cod=<%=e.getCodigo()%>">
Excluir< /a>
< /td>
< /tr>
<% } %>
< /table>
< /body>
< /html>
A página é iniciada com a definição de um link para CadastroFC, com o parâmetro acao
contendo o valor incEmp. Em seguida, é definida uma tabela para exibir os dados de cada
empresa do banco de dados, contendo os títulos Código, Razão Social e Opções.
Recuperamos a coleção de empresas, através de um atributo de requisição com o nome lista,
e preenchemos as células de cada linha da tabela a partir dos dados da entidade, além de um
link para exclusão montado dinamicamente. A exclusão será efetuada com a chamada para
CadastroFC, tendo o valor excEmpExec no parâmetro acao, e o código da empresa corrente
no parâmetro cod.
< html>
< body>
<%
request.getAttribute("lista");
for(Departamento d: lista){
%>
< td>
< a href="CadastroFC?acao=excDepExec&cod=<%=d.getCodigo()%>">
Excluir< /a>
< /td>
< /tr>
< % } % >
< /table>
< /body>
< /html>
< html>
< body>
< a href="CadastroFC?acao=listaDep">
< a href="CadastroFC?acao=listaEmp">
< /body>
< /html>
Podemos observar que os links utilizados fazem referência a CadastroFC, com os valores de
acao para obtenção de listagens para as entidades, que no caso são listaDep, para
departamentos, e listaEmp, para empresas.
IMPLEMENTAÇÃO DO FRONT
CONTROLLER
Com as interfaces concluídas, devemos iniciar a construção do Front Controller, levando à
conclusão da camada View. Utilizaremos também um padrão Strategy, com o objetivo de
segmentar as chamadas aos EJBs, e todas as classes serão criadas no pacote view, do
projeto ExemploEJB-war.
this.facade = facade;
HttpServletRequest request);
}
Com base em uma classe abstrata, e uso de elemento genérico, definimos um padrão
Strategy, onde a execução ocorrerá a partir do valor para acao e da requisição HTTP, além
de um construtor recebendo a interface para o EJB, através do elemento genérico.
super(facade);
@Override
HttpServletRequest request) {
switch(acao){
case "listaEmp":
request.setAttribute("lista", facade.findAll());
break;
case "excEmpExec":
Integer codigo =
new Integer(request.getParameter("cod"));
facade.remove(facade.find(codigo));
request.setAttribute("lista", facade.findAll());
break;
case "incEmpExec":
String razaoSocial =
request.getParameter("razao_social");
empresa.setRazaoSocial(razaoSocial);
facade.create(empresa);
request.setAttribute("lista", facade.findAll());
break;
case "incEmp":
paginaDestino = "DadosEmpresa.jsp";
break;
return paginaDestino;
Além da definição da página correta, temos as operações efetuadas a partir do atributo facade,
como a remoção da entidade, quando acao vale excEmpExec, ou a inclusão, para o valor
incEmpExec. Para todas as ações que direcionam para a página de listagem, temos ainda a
definição do atributo de requisição com o nome lista, contendo a coleção de empresas, obtidas
a partir do método findAll do facade, o que permite que ocorra sua recuperação posterior, na
página JSP.
EmpresaFacadeLocal empresaFacade) {
super(facade);
this.empresaFacade = empresaFacade;
@Override
HttpServletRequest request) {
switch(acao){
case "listaDep":
request.setAttribute("lista", facade.findAll());
break;
case "excDepExec":
Integer(request.getParameter("cod"));
facade.remove(facade.find(codigo));
request.setAttribute("lista", facade.findAll());
break;
case "incDepExec":
request.getParameter("cod_empresa"));
departamento.setNome(nome);
departamento.setEmpresa(empresa);
facade.create(departamento);
request.setAttribute("lista", facade.findAll());
break;
case "incDep":
request.setAttribute("listaEmp",
empresaFacade.findAll());
paginaDestino = "DadosDepartamento.jsp";
break;
return paginaDestino;
A estratégia para departamentos é um pouco mais complexa, o que exigiu a utilização de duas
interfaces para EJBs. Durante a execução, teremos a página de destino definida como
ListagemDepartamento.jsp, a não ser para acao com valor incDep, onde a página de destino
utilizada será DadosDepartamento.jsp.
PASSO 1
PASSO 2
PASSO 3
PASSO 1
PASSO 2
Também temos a utilização de facadeEmpresa, para definir o atributo listaEmp, quando acao
tem valor incDep, e para recuperar a empresa selecionada, quando acao vale incDepExec.
PASSO 3
@WebServlet(name="CadastroFC", urlPatterns={"/CadastroFC"})
@EJB
EmpresaFacadeLocal empresaFacade;
@EJB
DepartamentoFacadeLocal departamentoFacade;
new HashMap<>();
@Override
super.init();
empresaFacade));
departamentoFacade,empresaFacade));
String[] acoesEmpresa =
{"listaEmp","incEmp","incEmpExec","excEmpExec"};
acoes.put(acao, "empresa");
String[] acoesDepto =
{"listaDep","incDep","incDepExec","excDepExec"};
acoes.put(acao, "departamento");
HttpServletResponse response)
if(acao==null)
Strategy st = estrategia.get(acoes.get(acao));
request.getRequestDispatcher(st.executar(acao, request)).
forward(request, response);
@Override
HttpServletResponse response)
processRequest(request, response);
@Override
HttpServletResponse response)
processRequest(request, response);
Como toda a complexidade foi distribuída entre os descendentes de Strategy, o Servlet irá
funcionar como um simples redirecionador de fluxo. Inicialmente, temos os atributos anotados
para acesso aos EJBs, e a definição de dois HashMaps, um para armazenar as estratégias de
empresa e departamento, com o nome estrategia, e outro para relacionar as ações do sistema
com os identificadores dos gestores, com o nome acoes.
COMENTÁRIO
Agora, com o aplicativo completo, podemos executá-lo, testando a inclusão e a listagem, tanto
para empresas quanto para departamentos. Algumas das telas de nosso sistema podem ser
observadas a seguir.
Fonte: Autor
Fonte: Autor
Fonte: Autor
VERIFICANDO O APRENDIZADO
A) Diagrama de Classes
B) Rede de Petri
D) Fluxograma
E) Diagrama de Componentes
A) HttpSession
D) RequestDispatcher
E) HttpServletResponse
GABARITO
1. No padrão Front Controller, temos a centralização das chamadas, com diversos fluxos
de processamento, identificados a partir de algum parâmetro, e o redirecionamento para
a visualização, ao final. Se a visualização representa um estado do sistema, e as
transições ocorrem nas chamadas, que diagrama seria adequado para a modelagem?
Através de uma Rede de Petri é possível modelar o sistema de forma macroscópica, com a
identificação das telas necessárias e fluxo de navegação, representando as transições, sempre
passando pelo Front Controller. É um modelo bastante genérico, que define o funcionamento
geral, sem descrever detalhes da implementação.
CONSIDERAÇÕES FINAIS
Aqui, analisamos duas tecnologias fundamentais na plataforma Java, para o ambiente
corporativo: JPA (Java Persistence API) e EJB (Enterprise Java Beans). Observamos que
ambas as tecnologias utilizam anotações, e compreendemos o papel do JPA nas tarefas de
persistência, com mapeamento objeto-relacional, e do EJB para implementação das regras de
negócio de nossos sistemas, de forma síncrona ou assíncrona.
Finalmente, construímos um sistema cadastral, no modelo Java para Web, com a adoção de
JPA na camada Model e EJB na camada Controller, além de utilizar um Servlet Front Controller
e algumas páginas JSP (Java Server Pages) na camada View. Na criação do sistema,
adotamos a automação do NetBeans, visando a um ganho de produtividade.
AVALIAÇÃO DO TEMA:
REFERÊNCIAS
CASSATI, J. P. Programação Servidor em Sistemas Web. Rio de Janeiro: Estácio, 2016.
CORNELL, G.; HORSTMANN, C. Core JAVA. 8. ed. São Paulo: Pearson, 2010.
DEITEL, P.; DEITEL, H. AJAX, Rich Internet Applications e Desenvolvimento Web para
Programadores. São Paulo: Pearson Education, 2009.
DEITEL, P.; DEITEL, H. JAVA, Como Programar. 8. ed. São Paulo: Pearson, 2010.
MONSON-HAEFEL, R.; BURKE, B. Enterprise Java Beans 3.0. 5. ed. USA: O’Reilly, 2006.
EXPLORE+
CONTEUDISTA
Denis Gonçalves Cople
CURRÍCULO LATTES