Por que eu devo ler este artigo:O leitor deste texto terá a oportunidade de entender detalhes sobre a implantação de uma aplicação Java em alta disponibilidade e desenvolver componentes importantes e desacoplados, como tabelas editáveis combinadas com serviços RESTful.

O tema analisado neste artigo é fundamental para desenvolvedores que buscam formas de investirem seu tempo e suas habilidades em processos prioritários para as atividades de desenvolvimento em vez de terem que realizar integralmente a configuração de ambientes, como servidores, redes, load balancers e bancos de dados. Além disso, o artigo é orientado aos desenvolvedores que precisam garantir alta disponibilidade às suas aplicações em um ambiente auto escalável e com alta demanda por flexibilidade.

Nos últimos anos temos visto a evolução do conceito de Cloud Computing e como esta definição expande cada vez mais suas fronteiras. Hoje já temos uma série de subclassificações que, individualmente, se materializam em forma de serviços, por exemplo: IaaS – Infrastructure as a Service, PaaS – Platform as a Service, SaaS – Software as a Service, STaaS – Storage as a Service, NaaS – Network as a Service, entre outros.

Uma das características destes serviços é a elasticidade, ou seja, a alocação dinâmica de recursos computacionais baseada na demanda da aplicação. Com a elasticidade, você consegue responder prontamente ao aumento súbito de requisições, alocando novos servidores automaticamente. Além disso, diminui drasticamente o risco de indisponibilidade por falha e mantém o tempo de resposta da aplicação mais estável.

Outro benefício da elasticidade, é que você não precisa investir antecipadamente em uma infraestrutura que será necessária apenas em alguns momentos de pico. O gráfico da Figura 1 mostra uma comparação entre o uso otimizado de recursos versus o modelo tradicional de investimentos antecipados.

Comparação entre uso de recursos sob demanda versus antecipados
Figura 1. Comparação entre uso de recursos sob demanda versus antecipados

Os desenvolvedores também foram beneficiados com este novo modelo. As ofertas de plataformas para implantação de sistemas (PaaS), automatizadas e parametrizadas, dão flexibilidade e velocidade na criação dos ambientes usuais de projetos, como os de testes, homologação ou produção. A grande vantagem é que os desenvolvedores não precisam mais instalar sistemas operacionais, configurar servidores, redes, load balancers, ou seja, cuidar de todo o ambiente que envolve a aplicação. Como a plataforma está totalmente disponível em forma de serviço, o único foco do time de desenvolvimento será a própria aplicação, o que reduz o custo do projeto, uma vez que toda a operação de TI que estava envolvida na implantação, alocação e gestão de ambientes, agora é fornecida como serviço.

Neste artigo vamos focar na oferta de plataforma da Amazon Web Services (AWS), chamada de Elastic Beanstalk. Este serviço não exige nenhum uso de API específica ou qualquer outra personalização da sua aplicação, o que facilita a adoção por aplicações já existentes. Para demonstrar seus recursos criaremos uma aplicação Web e a tornaremos totalmente elástica, ou seja, baseado em métricas previamente estabelecidas, a quantidade de servidores poderá aumentar ou diminuir para atender o novo volume de requisições. Desta maneira, para testar a elasticidade da plataforma, simularemos um comportamento aleatório de acessos, com picos de requisições. Feita a simulação, novos servidores serão instanciados automaticamente e depois, quando o volume de requisições cair, deverão ser finalizados de maneira transparente.

Além do Elastic Beanstalk, também usaremos um outro serviço da AWS, o Elastic Load Balancing. Este serviço será usado para fazer a distribuição de carga entre os servidores, ou seja, distribuir as requisições dos usuários pelos servidores da aplicação. Esse serviço é muito importante para a nossa aplicação, já que a quantidade de servidores irá variar em períodos de pico. Sendo assim, novos servidores estarão disponíveis para responder as requisições e o loadbalancer deve ser inteligente para adicioná-los à lista de servidores disponíveis, assim como removê-los quando eles não mais estiverem em funcionamento.

Como dito, criaremos uma aplicação para testar estes recursos. Ela terá apenas uma lista de funcionários tabelada e permitirá a edição dos dados na própria tabela. Esta tabela editável de funcionários será construída com o framework JavaScript ExtJS 4 e será totalmente desacoplada do servidor, sendo alimentada apenas por serviços RESTful.

Do lado do servidor, criaremos os serviços RESTful utilizando a implementação do JAX-RS chamada Jersey. Como banco de dados, usaremos outra oferta da Amazon Web Services, chamada RDS (Relational Database Service). Assim, a criação e a configuração do banco de dados também serão delegadas à plataforma, novamente fazendo com que o time de desenvolvimento possa se dedicar a outras responsabilidades. Discutiremos em mais detalhes cada um dos serviços ao longo do artigo e todo o conteúdo desenvolvido estará disponível no site da Java Magazine.

Vale ressaltar que para a maioria dos serviços da AWS existe uma faixa de uso que garante gratuidade pelo período máximo de um ano, contando da data de criação da conta. Para entender mais sobre esta faixa de serviços gratuitos, acesse o endereço na seção de referências.

