Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Criar Aplicativos da Web Elaborados, Centrados em Dados, Usando JAX-RS, JPA e Dojo

Desenvolver um aplicativo para gerenciamento de uma liga de futebol

Michael Galpin, Software Architect, eBay
Michael Galpin's photo
Michael Galpin vem desenvolvendo software Java profissionalmente desde 1998. Atualmente, ele trabalha no Ludi Labs, um negócio novo em Mountain View, Calif. Ele possui formação superior em matemática do California Institute of Technology.

Resumo:  O desenvolvimento de um aplicativo elaborado para manipulação de grandes quantidades de dados costumava ser o domínio exclusivo de aplicativos de desktop. Agora, isso pode ser feito em um aplicativo da Web, e não é necessário ser nenhum guru em JavaScript™ para fazê-lo. Aprenda a usar o Dojo Toolkit para criar aplicativos da Web centrados em dados, impressionantes, e conectá-los a um backend nos padrões do JavaEE, como o JAX-RS e a JPA. Essas tecnologias permitem que você use a convenção por meio de princípios de configuração para ligar facilmente aplicativos complexos sem perder tempo no final.

Data:  17/Mai/2011
Nível:  Intermediário Também disponível em :   Inglês
Atividade:  1003 visualizações
Comentários:  


Introdução

Neste artigo, você desenvolverá um aplicativo da Web centrado em dados usando algumas das tecnologias Java do lado do servidor mais recente e o Dojo Toolkit para criação de uma interface de usuário elaborada. Essas tecnologias reduzem significativamente a quantidade de código que se tem de escrever, em ambos os lados, servidor e cliente. Para tirar o máximo deste artigo, é recomendado ter familiaridade com Java e JavaScript. Será necessário ter um Java 1.6 JDK para compilar e executar o código; este artigo usou o JDK 1.6.0_20. Você também precisará de um contêiner de Web Java; este artigo usou o Apache Tomcat 6.0.14. Para a persistência de dados, pode ser usado qualquer banco de dados com um driver compatível com JDCB 2.0. Para manter as coisas simples, foi usado um banco de dados incorporado, o Apache Derby 10.6.1. Este artigo usa o Java API for RESTful Web Services (JAX-RS), com Jersey 1.3 para a implementação do JAX-RS. Será usado também o Java Persistence API (JPA) com Hibernate 3.5.3 para a implementação. Finalmente, este artigo também usou o Dojo Toolkit 1.4. Veja Recursos para obter os links para essas ferramentas.


Dados Durante a Execução com a Java Persistence API

Muitos aplicativos da Web são centrados em dados — eles apresentam dados persistentes e permitem que o usuário crie ou atualize seus dados. Parece bastante simples, mas mesmo quando se trata de algo tão básico como ler e escrever dados de um banco de dados, as coisas podem ficar feias. No entanto, a Java Persistence API (JPA) reduz grandemente a quantidade de código clichê, tedioso, que precisa ser escrito. Vamos ver um exemplo simples de como usar a JPA.

Neste artigo, será desenvolvido um aplicativo simples para gerenciamento de uma liga de futebol jovem. Você começará desenvolvendo um modelo de dados simples para manter controle das equipes na liga e dos jogadores nessas equipes. Usará a JPA para todo o acesso a esses dados. Iniciará com o primeiro dos dois modelos, uma Team. A Listagem 1 mostra essa classe.


Listagem 1. A classe de modelo de dados Team

@Entity
public class Team {
....
....@Id
....@GeneratedValue(strategy = GenerationType.IDENTITY)
....private long id;
....
....private String name;
....
....@OneToMany
....private Collection<Player> players;
....
     // getters and setters........
}

Essa é uma classe anotada JPA típica. Você usa a anotação @Entity para declarar que essa classe será mapeada a um banco de dados. É possível especificar o nome da tabela para a classe ou implementar a convenção de onde usar o mesmo nome que a classe. Em seguida, você anota o campo id da classe. Você deseja que esta seja a primeira chave da tabela, assim usa a anotação @Id para declarar isso. O id não é importante da perspectiva da lógica de negócios; é necessário fazer isso apenas para o banco de dados. Como você deseja que o banco de dados se encarregue do que acontecerá com seus valores, use a anotação @GeneratedValue.

