A arquitetura de referência J2EE define terminologias e conceitos muito úteis quando estamos definindo e discutindo arquiteturas de aplicações. Um dos conceitos mais básicos, que infelizmente parece ser pouco conhecido entre os profissionais J2EE, são as camadas de aplicação e alguns conceitos relacionados.

O objetivo desse artigo é dar uma visão geral sobre esses conceitos.

Pré-requisitos

Esse artigo requer muito pouco conhecimento técnico para ser lido, podendo inclusive ser interessante para gerentes ou outras pessoas de áreas não técnicas terem uma idéia do que significa desenvolvimento J2EE.

Arquitetura de referência JavaEE

Dentre as várias formas de classificar os tipos possíveis de arquiteturas de software, existe uma que as divide entre arquiteturas de sistema e arquiteturas de referência.

Arquitetura de sistema refere-se à arquitetura de um sistema específico, na qual são definidos diagramas de instalação, design, interfaces, classes, etc. É a especificação técnica de como o sistema vai lidar com requisitos não funcionais.

Arquitetura de referência refere-se a um método ou estilo arquitetural. Ao invés de definir como agir para um caso específico, define uma linha de pensamento a ser seguida na definição da arquitetura de um sistema.

Assim é a arquitetura definida pela especificação J2EE, uma arquitetura de referência que define, dentre outras coisas, as camadas de uma aplicação J2EE.

As camadas

J2EE define 4 camadas básicas no modelo de aplicação. São as seguintes, como ilustrado na Figura 1:

  • Camada Cliente – Parte do software que roda no computador do usuário;
  • Camada Web     - Parte do software que roda no servidor web, que por sua vez fica normalmente dentro do servidor de aplicações;
  • Camada de negócios – Parte do software que roda no servidor de aplicações;
  • Camada de dados – Banco de dados e sistemas externos;
Camadas numa aplicação J2EE

Figura 1: Camadas numa aplicação J2EE

 

Cada camada pode ser dividida em várias subcamadas na arquitetura da aplicação, mas a especificação J2EE estabelece que o software rodando na máquina do cliente está na camada cliente, páginas servidas por um servidor web como o Tomcat está na camada web, componentes de negócio rodando em um servidor de aplicações como o JBoss estão na camada de negócio e, finalmente, que o banco de dados e sistemas externos estão na camada de dados.

Vamos estudar um pouco mais de cada camada.

Camada cliente

Estão na camada cliente softwares que rodam dentro do browser web, por exemplo, como páginas HTML, JavaScript, CSS, etc. Também rodam na camada cliente aplicações feitas em linguagens visuais, como Visual Basic ou Delphi, aplicativos Swing, SWT, AWT e afins. Todos esses tem em comum o fato de rodarem na máquina do usuário.

Aqui cabe um conceito muito importante: você sabe o que significa “thin client”? “Thin client” (ou “cliente magro”) é uma expressão muito utilizada para descrever aplicações rodando na camada cliente que não realizem funções complexas como acesso a banco de dados, cálculos, processamento de regras de negócio, conexão com sistemas externos, etc. Eles devem conter pura e simplesmente a interface com o usuário, tendo somente lógica de apresentação.

A idéia é que estes clientes sejam bem mais leves do que aqueles normalmente usados em aplicações Client/Server, onde a regra de negócio fica toda no cliente (Fat Clients) ou no servidor de banco de dados, através de Stored Procedures, triggers, etc. Além disso, toda a parte de segurança, desempenho e adequação a outros requisitos não funcionais ficam por conta dos servidores web ou de aplicação.

Por exemplo, uma aplicação que tem toda a lógica de negócio implementada em um JSP (que roda no servidor web) usa thin clients. Uma aplicação que usa JSPs para camadas de apresentação e chama EJBs para lógica de negócio também. Já uma aplicação Swing que processa toda a parte de negócio usando EJBs para acessar o banco ou sistemas externos é um Fat client.

Camada web

Nessa camada estão os JSPs, servlets, action struts e softwares que normalmente rodam num servidor web como o Tomcat, por exemplo. Normalmente, esse tipo de aplicação é empacotado em um arquivo WAR (Web Archive), que pode ser instalado num web Server ou num Application Server. 

Camada de negócios

Nessa camada Ficam os EJBs, classes de negócio, DAOs, classes que acessam sistemas externos, etc.

Toda integração entre as aplicações deve ser realizada por essa camada. Quando usamos DBLINK (ligações diretas entre servidores de bancos de dados), por exemplo, não estamos seguindo à risca a arquitetura de referência J2EE. Se colocarmos lógica de negócio em uma PL rodando no banco ou se calcula a soma de valores dos produtos em um carrinho de compras de uma aplicação de e-commerce, também não estamos seguindo J2EE à risca.