Preparando o ambiente

Para construir a aplicação usaremos a IDE Eclipse com o plugin AWS Toolkit for Eclipse. Você pode baixar a última versão do Eclipse a partir do endereço indicado na seção Links. Para instalar o plugin da AWS, acesse o menu Help > Install New Software, de dentro da IDE. Feito isso, informe o endereço http://aws.amazon.com/eclipse no campo Work with e tecle Enter. Em seguida selecione a opção AWS Toolkit for Eclipse, conforme a Figura 2, e siga até o final do processo de instalação. Logo após, reinicie o Eclipse.

Instalando o AWS Toolkit for Eclipse
Figura 2. Instalando o AWS Toolkit for Eclipse

Após instalar o plugin e reiniciar o Eclipse, acesse o menu Window > Show View > Other, e escolha a opção AWS Explorer, como mostra a Figura 3.

Exibindo o AWS Explorer
Figura 3. Exibindo o AWS Explorer

Esta visualização dará acesso aos serviços da AWS, porém você precisará de uma conta. Para se registrar, realize os passos a seguir:

  1. Acesse a URL da AWS: http://aws.amazon.com;
  2. Clique no botão Sing Up no topo da página. Feito isso, uma nova página se abrirá. Nela você informará que é um novo usuário (I am a new user);
  3. Continue no processo de cadastro. Em algum momento você deverá informar seu telefone para receber uma ligação e confirmar sua identidade. Este processo é para garantir a identidade de quem está se registrando e testar o canal de contato;
  4. No final você deverá informar seu cartão de crédito. Este passo é importante pelo modelo que a AWS usa para cobrar pelo uso de seus serviços. Como você pagará apenas pelo que usar e, principalmente, pelo tempo que usar, a informação do método de pagamento é importante.

Feito isto você terá sua conta ativa e estará pronto para usufruir dos serviços da AWS. Agora, efetue o login, acesse a área chamada Security Credentials e localize a região que mostra suas chaves, Access Keys. Você precisará delas neste artigo.

Escolhendo a Região

Uma das vantagens da plataforma da AWS é que ela oferece os mesmos serviços em diferentes regiões do mundo, ou seja, você pode implantar sua aplicação em um datacenter localizado no Brasil, ou EUA, ou Europa, ou em qualquer outra região em que ela ofereça o serviço. Neste artigo vamos criar toda a infraestrutura da aplicação no Brasil, o que diminui acentuadamente a latência de rede, comparada com outras ofertas de PaaS localizadas fora da América Latina.

Primeiro vamos configurar a sua conta da AWS no Eclipse, para depois escolher a região. Deste modo, acesse a área de preferencias da IDE e informe os dados da sua conta como mostra a Figura 4. Toda conta na AWS possui pelo menos uma Access Key ID e uma Secret Access Key. Como dito anteriormente, você pode obter estas informações na área chamada Security Credentials, dentro da área administrativa da AWS. Sem a chave o toolkit não poderá acessar os serviços da AWS diretamente.

Configurando o AWS Toolkit for Eclipse
Figura 4. Configurando o AWS Toolkit for Eclipse

Feito isto, na coluna do lado esquerdo, escolha a opção Regions e selecione a opção South America (São Paulo). Assim, terminamos a configuração do plugin e definimos em qual região vamos trabalhar. Vamos então começar a construir a aplicação.

Criando a aplicação Web e já implantando

Para criar uma nova aplicação, acesse o menu File > New > Other, e então navegue até a pasta AWS e escolha a opção AWS Java Web Project. Neste momento você pode pensar: e se já tenho a minha aplicação? Não tem problema, você poderá implantá-la da mesma maneira.

Na próxima tela, informe o nome da aplicação, certifique que sua conta da AWS foi selecionada e que a opção Basic Java Web Application esteja selecionada, como mostra a Figura 5.

Criando uma nova aplicação Web
Figura 5. Criando uma nova aplicação Web

Quando concluído, você terá um novo projeto Web com configurações e estruturas semelhantes à de um projeto normal do Eclipse. A diferença está nos pacotes de bibliotecas que virão configurados, por exemplo, a AWS SDK for Java, que dará acesso à API de manipulação dos serviços da AWS.

Na Figura 6, podemos observar a estrutura do projeto criado. Veja que já existe um arquivo JSP criado. Este arquivo é um exemplo de acesso à API da AWS e pode ser estudado posteriormente. Para este artigo, remova todo o seu conteúdo e adicione o código da Listagem 1.

Estrutura do projeto Web criado
Figura 6. Estrutura do projeto Web criado

<%@ page language="java" contentType="text/html; charset=utf-8" 
pageEncoding="utf-8"%>
  <!DOCTYPE html>
  <html>
   <head>
      <meta http-equiv="Content-type" content="text/html; charset=utf-8">
      <title>Lista Funcionários Web</title>
   </head>
   <body>
      <h1>Lista de Funcionários Web</h1>
   </body>
  </html>
Listagem 1. Conteúdo inicial do arquivo index.jsp