Na listagem 1, também é declarado outro campo, name. Esse será o nome da equipe. Observe que não há nenhuma anotação da JPA nesse campo. Por padrão, ele estará mapeado a uma coluna com o mesmo nome, e isso é o suficiente para os fins deste artigo. Finalmente, cada equipe tem vários jogadores associados a ela. Você usa a anotação @OneToMany para permitir que o tempo de execução da JPA saiba que esta é uma relação gerenciada com uma equipe que tem muitos jogadores. Na sua classe Java, esse é apenas um objeto Player de java.util.Collection do .A listagem 2 mostra a classe Player que está sendo referenciada.


Listagem 2. A classe de modelo de dados Player

@Entity
public class Player {
....
....@Id
....@GeneratedValue(strategy = GenerationType.IDENTITY)
....private long id;
....
....private String firstName;
....
....private String lastName;
....
....private int age;
....
....@ManyToOne (cascade=CascadeType.ALL)
....private Team team;
....
     // getters and setters
}

A classe Player mostrada na listagem 2 é similar à classe Team na listagem 1. Ela tem mais campos, mas, novamente, na maioria dos casos, você não terá de se preocupar em anotá-los. A JPA fará a coisa certa para você. A única diferença entre as listagens 1 e 2 é o modo de especificação do relacionamento entre as classes Player e Team. Neste caso, você usa uma anotação @ManyToOne, porque há muitos Players em uma única Team. Observe que você especificou uma política de cascata. Examine alguma documentação da JPA para selecionar a política de cascata certa para o seu aplicativo. Neste caso, com essa política, é possível criar uma nova Team e um Player, ao mesmo tempo, e a JPA salvará a ambos, o que é conveniente para o aplicativo.

Agora que você declarou essas duas classes, precisará informar ao tempo de execução da JPA como se conectar ao seu banco de dados. Isso é possível criando um arquivo persistence.xml. O tempo de execução da JPA precisa localizar esse arquivo para usar os metadados nele. O modo mais fácil de fazer isso é colocá-lo em um diretório /META-INF que seja subdiretório do seu código de origem (ele deve estar na raiz do diretório de saída das classes compiladas). A listagem 3 mostra o arquivo persistence.xml file.


Listagem 3. O arquivo persistence.xml do aplicativo soccer

<persistence version="1.0"
....xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
....xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
....<persistence-unit name="soccer">
........<class>org.developerworks.soccer.model.Team</class>
........<class>org.developerworks.soccer.model.Player</class>
........<properties>
............<property name="hibernate.dialect" 
                      value="org.hibernate.dialect.DerbyDialect" />
............<property name="hibernate.connection.driver_class"....
                      value="org.apache.derby.jdbc.EmbeddedDriver" />
............<property name="hibernate.connection.url" 
                       value="jdbc:derby:soccerorgdb;create=true" />
............<property name="hibernate.hbm2ddl.auto" value="update" />
............<property name="hibernate.show_sql" value="true" />
............<property name="hibernate.connection.characterEncoding" 
                      value="UTF-8" />
............<property name="hibernate.connection.useUnicode" 
                       value="true" />
........</properties>
....</persistence-unit>
</persistence>

Olhando novamente as listagens 1 e 2, observe que todo o código é JPA genérico. Na verdade, tudo o que é usado são anotações da JPA e algumas de suas constantes. Não há nada que seja específico do seu banco de dados ou da implementação da JPA usada. Como é possível ver na listagem 3, o arquivo persistence.xml é onde as coisas específicas se encontram. Várias implementações de JPA excelentes estão disponíveis, inclusive OpenJPA e TopLink (veja Recursos). Você usou o venerável Hibernate, assim tem várias propriedades específicas do Hibernate especificadas por você. Essas são as coisas mais simples como o driver JDBC e a URL, e algumas coisas úteis como informar ao Hibernate para registrar o SQL em que ele está executando (algo que você definitivamente não desejará fazer em uma situação de produção, mas que é muito útil quando realizado para fins de depuração durante o desenvolvimento).