Normalmente a camada de negócios fica empacotada em um arquivo JAR (também chamado de EJB-JAR) contendo os EJBs e demais classes de negócio e acesso a dados da aplicação, que pode ser instalada em um container EJB. Um exemplo de container EJB é o servidor de aplicações JBoss.

Outra forma de empacotamento oferecida pela especificação J2EE são os arquivos EAR, ou Enterprise Application Archive. Esses pacotes simplesmente agrupam arquivos WAR, EJB-JAR e suas dependências em um único pacote, que guarda toda a parte de software que deve rodar em um servidor J2EE: as camadas WEB e de negócios.

A especificação J2EE define uma série de serviços de infra-estrutura oferecidos pelos servidores J2EE. Eles basicamente devem se responsabilizar da melhor forma possível por suprir facilmente requisitos não funcionais comuns de toda aplicação, como segurança, desempenho, escalabilidade, adaptabilidade, compatibilidade, capacidade de gerenciamento e disponibilidade.

Na medida do possível, toda aplicação J2EE deve delegar essa responsabilidade para o container, ao invés de programá-la na aplicação. Por exemplo, uma vez que o container oferece mecanismos sofisticados de autenticação autorização e gerenciamento de sessões, não é uma boa prática tentar escrever código para essas tarefas.

Camada de dados

Nessa camada ficam as tabelas de bancos de dados, índices e tudo mais que o servidor de banco suporta. Essa camada deve se limitar somente ao fornecimento de dados, sem qualquer lógica de negócio. O motivo disso é muito simples, não há como a especificação J2EE garantir escalabilidade executando regras de negócio em PLs rodando num banco Oracle, por exemplo. Já rodando num container J2EE, a especificação permite configurar a aplicação para rodar em um Cluster sem qualquer modificação (ou com mínimas modificações) no código fonte da aplicação.

Para conseguir as vantagens oferecidas pela especificação J2EE, é necessário seguir a linha guia proposta pela mesma.

Sistemas legados e outros sistemas externos também se encontram nessa camada. A especificação J2EE contém uma especificação especial para acesso a dados de sistemas externos, a chamada JCA, ou J2EE Connector Architecture. Essa especificação é semelhante à especificação JDBC para acesso a bancos de dados, mas permitindo acessos a sistemas externos.

A grande diferença é que além do acesso indexado, também oferecido no JDBC, é oferecida uma interface para acesso mapeado, referenciando registros de dados por seus nomes. A JCA define o conceito de Resource Adapter, que corresponderia aos drivers do JDBC. Para acessar um sistema X, é necessário construir um Resource Adapter para ele, por exemplo, da mesma maneira que precisamos de um driver JDBC Oracle para acessar um banco Oracle. Boa parte de grandes fabricantes de software, como a SAP, oferecem Resource Adapters já prontos para seus produtos.

Perceba que os sistemas externos podem sim ter lógica de negócio, mas somente lógica de negócio referente às suas respectivas aplicações. No tocante a aplicação que acessa o sistema externo, o sistema externo não tem lógica nenhuma, apenas fornece dados.  

Por exemplo, se temos duas aplicações: um sistema de vendas e um sistema de estoque. O sistema de estoque é um sistema externo para o sistema de vendas. Qualquer lógica de negócio referente a estoque deve ser feita somente pelo sistema de estoque. Sempre que a aplicação de vendas precisa lidar com estoque, deve fazer chamadas para a aplicação de estoques, enxergando a mesma de forma semelhante a forma como enxerga um banco de dados.

Cuidados especiais: acoplamento de camadas

Algumas aplicações não usam EJBs e processam todas as regras de negócio na aplicação web. Nesse caso, tanto a camada web quanto a camada de negócios ficam numa mesma aplicação web, sem necessidade de um servidor de aplicações. Isso não significa, contudo, que a aplicação não tenha uma camada de negócios. A definição de camada de negócios diz que esta é a parte do software que realiza as regras de negócio.

Em casos como esse, cuidado deve ser tomado para não misturar código web com código que contem regras de negócio. Por exemplo, processar regras de negócio em servlets ou actions struts torna as camadas web e de negócio acopladas, pois a mesma classe que processa lógica de apresentação contém as regras de negócio. Mesmo não usando EJBs, é uma boa prática criar classes de negócio (podem ser POJO mesmo) que contenham as regras de negócio e são chamadas a partir dos servlets ou das actions.

Preferencialmente, essas classes podem ser ainda mais desacopladas, usando conceitos de inversão de controle, o que é facilitado por um framework como o Spring.