Vamos então implantar esta aplicação. Para isso, clique com o botão direito sobre o nome do projeto e escolha a opção AWS Web Services > Deploy to AWS Elastic Beanstalk. Uma nova janela aparecerá e você poderá escolher o servidor no qual deseja implantar sua aplicação. Dentro da pasta Amazon Web Services, escolha o servidor Tomcat 7 e clique em Next.

Na próxima tela você dará uma nome para a sua aplicação. Este será o nome utilizado pelo Elastic Beanstalk para identificá-la. Logo abaixo você terá os campos para criação do Environment, que servirá para termos o controle do ambiente no qual a sua aplicação será implantada. Por exemplo, podemos ter diferentes ambientes que definem estados da sua aplicação ou do release, como: Desenvolvimento, Homologação, Produção, etc.

Outra vantagem de se utilizar este serviço é o versionamento da sua aplicação a cada nova implantação, podendo eliminar janelas de manutenção, efetuar correções ou até mesmo rollbacks entre versões. Além disso, você poderá criar um ambiente de implantação completamente novo e redirecionar os usuários do ambiente antigo para o novo automaticamente.

Em nosso exemplo, vamos criar um ambiente chamado Desenvolvimento. Veja como ficará esta tela na Figura 7.

Definindo nome e ambiente no serviço AWS Elastic Beanstalk
Figura 7. Definindo nome e ambiente no serviço AWS Elastic Beanstalk

Na próxima tela, como mostra a Figura 8, podemos informar um par de chaves para acessar os servidores criados pelo Elastic Beanstalk. Esta é outra grande vantagem deste serviço, o acesso aos servidores nos quais estão instalados o Tomcat 7.

Informe também a URL de health check. Este endereço será usado pela plataforma para definir se a aplicação ainda está respondendo. Cada aplicação pode usar a URL que mais representa seu estado de disponibilidade. Em nosso exemplo, vamos usar apenas /index.jsp. Você também pode definir um e-mail para receber notificações. Prossiga para a próxima tela.

Configurando e-mail para notificações e URL para health check
Figura 8. Configurando e-mail para notificações e URL para health check

Na próxima tela, a sua aplicação já estará selecionada para implantação. Depois de clicar em Finish, o processo de implantação começará.

No final deste processo teremos sua aplicação sendo executada na infraestrutura da Amazon e disponível na Internet através de uma URL pública. Seguem algumas atividades que aconteceram automaticamente durante esta implantação:

  • Upload da sua aplicação e versionamento (também pode-se usar deployment incremental);
  • Novo servidor com Tomcat 7 instalado;
  • Configuração de um Load Balancer com uma URL de health check;
  • Configuração de uma URL pública para sua aplicação.

A Figura 9 demonstra uma visualização simplificada da arquitetura criada automaticamente para você. Para ter uma URL pública, sua aplicação foi registrada no serviço de DNS da Amazon, chamado Route 53. Além de traduzir o seu domínio (minhaapp.com.br) para endereços numéricos, IPs, ele fornece vários recursos para melhorar a performance da sua aplicação, viabilizar a construção de planos de Disaster Recovery ou simplesmente adicionar pesos diferentes por rota de IP.

Para melhorar a performance da sua aplicação, caso tenha usuários espalhados pelo globo, você pode implantá-la em diferentes Regiões, por exemplo: US East (N. Virginia) e South America (São Paulo). Deste modo, para cada requisição, o Route 53 decidirá a região do globo que deverá atendê-la, baseado na melhor latência para o usuário.

Arquitetura inicial criada pelo Elastic Beanstalk
Figura 9. Arquitetura inicial criada pelo Elastic Beanstalk

O serviço de Load Balancer também foi configurado e redirecionado para a sua aplicação (veja a Figura 9). O endereço de health check que configuramos é muito importante para o Load Balancer. Ele será utilizado para avaliar a saúde dos servidores e dependendo do tempo de resposta a própria infraestrutura configurada poderá decidir se um novo servidor é necessário. Faremos este teste no final do artigo.

Note, ainda na Figura 9, que a aplicação está localizada dentro de três áreas, são elas: Availability Zone #1, Auto Scaling Group e Security Group. Para entender a primeira, temos que lembrar que cada Região na AWS pode ser formada por vários datacenters geograficamente separados. Cada datacenter é chamado de Availability Zone. Sendo assim, você poderá usar mais de um datacenter para implantar a sua aplicação, garantindo que se algo aconteça com um, a sua aplicação ainda continuará respondendo do outro. Este tipo de técnica deverá fazer parte do seu plano de alta disponibilidade.

A segunda área, Scaling Group, define a elasticidade da sua aplicação, ou seja, quantos servidores você gostaria de ter executando sua aplicação e, caso seja necessário melhorar a performance, quantos servidores devem ser adicionados até que se atinja o número máximo. Veremos mais detalhes sobre esta configuração ao longo do artigo.

A terceira área, Security Group, define as regras de firewall para as instâncias de servidores. Da maneira como implantamos a nossa aplicação, apenas a porta 80 (HTTP) foi liberada para acesso.

Quando a implantação acabar, o toolkit abrirá a página padrão da sua aplicação já na URL pública. A Figura 10 mostra o resultado da implantação.