Também é possível observar na listagem 3 que está sendo usado o banco de dados do Apache Derby. Na verdade, você está usando uma versão integrada do banco de dados. Assim, não é necessário inicializar o banco de dados separadamente nem se preocupar com a sua configuração. Adicionalmente, foi especificado na URL da conexão que o banco de dados deve ser criado automaticamente, e se informou ao Hibernate para criar automaticamente o esquema (essa é a propriedade hibernate.hbm2ddl.auto). Assim, basta executar seu aplicativo, para que o banco de dados e as tabelas sejam criados. Isso é grande para o desenvolvimento, mas é evidente que você desejará configurações diferentes em um sistema de produção. Agora que foi criado todo o código do modelo de dados e o acesso à JPA já foi ativado, vamos examinar a exposição desses dados, de modo que um aplicativo da Web possa tirar proveito disso.


Acesso do RESTful aos Dados com JAX-RS

Se estivesse criando este aplicativo cinco anos atrás, agora seria o momento de começar a criar algumas Java Server Pages (JSPs) ou Java Server Faces (JSFs), ou alguma tecnologia de criação de modelos semelhante. Em vez de criar a UI desse aplicativo no servidor, será usado o Dojo para criá-la no cliente. Tudo o que é necessário fazer é fornecer um modo para que o código do lado do cliente acesse esses dados usando o Ajax. É possível ainda usar uma solução de modelos para fazer algo como isso, mas é muito mais simples usar a API for RESTful Web Services (JAX-RS). Vamos iniciar pela criação de uma classe para leitura de todas as Teams no banco de dados e para criação de novas Teams. A listagem 4 mostra essa classe.


Listagem 4. Classe de acesso a dados de Teams

@Path("/teams")
public class TeamDao {
....
....private EntityManager mgr = 
          DaoHelper.getInstance().getEntityManager();
....
....@GET
....@Produces("application/json")....
....public Collection<Team> getAll(){
........TypedQuery<Team> query = 
                mgr.createQuery("SELECT t FROM Team t", Team.class);
........return query.getResultList();
....}
....
....@POST
....@Consumes("application/x-www-form-urlencoded")
....@Produces("application/json")
....public Team createTeam(@FormParam("teamName") String teamName){
........Team team = new Team();
........team.setName(teamName);
........EntityTransaction txn = mgr.getTransaction();
........txn.begin();
........mgr.persist(team);
........txn.commit();
........return team;
....}
}

A listagem 4 mostra uma classe de objeto de acesso a dados de classe, daí o nome TeamDao. Nós vamos chegar às anotações nessa classe em breve, mas deixe-me primeiro explicar o acesso aos dados. A classe tem uma referência à classe EntityManager da JPA. Essa é uma classe central na JPA e fornece acesso ao banco de dados subjacente. Para o primeiro método, que recupera todas as equipes na liga, use EntityManager para criar uma consulta. A consulta usa a linguagem de consulta da JPA, que é muito similar à SQL. Essa consulta simplesmente obtém tudo das Teams. Para o segundo método, simplesmente crie uma nova Team usando o nome da equipe informado, crie uma transação, salve a nova equipe e confirme a transação usando a classe EntityManager. Todo esse código é código JPA baunilha, já que todas essas classes e interfaces são parte da API básica.

Agora que a parte da JPA na listagem 4 está entendida, vamos falar sobre os aspectos do JAX-RS. Primeiramente, é possível observar a anotação @Path que expõe isso para os clientes baseados em HTTP. A cadeia de caractere /teams especifica o caminho relativo para essa classe. O caminho completo da URL será <host>/SoccerOrg/resources/teams. /SoccerOrg especificará o caminho para o aplicativo da Web (evidentemente, é possível configurá-lo para algo diferente ou removê-lo por completo). A parte /resources será usada para especificar um terminal do JAX-RS. /teams corresponde à anotação @Path e especifica quais classes do JAX-RS usar.

Em seguida, o primeiro método, getAll, tem uma anotação @GET nele. Isso especifica que esse método deverá ser chamado se a solicitação GET do HTTP for recebida. Em seguida, o método tem uma anotação @Produces. Essa declara o tipo MIME da resposta. Neste caso, você deseja produzir JSON, visto ser a coisa mais fácil de usar com o cliente baseado em JavaScript.