Aplicação implantada com sucesso no serviço AWS Elastic Beanstalk
Figura 10. Aplicação implantada com sucesso no serviço AWS Elastic Beanstalk

Dentro da IDE Eclipse, agora que a aplicação já foi implantada, você verá novos itens nas Views AWS Explorer e Servers, como mostra a Figura 11.

Informações sobre o ambiente criado
Figura 11. Informações sobre o ambiente criado

Através da View AWS Explorer, você pode abrir a configuração do ambiente. Para isso, clique duas vezes sobre o ambiente Desenvolvimento. Isso abrirá a janela de configuração, iniciando com um resumo, seguido de todos os recursos alocados para sua aplicação, configurações simples e avançadas, eventos do processo de implantação e logs.

Uma aba desta janela que é importante é a Environment Resources, usada para visualizar os recursos utilizados pela sua aplicação. Esta tela mostrará todos os servidores (neste caso apenas 01), a configuração de elasticidade da sua aplicação (Auto Scaling Group) e a configuração do Load Balancer. A Figura 12 mostra esta tela e a sua configuração.

Recursos consumidos na AWS pela implantação do sistema
Figura 12. Recursos consumidos na AWS pela implantação do sistema

Criando o banco de dados

Para criar o banco de dados, teremos que acessar a ferramenta de administração da AWS na Internet, já que o plugin para o Eclipse não possui a funcionalidade de criação de bancos. Na Internet você terá ainda mais funcionalidades além das oferecidos pelo plugin, como monitoração dos recursos utilizados e acesso a várias outras configurações avançadas.

Para acessar diretamente o console de administração, clique com o botão direito sobre o Server dentro da view Servers e acesse o menu Amazon Web Services > Go to AWS Management Console. Feito isso, você será levado à página padrão do Elastic Beanstalk.

Você pode explorar esta tela à vontade. Uma dica interessante, vá até a aba Monitoring, dentro de Environment Details, para visualizar os relatórios de monitoração dos recursos. A Figura 13 mostra os gráficos desta tela. Caso queira ver mais detalhes em cada um dos gráficos, clique sobre o gráfico desejado que uma nova janela se abrirá. Desta tela você poderá ver a média de uso de CPU, quantidade de requisições e até mesmo a latência média de resposta da sua aplicação.

Relatório de monitoração dos recursos alocados
Figura 13. Relatório de monitoração dos recursos alocados

Agora volte para a aba Overview e clique em Edit Configuration. Na janela que se abrirá, acesse a aba Database. Nesta aba você poderá configurar uma instância de banco de dados e relacionar esta instância com a sua aplicação. Há algumas configurações nesta tela que são importantes. Por exemplo, você poderia usar uma cópia (snapshot) de outro banco para iniciar a sua nova instância. Outra opção é escolher qual a engine de banco que você quer. Neste caso escolhemos MySQL, mas você pode criar outros tipos de instâncias na AWS, como Oracle e SQL Server. Como você está relacionando a sua aplicação com um banco de dados, também é possível escolher qual a política de remoção do banco, quando o seu ambiente for terminado. Neste caso, escolhemos que quando o ambiente for finalizado, queremos uma cópia como backup.

A última opção é muito especial, Multiples Availability Zones. Esta opção cria duas instâncias de banco de dados em diferentes datacenters (Availability Zone), porém dentro da mesma Região (São Paulo) e mantém a sincronia entre os dois bancos. Caso ocorra algum problema com a instância principal, a outra substitui automaticamente. Para a sua aplicação isso acontecerá de maneira transparente, já que o endereço de conexão com o banco não sofrerá nenhuma alteração.

Portanto, deixe a configuração desta tela como mostra a Figura 14. Logo após, clique no botão Apply Changes.

Criando uma nova instância de banco de dados para a aplicação
Figura 14. Criando uma nova instância de banco de dados para a aplicação

A criação do banco levará alguns minutos e no final você terá um endereço para conexão. Assim que terminar esta etapa, volte ao Eclipse e atualize a view AWS Explorer. Expanda a opção Amazon RDS e veja que agora há um banco configurado. Neste banco, clique duas vezes para se conectar e informe a senha configurada.

Na aba Database Explorer do Eclipse você encontrará o banco de dados já conectado e com um schema padrão criado, chamado “ebdb”. Com o botão direito do mouse, clique sobre a conexão do banco e escolha a opção Open SQL Scrapbook. Na janela que se abrirá, defina o nome do seu banco e execute a DDL da Listagem 2. Esta DDL é para a criação da única tabela da nossa aplicação.


CREATE TABLE funcionario (
   id_funcionario INT NOT NULL AUTO_INCREMENT,
   nome VARCHAR(255) NOT NULL, 
   email VARCHAR(255) NULL, 
   data_contratacao DATE NULL, 
   salario DOUBLE NULL, 
   ativo BIT(1), 
   PRIMARY KEY(id_funcionario));
Listagem 2. DDL para criação da tabela de funcionario

Depois que a tabela foi criada, clique com o botão direito sobre ela e escolha a opção Data > Edit, que abrirá a tabela para edição. Nesta janela, clique sobre os campos para adicionar conteúdo e novos registros. A Figura 15 mostra um exemplo de preenchimento desta tabela. Cada registro representa um funcionário e todos serão listados pela nossa aplicação de exemplo.

Editando a tabela criada diretamente do Eclipse
Figura 15. Editando a tabela criada diretamente do Eclipse

Construindo RESTful Web Services

Em nossa aplicação de exemplo, usaremos serviços RESTful para prover os dados à camada de apresentação. Para a construção dos serviços usaremos a implementação de referência da API JAX-RS, chamada Jersey, que é disponibilizada como open source e provê grande facilidade na criação de serviços através de anotações. O endereço para download do Jersey se encontra na seção Links.

Há várias maneiras de baixar o Jersey, a principal é utilizando o Maven (usado, entre outras coisas, para automatizar o processo de gestão de dependências entre bibliotecas). Neste artigo, vamos baixar apenas um arquivo .zip, que possui as bibliotecas principais para se utilizar o Jersey. Deste modo, acesse o endereço indicado na seção Links e na página que se abrirá, procure por “zip of Jersey”. Em seguida baixe o arquivo indicado no site.

Assim que concluir o download, descompacte e copie o conteúdo da pasta lib para dentro da pasta WEB-INF/lib do seu projeto no Eclipse. Ela deverá apresentar o conteúdo como mostra a Figura 16.

Bibliotecas do Jersey copiadas para dentro do WEB-INF/lib
Figura 16. Bibliotecas do Jersey copiadas para dentro do WEB-INF/lib

Agora que já temos as bibliotecas necessárias, vamos criar duas classes: Funcionario e FuncionarioRest. A primeira classe define a principal entidade do sistema, o funcionário. Vamos utilizá-la para transportar os dados pesquisados no banco. Além disso, o Jersey usará esta classe para a conversão de objeto Java para JSON, que será o formato de resposta em nossos serviços RESTful. A conversão de Java para JSON será feita automaticamente pelo Jersey baseado nas anotações JAXB da classe. A Listagem 3 mostra como deve ficar a classe Funcionario.

Note que usamos apenas uma anotação JAXB, @XmlRootElement. Esta anotação vai informar ao framework de conversão do Jersey que esta classe pode ser transformada e que seu elemento raiz começará pela definição da própria classe.

Para a classe FuncionarioRest, por enquanto adicione o conteúdo da Listagem 4. Vamos usar este código temporariamente apenas para testar se o ambiente está funcionando corretamente. As anotações que utilizamos definem o caminho que publicaremos o serviço (@Path), seguido da definição do método que receberá as requisições HTTP GET (@GET) e qual o formato do dado que o serviço retornará, neste caso vamos retornar JSON (@Produces(“application/json”)).