Isso é tudo o que é necessário fazer para usar o JAX-RS para expor essa classe aos clientes da Web. No entanto, talvez esteja se perguntando: se esse método retornar uma java.util.Collection de objetos Team, como isso será enviado aos clientes da Web? A anotação @Produces declara que você deseja enviar como JSON, mas como o JAX-RS serializará isso no JSON? Tudo o que é necessário, é incluir mais uma anotação na classe Team mostrada na listagem 5.


Listagem 5. Classe Team modificada

@XmlRootElement
@Entity
public class Team {
....
// unchanged from Listing 1
........
}

Incluindo a anotação @XmlRootElement, o JAX-RS pode agora transformar essa classe em um objeto JSON. É possível reconhecer essa anotação. Ela não pertence ao JAX-RS; é parte da API do Java Architecture for XML Binding (JAXB) que compõe a plataforma Java 1.6 principal. Essa anotação parece indicar que ela é para XML, mas ela pode ser, na verdade, usada para diversas saídas do JAXB, inclusive o JSON. Há muitas outras anotações do JAXB, mas essa é a única que você precisa usar neste caso. Simplesmente serão usadas convenções para serializar todos os campos da classe Team para JSON.

Agora, voltemos à listagem 4 e examinemos o segundo método da classe, o método createTeam. Esse método usa a anotação @POST para especificar que ele deve ser chamado quando uma solicitação POST do HTTP é recebida. Em seguida, ele usa a anotação @Consumes para declarar que tipo de solicitação POST ele pode consumir. O valor especificado aqui corresponde ao cabeçalho de tipo de conteúdo da solicitação HTTP. Nesse caso, ele é especificado como x-www-form-urlencoded. Esse é o tipo que você receberá quando um formulário HTML for submetido. Assim, esse método será chamado quando um formulário HTML for submetido com o terminal /SoccerOrg/resources/teams. Finalmente, observe que o método apresenta um único parâmetro de entrada, uma cadeia de caractere denominada teamName. Note que esse parâmetro está decorado com a anotação @FormParam. Essa informa ao tempo de execução do JAX-RS para procurar um parâmetro de formulário no corpo da solicitação de nome teamName (o valor da anotação) e ligar o parâmetro a uma variável informada na chamada do método. Desse modo, é possível facilmente manusear um envio de formulário simples e ligá-lo ao código. Isso pode ficar confuso se você tiver um monte de dados sendo enviados. Nesse caso, talvez seja apropriado usar uma abordagem mais estruturada. A listagem 6 mostra um exemplo de como criar um objeto Player .


Listagem 6. Manipulação de dados POST estruturados usando o JAX-RS

@Path("/players")
public class PlayerDao {
....private EntityManager mgr = 
          DaoHelper.getInstance().getEntityManager();
....
....@POST
....@Consumes("application/json")
....@Produces("application/json")
....public Player addPlayer(JAXBElement<Player> player){
........Player p = player.getValue();
........EntityTransaction txn = mgr.getTransaction();
........txn.begin();
........Team t = p.getTeam();
........Team mt = mgr.merge(t);
........p.setTeam(mt);
........mgr.persist(p);
........txn.commit();
........return p;
....}
....
....@GET
....@Produces("application/json")
....public List<Player> getAllPlayers(){
........TypedQuery<Player> query = 
............mgr.createQuery("SELECT p FROM Player p", Player.class);
........return query.getResultList();
....}
}

A classe PlayerDao na listagem 6 é muito similar à classe TeamDao da listagem 5. A principal diferença que você deseja examinar é seu método addPlayer. Esse manipula as solicitações POST do HTTP, similar ao método createTeam no TeamDao. No entanto, ele consome application/json — ou seja, está esperando dados JSON. Isso implica em duas coisas. Primeiro, a solicitação precisa especificar um tipo de conteúdo application/json de modo que o método seja chamado. Em seguida, o corpo da postagem deve ser dados JSON. Observe que o parâmetro de entrada desse método é do tipo JAXBElement<Player>, ou seja, é um wrapper do JAXB ao redor de um objeto Player. Isso informa ao JAX-RS para analisar automaticamente os dados postados em um wrapper JAXBElement, assim não é necessário ter o incômodo de escrever código de análise com esse objetivo. Observe que no corpo do método, leva apenas uma linha de código para obter um objeto Player completo que pode ser usado para salvar o novo Player no banco de dados usando a JPA.

A última coisa a ser feita para concluir a história do JAX-RS é mostrar a configuração necessária para ligar tudo isso. Para tal, é necessário apenas modificar o web.xml do seu aplicativo. A Listagem 7 mostra o web.xml do aplicativo.


Listagem 7. web.xml do aplicativo

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
....xmlns="http://java.sun.com/xml/ns/javaee" 
....xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
....xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
....id="Soccer_Org" version="2.5">
  <display-name>SoccerOrg</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>JAXRS-Servlet</servlet-name>
   
 <servlet-class>com.sun.jersey.spi.container.servlet.
ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
     
 <param-value>org.developerworks.soccer.model;org.developerworks.
soccer.web</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>JAXRS-Servlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
  </servlet-mapping>
</web-app>

Como é possível ver na listagem 7, o seu aplicativo tem um único servlet declarado. Esse é o servlet fornecido pelo Jersey, a implementação do JAX-RS que está sendo usada. Você passa um parâmetro de inicialização ao servlet — os pacotes contendo as classes sobre as quais o JAX-RS deve saber. Neste caso, há um pacote onde são mantidos os modelos de dados e outro que mantém os objetos de acessos a dados. Você precisa que os modelos sejam descobertos de modo que o JAX-RS possa convertê-los em JSON. Evidentemente, é necessário que os DAOs sejam descobertos de modo que o JAX-RS possa encaminhar solicitações para eles. Finalmente, observe o mapeamento do servlet. É aí que a parte /resources dos caminhos URL é especificada. Agora você está pronto para usar todo esse código de backend no cliente para criar uma UI usando o Dojo.


Usando o REST no Cliente com Dojo

O Dojo Toolkit fornece praticamente qualquer tipo de biblioteca ou utilitário que pode ser necessário para desenvolver o lado do cliente do seu aplicativo da Web. Você verá como ele é útil quando trabalhar com Ajax, formulários, JSON e criar as widgets da UI. (No entanto, ele pode fazer muito mais do que isso. Acontece, que isso é tudo o que este exemplo simples necessita.) Em um sistema grande, talvez você queira fazer download do kit de ferramentas completo e um desenvolvimento customizado para obter exatamente o que o seu aplicativo precisa. Neste aplicativo de exemplo, será preciso usar as Google Ajax APIs para obter acesso às diversas partes do conjunto de ferramentas necessário. Além de isso ser conveniente, há algumas vantagens interessantes de desempenho visto que as cópias do Dojo do Google são fornecidas pela content delivery network (CDN) altamente eficiente do Google.

O seu aplicativo é centrado a dados, assim para iniciar é necessário incluir algum dado nele. Usaremos o Dojo para criar uma UI de inclusão de Teams. A listagem 8 mostra todo o código necessário para isso.


Listagem 8. Incluindo Teams usando o Dojo

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Harness</title>
        <link rel="stylesheet" type="text/css" 
       
 ....href="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dijit
/themes/soria/soria.css"/>
        <script type="text/javascript"
 src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js"
 djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
....function init(){
....    var btn = dijit.byId("addTeamBtn");
....    dojo.connect(btn, "onClick", function(event){
....    ....event.preventDefault();
            event.stopPropagation();
            dojo.xhrPost({
                  form : dojo.byId("addTeamForm"),
            ....handleAs: "json",
            ....load : function(data){
            ........addTeam(data);
            ........alert("Team added");
            ....},
            ....error : function(error){
                ....    alert("Error adding team: " + error);
            ....}
            });
....    });
....}
</script>
</head>
<body class="soria">
....Add a Team<br/>
....<form method="POST" action="/SoccerOrg/resources/teams" id="addTeamForm">
........<label for="teamName">Team Name:</label>
........<input name="teamName" type="text" id="teamName"
 dojoType="dijit.form.TextBox"/>