Para finalizar, precisamos configurar o Jersey para interceptar todas as requisições que tiverem o endereço começando com /rest/*. Portanto, edite o arquivo WEB-INF/web.xml e adicione o código da Listagem 5 entre as tags.


package com.minhaapp.model;
   
  import java.sql.Date;
  import javax.xml.bind.annotation.XmlRootElement;
   
  @XmlRootElement
  public class Funcionario {
   
   private int idFuncionario;
   private String nome;
   private String email;
   private Date dataContratacao;
   private Double salario;
   private boolean ativo;
   
  //getters and setters 
  }
Listagem 3. Código da classe Funcionario

package com.minhaapp.rest;
 
import java.util.*;
import javax.ws.rs.*;
 
import com.minhaapp.model.Funcionario;
 
@Path("/funcionarios")
public class FuncionarioRest {
 
 @GET
 @Produces("application/json")
 public List<Funcionario> getListaFuncionarios(){
  
  Funcionario funcionario = new Funcionario();
  funcionario.setNome("Ari Dias");
  
  List<Funcionario> funcionarios = new ArrayList<Funcionario>();
  funcionarios.add(funcionario);
 
  return funcionarios;
 }
}
Listagem 4. Código da classe FuncionarioRest

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
 </servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
Listagem 5. Configuração do WEB-INF/web.xml

Feito isto, testaremos se o nosso serviço REST está corretamente configurado e se a transformação de Java para JSON está ocorrendo corretamente. Para isto, faça uma nova implantação no ambiente do Elastic Beanstalk. Caso queira acelerar o processo de implantação, você pode configurar o serviço para usar implantações incrementais. Assim, apenas o que foi alterado será enviado para o ambiente do Beanstalk, acelerando o processo de upload. Para configurar a implantação incremental, clique duas vezes sobre o servidor e marque a opção Use Incremental Deployments, localizada na coluna do lado direito.

Após o final da implantação, sua aplicação abrirá na URL padrão, index.jsp. Substitua o nome deste arquivo por rest/funcionários. Se tudo estiver correto, o Jersey interceptará esta requisição e a entregará ao método getListaFucionário() da classe FuncionarioRest. O resultado deverá ser como mostra a Figura 17.

Testando o retorno do serviço REST
Figura 17. Testando o retorno do serviço REST

Listando os funcionários com o ExtJS

Agora que já temos o serviço que provê os dados, precisamos criar uma camada de apresentação. Para isto, usaremos um framework moderno e já maduro para construção de aplicativos Web, o ExtJS.

A empresa responsável por este framework se chama Sencha e oferece vários outros produtos, inclusive um dos mais conceituados frameworks para desenvolvimento de aplicativos móveis, o Sencha Touch. Para mais informações, veja o endereço de referência na seção Links. Do site da empresa Sencha, baixe o ExtJS. Lembre-se de escolher a licença que melhor se adapte ao seu modelo comercial, já que o ExtJS possui vários modelos de licença. Para este artigo, já que estamos disponibilizando todo o código fonte de exemplo, vamos baixar a versão compatível com a GPL license v3, que incentiva programas Open Source.

Após baixar o ExtJS, crie uma pasta no seu projeto chamada extjs, dentro de WebContent. Depois copie do arquivo baixado a pasta resources e o arquivo ext-all.js. Ao final deste processo, a estrutura da pasta WebContent/extjs deverá estar exatamente como a da Figura 18.

Estrutura da pasta extjs
Figura 18. Estrutura da pasta extjs

Feito isto, vamos alterar o arquivo index.jsp e adicionar a tabela editável que exibirá todos os funcionários vindos diretamente do nosso serviço REST (/rest/funcionarios). Assim, primeiramente temos que adicionar o arquivo de estilo do ExtJS e seu arquivo JavaScript. A Listagem 6 mostra o arquivo index.jsp e o cabeçalho após a inclusão dos arquivos do ExtJS.


<head>
    <meta http-equiv="Content-type" content="text/html; 
        charset=utf-8">
    <title>Lista Funcionários Web</title>
     <link rel="stylesheet" href="extjs/resources/
         css/ext-all.css" type="text/css" />
    <script type="text/javascript" 
        src="extjs/ext-all.js"></script>
  </head>
Listagem 6. Configuração do arquivo index.jsp

O ExtJS também conta com o carregamento automático de dependências, porém não usaremos neste artigo. No entanto, usaremos a capacidade de MVC do framework. Para isso, a primeira coisa que definiremos será o nosso modelo de dados, que será informado dentro do próprio arquivo index.jsp. Segue o código da definição do modelo:


  Ext.define('Funcionario', { 
   extend: 'Ext.data.Model',
   fields: [ 'nome', 'email',
   { name: 'dataContratacao', type: 'date', dateFormat: 'd/m/Y' },
   { name: 'salario', type: 'float' },
   { name: 'ativo', type: 'bool' }] });

Com o modelo de dados pronto, vamos usar um recurso do ExtJS chamado de Store. Podemos considerar uma Store como se fosse um datasource. Uma Store será conectada à tabela e será responsável por carregar e salvar todas as alterações feitas nos dados. Para traduzir a mensagem JSON do servidor no modelo de dados que definimos no ExtJS, a Store deve possuir um Reader. Este Reader interpretará cada registro de funcionário vindo do servidor e criará para cada registro um objeto chamado Record. A seguir, temos a definição da Store que será definida no arquivo index.jsp, dentro da tag:


Ext.create('Ext.data.Store', {
 model: 'Funcionario',
 proxy: { type: 'ajax', url: 'rest/funcionarios',
 reader: { type: 'json'}
 } });

Observe que definimos o modelo dos dados e logo após especificamos uma URL (/rest/funcionarios), de onde virá a lista de funcionários.

Feito isto, temos o modelo e a origem dos dados configurados. Nos falta agora criar a interface gráfica. Para isso, usaremos outro componente do ExtJS, a tabela editável. A Listagem 7 mostra o código necessário para adicionar este componente em nossa página.

Na primeira linha você encontra a chamada à função que criará a tabela: Ext.create('Ext.grid.Panel', { … })

Logo em seguida vêm os parâmetros como, por exemplo, o ID do componente DOM onde a tabela deverá ser desenhada (renderTo), qual a origem de dados (store), título e tamanho.


Ext.create('Ext.grid.Panel', {
     title: 'Lista de Funcionários',
     store: store,
     renderTo: 'listafuncionarios-grid',
     width: 600,
     height: 400,
     frame: true,
     columns: [{
        header: 'Nome',
        dataIndex: 'nome',
        flex: 1,
        editor: {
           allowBlank: false
        }
     }, {
        header: 'Email',
        dataIndex: 'email',
        width: 160,
        editor: {
           vtype: 'email'
        }
     }, {
        xtype: 'datecolumn',
        header: 'Data Contratação',
        dataIndex: 'dataContratacao',
        width: 90,
        editor: {
            xtype: 'datefield',
            format: 'd/m/Y'
        }
     }, {
        xtype: 'numbercolumn',
        header: 'Salário',
        dataIndex: 'salario',
        format: '$0,0',
        width: 90,
        editor: {
           xtype: 'numberfield'
        }
     }, {
         header: 'Ativo?',
         dataIndex: 'ativo',
         width: 60,
         editor: {
            xtype: 'checkbox'
         }
     }]
  });
Listagem 7. Código para adicionar uma tabela editável

Depois definimos as colunas e relacionamos cada uma delas com um campo do modelo de dados (Funcionario). Assim que os dados do serviço chegarem à página, o Reader interpretará os dados de cada funcionário, criando o Record e salvando dentro do Store. No entanto, precisamos ainda definir o que será mostrado em cada linha da tabela. Por isso a necessidade de mapear cada coluna com um atributo do funcionário. Para isso, usamos o atributo dataIndex. O código a seguir mostra a configuração de uma coluna na tabela:


columns: [{
 header: 'Nome',
 dataIndex: 'nome'
}]

Ainda no arquivo index.jsp, adicione dentro da tag um componente, que será usado pelo framework para posicionar a tabela criada. Veja a definição do na sequência:

Com isto, já podemos reimplantar a aplicação e testar o resultado da integração da tabela com nosso serviço REST. Lembre-se que até o momento o nosso serviço REST ainda não retorna dados do banco de dados. A Figura 19 mostra o resultado atual da lista de funcionários. Vale lembrar também que o código completo da aplicação estará disponível no site da Java Magazine.

Tabela editável exibindo lista temporária de funcionários
Figura 19. Tabela editável exibindo lista temporária de funcionários

Buscando os dados

Agora que a integração entre a camada de apresentação e os serviços REST está funcionando, vamos ao passo final, conectar ao banco de dados e buscar a lista de todos os funcionários. Para conectar ao banco de dados precisaremos da URL de conexão. Esta URL pode ser encontrada na configuração da conexão com o banco dentro do Eclipse. Portanto, clique sobre a conexão com o banco dentro da aba Data Source Explorer e escolha a opção Properties.

A URL apresentada estará no seguinte formato: jdbc:mysql://xxxxxxx.yyyyyyy.sa-east-1.rds.amazonaws.com:3306/ebdb

Esta URL define o endereço de conexão JDBC do seu banco, e onde você vê xxxx.yyyy, na sua conexão estará o endereço do seu banco.

Como o nosso objetivo neste artigo não é a criação de uma camada complexa de acesso a dados, criaremos uma classe bem simples para fazer a conexão com o banco e executar a query que buscará os dados dos funcionários. Esta classe serve apenas para representar a busca dos dados e não deve ser usada para um sistema em produção.

A Listagem 8 mostra o código da classe FuncionarioDAO. Veja que usamos a URL de conexão diretamente em nosso código, porém esta URL poderia ser configurada como um parâmetro da aplicação através do próprio Elastic Beanstalk.

Não vamos explorar neste artigo todas as possibilidades de parametrização que o Elastic Beanstalk fornece, entretanto, vale ressaltar algumas que são mais usadas, como: memória alocada para o heap da JVM, habilitar debug remoto, Session Stickiness entre o Load Balancer e os servidores (mantém o usuário conectado ao mesmo servidor durante toda a sua sessão) e parâmetros genéricos, configurados como chave-valor.

Ainda sobre a conexão para acesso a dados, não se esqueça de baixar o driver do MySQL e adicionar na biblioteca da aplicação, dentro da pasta WEB-INF/lib. Para baixar o driver do MySQL, acesse o endereço informado na seção Links.

Criada a classe de acesso a dados, vamos então alterar o código do serviço REST para usá-la. A Listagem 9 mostra o código final do método do serviço. Observe o uso da nova classe para criar a lista de funcionários (List).

Com isso, estamos quase prontos para testar a nossa tabela editável com todos os funcionários listados. Em seguida, uma nova implantação será necessária para atualizar a aplicação nos servidores do Elastic Beanstalk. Quando a implantação terminar, carregue novamente a página index.jsp. Ela deverá mostrar a tabela editável semelhante à da Figura 20.

Tabela editável exibindo a lista de funcionários
Figura 20. Tabela editável exibindo a lista de funcionários

  import java.sql.*;
  import java.util.*;
   
  import com.minhaapp.model.Funcionario;
   
  public class FuncionarioDAO {
   
   public List<Funcionario> buscaFuncionarios() {
   
    List<Funcionario> funcionarios = new ArrayList<Funcionario>();
   
    Connection con = null;
    Properties connectionProps = new Properties();
    connectionProps.put("user", "xxxxxx");
    connectionProps.put("password", "xxxxxx");
    Statement stmt = null;
    String query = "select id_funcionario, nome, email, 
     data_contratacao, salario, ativo from funcionario";
    try {
     Class.forName("com.mysql.jdbc.Driver");
     con = DriverManager
       .getConnection(
          "jdbc:mysql://xxxxxx.yyyyyy.sa-east-1.rds.amazonaws.com:3306/ebdb",
          connectionProps);
     stmt = con.createStatement();
     ResultSet rs = stmt.executeQuery(query);
     while (rs.next()) {
      int idFuncionario = rs.getInt("id_funcionario");
      // carrega o restando dos atributos do recordset
      funcionarios.add(new Funcionario(idFuncionario, nome, email,
        dataContratacao, salario, ativo));
     }
    } catch (Exception e) {
     // tratamento de erros
    } finally {
     // fechando a conexão
    }
    return funcionarios;
   }
  }
Listagem 8. Código da classe de acesso a dados

package com.minhaapp.dao

 @GET
   @Produces("application/json")
   public List<Funcionario> getListaFuncionarios(){
    FuncionarioDAO funcDAO = new FuncionarioDAO();
    List<Funcionario> funcionarios = funcDAO.buscaFuncionarios();
    return funcionarios;
   }
Listagem 9. Versão final do serviço REST

Testando a elasticidade da sua aplicação

Para testar a elasticidade da sua aplicação, vamos supor o seguinte cenário: sua aplicação ficou pronta, e agora você fará várias campanhas de marketing ao longo dos próximos meses. Algumas campanhas serão veiculadas na parte da manhã, pela TV e outras serão através de marketing online, em grandes portais. Desta maneira, você já sabe que terá picos de acesso, porém não sabe o tamanho do sucesso que terá.

Neste cenário, você tem dois caminhos: a compra de uma infraestrutura necessária de forma antecipada (upfront), porém sem a certeza de que ela será suficiente, além do investimento realizado no trabalho de gestão de tudo que foi adquirido; ou, como descrevemos no início do artigo, você pode optar por uma infraestrutura elástica, como a fornecida pelo Elastic Beanstalk.

Como abordado anteriormente neste artigo, a sua aplicação deve estar preparada para suportar grandes volumes de tráfego em momentos de pico. No entanto, quando este volume decrescer, o ideal é que ela também consuma menos recursos computacionais, fazendo com que seu custo de infraestrutura e de gestão acompanhe o momentum da sua aplicação, sem investimentos adiantados, sem grandes custos de gerenciamento e diminuindo os riscos.

Quando se trata da plataforma da AWS, isso significa configurar um Auto Scaling Group. Você pode ver a configuração atual dentro da janela de configuração do seu ambiente, dando um duplo clique no servidor configurado pelo toolkit. Ao invés de usarmos a configuração fornecida pelo toolkit, usaremos o console da web, onde temos mais opções. Para abrir diretamente o console da web, clique com o botão direito sobre o servidor e acesse a opção Amazon Web Services > Go to AWS Management Console. Uma página será aberta no seu navegador padrão. Nesta página, expanda a opção Environment Details e clique em Edit Configuration. Em seguida, acesse a aba Auto Scaling e deixe sua configuração conforme mostra a Figura 21.

O Auto Scaling Group define o número mínimo e máximo de servidores através dos parâmetros Minimum e Maximum Instance Count. Logo abaixo você poderá escolher se deseja que os servidores sejam distribuídos automaticamente entre Availability Zones diferentes, ou seja, entre datacenters geograficamente distribuídos. O atributo Cooldown permite configurar a quantidade de segundos que o serviço deve esperar depois de tomada uma decisão de aumentar ou diminuir o número de servidores.

A segunda parte desta tela definirá as métricas do gatilho que aumentará ou diminuirá o número de servidores. Em nosso exemplo, vamos utilizar a quantidade de requisições, medidas a cada 1 minuto. Caso a quantidade de requisições que atingirem o Load Balancer ultrapassar a quantidade de 20, um servidor será adicionado ao grupo. Caso baixe de 20 requisições, um servidor será removido. Vale lembrar que a quantidade máxima e mínima de servidores sempre será respeitada.

Configuração do Auto Scaling Group
Figura 21. Configuração do Auto Scaling Group

Do seu navegador, acesse algumas vezes a aplicação no intervalo de um minuto. Assim você fará com que a configuração do Auto Scaling Group dispare novas instâncias de servidores automaticamente, com a sua aplicação já instalada e configurada. Quando você parar com as requisições, as novas instâncias serão terminadas, já que o limite inferior de acessos foi alcançado.

Nota: Para cada aplicação, a métrica utilizada como gatilho deve ser analisada. Muitas vezes a quantidade de requisições não é suficiente para diagnosticar que seus servidores estão sobrecarregados. Há várias métricas disponíveis, por exemplo: utilização de CPU, tráfego de rede, escrita em disco, tempo de resposta, etc.

A Figura 22 mostra a nova realidade da arquitetura da sua aplicação. Observe que adicionamos agora mais servidores no Auto Scaling Group e o banco de dados.

Arquitetura final da aplicação
Figura 22. Arquitetura final da aplicação

Conclusão

Os serviços de Cloud Computing oferecidos pala Amazon Web Services proporcionam novas fronteiras para a sua aplicação. O que antes era difícil, como implantar em poucos minutos sua aplicação em diferentes datacenters ou aumentar e diminuir sua infraestrutura baseada na demanda, agora está ao alcance de todos.

Esta flexibilidade vem viabilizando várias iniciativas de Startups, que precisam crescer rapidamente caso o sucesso repentino bata a porta, além de diminuir o investimento inicial. E para as empresas de grande porte, este modelo reduz drasticamente os custos de construção e gestão da infraestrutura, além de prover dinamismo em novos projetos e processos de inovação.

Esse novo modelo de computação vem sendo adotado massivamente em todo o mundo, tanto em mercados maduros como nos emergentes. Sem dúvida podemos considerar que Cloud Computing já é uma realidade e está ao alcance de todos. E você, quanto tempo ainda vai esperar para levar a sua aplicação para a Nuvem?