........<button type="submit" id="addTeamBtn" dojoType=
"dijit.form.Button">Add Team</button>
....</form>
....<script type="text/javascript">
........dojo.require("dijit.form.Button");
....    dojo.require("dijit.form.TextBox");
....    dojo.addOnLoad(init);
....</script>
</body>
</html>

Observe na listagem 8 que você faz referência à biblioteca base do Dojo a partir da CDN do Google. Uma vez feito isso, é possível solicitar cada parte adicional desejada do Dojo usando a função dojo.require (consulte o bloco de scripts na parte inferior da listagem 8). Observe que você acabou de criar um formulário HTML normal, mas são usados alguns atributos extras específicos do Dojo. Isso informa ao Dojo para incluir algum estilo adicional nos elementos visuais e adicionar alguns recursos extras aos elementos DOM correspondentes. Você informa ao Dojo uma vez para executar a função init e tudo o mais é carregado (todos os componentes do Dojo). Nessa função, é usada a função dijit.byId para obter uma manipulação no botão do formulário. Dijit é a biblioteca de widgets do Dojo. É possível usar dojo.byId para fazer referência a qualquer elemento do DOM por seu ID, mas o dijit.byId similar fornece um widget com recursos extras (se o elemento estiver marcado como widget, o que é o caso do botão na listagem 8).

O Dojo é usado para associar um manipulador de eventos para quando o botão é clicado. O manipulador para o envio do formulário e, em vez disso, usa o Ajax por meio da função dojo.xhrPost. Essa função facilita a postagem (POST) de formulários HTML. Ela descobre o terminal do Ajax inspecionando o atributo action do formulário HTML. Ela também lê todos os elementos do formulário e os passa para o POST do Ajax. Quando obtém uma resposta do servidor, ela chama a função load que é transmitida para xhrPost. Observe que você declarou que JSON será retornado pelo servidor configurando a propriedade handleAs passada para a função xhrPost. Você verá a função addTeam em breve, mas pode transmitir o objeto de dados diretamente porque o Dojo já analisou com segurança os dados JSON em um objeto JavaScript utilizável. Esta função addTeam é usada em conjunto com outro formulário, para a inclusão de Players. A Listagem 9 mostra o HTML desse formulário.


Listagem 9. Inclusão do formulário Player

Add a Player<br/>
<form id="addPlayerForm" action="/SoccerOrg/resources/players">
....<label for="firstName">First Name:</label>
....<input name="firstName" id="firstName" type="text"
 dojoType="dijit.form.TextBox"/>
....<label for="lastName">Last Name:</label>
....<input type="text" name="lastName" id="lastName"
 dojoType="dijit.form.TextBox"/><br/>
....<label for="age">Age:</label>
....<input type="text" name="age" id="age"
 dojoType="dijit.form.TextBox"/><br/>
....<label for="team">Team:</label>
....<select id="team" name="team" dojoType="dijit.form.
Select"></select>
....<button type="submit" id="addPlayerBtn" dojoType=
"dijit.form.Button">Add Player</button>
</form>
<script type="text/javascript">
     dojo.require("dijit.form.Select");
     dojo.addOnLoad(loadTeams);
</script>

Esse formulário, a exemplo do presente na listagem 8, é um formulário HTML válido. No entanto, ele também tem os atributos específicos do Dojo incluídos nos seus elementos. Observe que ele tem um elemento SELECT que servirá como lista suspensa das equipes (Teams), de modo que o usuário pode selecionar qual Team incluir para o novo Player. Esses são dados dinâmicos que precisam ser carregados do servidor. Observe que você incluiu outra função para ser chamada na inicialização — a função loadTeams. E essa função que carrega as equipes do servidor. A listagem 10 mostra essa função, além da função addTeam que você viu referenciada na listagem 9.


Listagem 10. As funções loadTeams e addTeam

var teams = {};
function loadTeams(){
....var select = dijit.byId("team");
....dojo.xhrGet({
........url: "/SoccerOrg/resources/teams",
........handleAs:"json",
........load : function(data){
............var i = 0;
............for (i in data.team){
................addTeam(data.team[i]);
............}
........},
........error : function(error){
............alert("Error loading team data: " + error);
........}
....});
}
function addTeam(team){
....teams[team.id] = team;
....var select = dijit.byId("team");
....var opt = {"label":team.name, "value":team.id};
....select.addOption(opt);
}

Aqui, mais uma vez, os utilitários Ajax do Dojo são usados para acessar os dados fornecidos pelo terminal do JAX-RS criado anteriormente. Desta vez, é usado o dojo.xhrGet, que faz uma solicitação GET do HTTP para um terminal do Ajax. Neste caso, é necessário especificar a URL, mas por outro lado, ele seria muito similar ao xhrPost visto na listagem 9. Finalmente, é possível ver o método addTeam. Esse, mais uma vez, usa os recursos extras de widget do Dojo para incluir facilmente novas opções na lista suspensa que mostra as equipes. Agora que você viu como o formulário do jogador é criado, examine o código que manipula os envios (veja a listagem 11).


Listagem 11. Incluindo um novo Player

var button = dijit.byId("addPlayerBtn");
dojo.connect(button, "onClick", function(event){
.... event.preventDefault();
       event.stopPropagation();
       var data = dojo.formToObject("addPlayerForm");
       var team = teams[data.team];
       data.team = team;
       data = dojo.toJson(data);
       var xhrArgs = {
           postData: data,
           handleAs: "json",
           load: function(data) {
               alert("Player added: " + data);
               dojo.byId("gridContainer").innerHTML = "";
               loadPlayers();
           },
           error: function(error) {
               alert("Error! " + error);
           },
           url: "/SoccerOrg/resources/players",
           headers: { "Content-Type": "application/json"}
       };
       var deferred = dojo.xhrPost(xhrArgs);
});

Este código enviará dados para o método PlayerDao.addPlayer já mencionado na listagem 6. Esse código espera que o objeto Player seja serializado em uma estrutura de dados do JSON. Primeiro, o Dojo é usado mais uma vez para ligar um manipulador de eventos a um clique de botão no formulário. Em seguida, você usa a função de conveniência do Dojo, dojo.formToObject, para transformar todos os dados do formulário em um objeto JavaScript. Então, esse objeto JavaScript é modificado um pouco para corresponder com a estrutura esperada no servidor. Em seguida, a função dojo.toJson do Dojo é usada para transformar o objeto em uma cadeia de caractere do JSON. Em seguida, a sequência é passada para o dojo.xhrPost, do mesmo modo como o formulário addTeam foi enviado. Observe que é incluído um cabeçalho do HTTP, Content-Type, para assegurar que ela será encaminhada para o método PlayerDao.addPlayer.

O xhrPost mais uma vez tem uma função load que será chamada assim que a solicitação do Ajax retornar com uma resposta bem-sucedida do servidor. Neste caso, ela é claramente um elemento na página denominado gridContainer e chamando uma função denominada loadPlayers. Esse é outro widget do Dojo usado para mostrar todos os jogadores. A listagem 12 mostra o HTML e o JavaScript usados para tal.


Listagem 12. HTML e JavaScript da grade de jogadores

<style type="text/css">
    @import
 "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojox/grid/resources/Grid.css";
    @import
 "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojox/grid/resources/soriaGrid.css";
    .dojoxGrid table { margin: 0; }
    html, body { width: 100%; height: 100%; margin: 0; }
</style>
<script type="text/javascript">
function loadPlayers(){
....var pStore = new dojox.data.JsonRestStore({
........target: "/SoccerOrg/resources/players"
....});
....pStore._processResults = function(data, deferred){
........return {totalCount:deferred.fullLength || data.player.length,
                    items: data.player};
....};
       var pLayout = [{
           field: "firstName",
           name: "First Name",
           width: "200px"
       },
       {
           field: "lastName",
           name: "Last Name",
           width: "200px"
       },
       {
           field: "age",
           name: "Age",
           width: "100px"
       },
       {
           field : "teamName",
           name : "Team",
           width: "200px"
       }];

       var grid = new dojox.grid.DataGrid({
           store: pStore,
           clientSort: true,
           rowSelector: "20px",
           structure: pLayout
       }, document.createElement("div"));
       dojo.byId("gridContainer").appendChild(grid.domNode);
       grid.startup();
}
</script>
<div id="gridContainer" style="width: 100%; height: 100%;"></div>
<script type="text/javascript">
    dojo.require("dojox.grid.DataGrid");
    dojo.require("dojox.data.JsonRestStore");
    dojo.addOnLoad(loadPlayers);
</script>

A Listagem 12 mostra o widget DataGrid do Dojo. Esse é um dos widgets mais complexos no Dojo e, portanto, requer algum CSS extra também. Para criar uma grade, é necessário fazer duas coisas. Primeiro, é necessário criar um armazenamento de dados para ela. Neste caso, esses serão os dados do JSON provenientes do seu servidor, assim crie um novo objeto JsonRestStore e aponte-o para a URL no seu servidor que produzirá esses dados. Em seguida, substitua seu _processResults. Você só tem que fazer isso porque é esperado um array de dados JSON e seu terminal JAX-RS produzirá um objeto um pouco mais complicado (ele terá uma propriedade denominada player cujo valor estará no array JSON esperado pelo JsonRestStore). A próxima coisa que a grade precisa são os metadados do layout que informam o que as colunas mostram e qual será a propriedade correspondente no objeto JavaScript. Em seguida, é possível criar a grade e soltá-la na árvore do DOM.

Agora você concluiu o aplicativo de futebol de amostra e tem um modo muito elaborado de mostrar os jogadores de futebol na liga. É possível expandir facilmente este exemplo simples adicionando a edição de jogadores, a classificação da grade ou incluindo mais dados como jogos e resultados.


conclusão

Este artigo mostrou um modo rápido para criar um aplicativo da Web elaborado, centrado em dados. Você usou várias tecnologias-chave para remover código de clichê, tedioso, do lado do servidor e do lado do cliente: JPA, JAX-RS e Dojo. Em muitos casos, as convenções padrão foram usadas para reduzir adicionalmente a quantidade de código necessária para criar o aplicativo da Web. O resultado é um aplicativo da Web muito moderno, criado com o mínimo de código. Todas as tecnologias usadas são extensíveis e têm qualidade de produção, assim é possível expandir confiantemente o aplicativo de amostra (ou seu próprio aplicativo) para casos de uso mais robustos de uma maneira simples. E o melhor é que não há nenhum impedimento. Foram usados padrões abertos no lado do servidor. É possível trocar facilmente as tecnologias de banco de dados, por exemplo. Foram usados REST e JSON no front-end, o que significa que é possível usar um kit de UIs diferente ou conectar facilmente um cliente móvel.



Download

DescriçãoNomeTamanhoMétodo de download
Article source codeSoccerOrg.zip14KBHTTP

Informações sobre métodos de download


Recursos

Aprender

Obter produtos e tecnologias

  • Faça download do Dojo Toolkit.

  • Obtenha o Java SDK. Este artigo usou o JDK 1.6.0_17.

  • Obtenha Apache Tomcat. Este artigo usou o Apache Tomcat 6.0.14.

  • Obtenha Apache Derby 10.6.1.0.

  • Jersey é a implementação de referência do JAX-RS: é software livre e tem qualidade de produção.

  • Hibernate é uma implementação da Java Persistence API (JPA). Este artigo usou a Versão 3.5.3.

  • Faça o download das versões de avaliação de produto IBM e tenha em suas mãos ferramentas de desenvolvimento de aplicativo e produtos de middleware do DB2, Lotus, Rational, Tivoli e WebSphere.

Discutir

Sobre o autor

Michael Galpin's photo

Michael Galpin vem desenvolvendo software Java profissionalmente desde 1998. Atualmente, ele trabalha no Ludi Labs, um negócio novo em Mountain View, Calif. Ele possui formação superior em matemática do California Institute of Technology.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=658272
ArticleTitle=Criar Aplicativos da Web Elaborados, Centrados em Dados, Usando JAX-RS, JPA e Dojo
publish-date=05172011
author1-email=mike.sr@gmail.com
author1-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).