quinta-feira, maio 31, 2012

Android: Apache Cordova

Olá estimados seguidores, obrigado pela constante visita e apreciação.

Hoje, resolve inovar um pouco a temática, vou abordar um start de desenvolvimento mobile com Android (que é em Java \o/) mas utilizando o projeto Cordova da Apache. Este projeto me chamou bastante a atenção, pois, como ele é possível que desenvolvamos aplicações mobile para Android :), iOs :) e até para o WindonwsPhone :( rsrs mas, deixando o preferencialismo de lado, sigamos!

Mas além do projeto Cordova se mostrar multiplataforma, o que é excelente, o que me deixou mais empolgado foi a forma de desenvolvimento, pois, "não" necessitamos, diretamente, utilizar a linguagem nativa de cada plataforma. Todo o desenvolvimento é realizado por meio de HTML e JavaScript, isso mesmo! Segmento este, que a maioria dos desenvolvedores estão(amos) acostumados.

O objetivo deste poste é mostrar a configuração do Apache Cordova num projeto Android (ahhh já testei no iOs, ficou show) e realizamos uma interação simples.

Obs: este post não irá demonstrar a configuração do ambiente de desenvolvimento android, é considerado que o mesmo já esteja devidamente pronto!

IMPLEMENTAÇÃO

Utilizando o Eclipse e o emulador android, o primeiro passo realizar o download dos artefatos do Cordova para serem acoplados ao projeto, o conteúdo está disponível em: http://incubator.apache.org/cordova/#download, ele já vem com um pacote de artefatos para cada uma das plataformas mobile citadas.

Feito isto, criaremos um projeto Android no Eclipse, com a seguinte configuração:


Tendo-se criado o projeto, na raiz do mesmo, crie uma pasta (folder) com o nome: lib
No diretório /assets, crie uma pasta (folder): www (path será: /assets/www);

Copie o arquivo cordova-1.7.0.jar (baixado no link acima) para o diretório lib;
Copie o arquivo cordova-1.7.0.js para o diretório www.
Finalmente, copie o diretório xml para /res;

Pronto! Neste momento, todas as dependência foram adicionadas. 

Para que o projeto tenha visibilidade aos fontes do Cordova, adicione o artefato cordova-1.7.0.jar no classpath da sua app mobile

Abra o arquivo AndroidManifest.xml, e adicione o seguinte conteúdo entre as tags <uses-sdk.../> e <application.../> :

<supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY" />


Por último, adicione a propriedade android:configChanges="orientation|keyboardHidden"na tag <activity>, deste modo:
<activity
            android:name=".CordovaHelloActivity"
            android:label="@string/app_name" 
            android:configChanges="orientation|keyboardHidden">

Ufa! Acabaram-se as configurações!

Vamos ao desenvolvimento: crie dentro do diretório www, anteriormente criado, o arquivo index.html, que deverá conter:
<!DOCTYPE HTML>
<html>
<head>
<title>Cordova</title>
<script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
<script type="text/javascript">

 function mensagem() {
  navigator.notification.alert("Mensagem cordova app for android!", null , "Ser Java!", "Ok");
 }

</script>
</head>
<body>
<h1>Primeira aplicação Mobile em HTML</h1>
<input type="button" value="Acao" onclick="mensagem()"></input>
</body>
</html>

Observe que este conteúdo, nada mais é, que implementação HTML e JavaScript, este deverá originar uma página com um botão, e ao acionar este, uma mensagem deverá ser exibida.

Resta agora direcionarmos a Activity para a página criada, então abra a classe CordovaHelloActivity e edite do seguinte modo:

package br.com.serjava.cordovahello;

import android.os.Bundle;
import org.apache.cordova.DroidGap;

public class CordovaHelloActivity extends DroidGap {

 @Override
 public void onCreate(Bundle saveInstanceState) {
  super.onCreate(saveInstanceState);
  super.loadUrl("file:///android_asset/www/index.html");
 }
}



Para testar, publique sua aplicação no seu emulador android 4.03 ou dispositivo compatível, o resultado será:

Embora tenha um "trabalhinho" inicial de configuração, pessoalmente, achei bem bacana o desenvolvimento de apps mobile deste modo: usando-se HTML e javascript!

Espero que tenham gostado!

Para maiores informações, consulte a documentação preliminar do projeto Cordova acessando: http://docs.phonegap.com/en/1.7.0/index.html

segunda-feira, maio 07, 2012

JPA: ManyToMany

Olá PessoAll!

Primeiramente, gostaria de agradecer a todos que têm seguido e contribuído com a divulgação deste meu humilde blog e, pelos positivos feedbacks que tenho recebido. Fico feliz não apenas por apreciarem o conteúdo que disponibilizo, mas por contribuírem com a divulgação do amplo ecossistema Java, que sustenta desde grandes organizações até muitos de nós rs!


Neste post vou dar continuidade ao uso de relacionamentos com JPA, neste, verificaremos como implementar uma relação do tipo N:N (muitos para muitos - @ManyToMany). Para demonstrar este relacionamento, darei continuidade no projeto já iniciado nos posts de JPA anteriormente, até então temos a relação 1:N entre Produto e Categoria.

Contexto: do que já foi implementado até o momento, consegue-se categorizar os produtos, logo, facilmente obtemos todos os produtos de uma dada categoria. Imagine que queremos catalogar todos os produtos que um usuário (cliente) visite, para que futuramente, possa-se traçar um perfil de consumo. O que envolve nisto: logo, um usuário poderá ver mais de um produto, e um produto será visualizado por mais de um usuário, o que caracteriza a relação N:N.

Modelagem

Como dito, teremos um relacionamento N:N entre cliente e produto, para contemplar este requisito, nossa modelagem ficará da seguinte forma:


Para efetuarmos as alterações, temos o seguinte sql:

create table cliente (
id_cliente serial,
nome  varchar(70),
primary key (id_cliente));

create table cliente_produto_rel (
id_cliente integer,
id_produto integer,
primary key (id_cliente, id_produto),
foreign key (id_cliente) references cliente (id_cliente),
foreign key (id_produto) references produto (id_produto));

IMPLEMENTAÇÃO

O primeiro passo, é procedermos a modelagem ORM da nova entidade (cliente) e realizar o mapeamento bi-direcional entre cliente e produto. Assim, temos:


Cliente:
package br.com.serjava.persistencia.entity;

//imports omitidos

/**
 * The persistent class for the cliente database table.
 * 
 */
@Entity
public class Cliente implements Serializable {
 private static final long serialVersionUID = 1L;

 @Id
 @SequenceGenerator(name="CLIENTE_IDCLIENTE_GENERATOR", sequenceName="CLIENTE_ID_CLIENTE_SEQ", allocationSize=1)
 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CLIENTE_IDCLIENTE_GENERATOR")
 @Column(name="id_cliente")
 private Integer idCliente;

 private String nome;

 //bi-directional many-to-many association to Produto
 @ManyToMany
 @JoinTable(
   name="cliente_produto_rel"
   , joinColumns={
    @JoinColumn(name="id_cliente")
    }
   , inverseJoinColumns={
    @JoinColumn(name="id_produto")
    }
   )
 private List listaProdutos;

        //getters and setters
Produto:
package br.com.serjava.persistencia.entity;

//imports omitidos
/**
 * The persistent class for the produto database table.
 * 
 */
@Entity
public class Produto implements Serializable {
 private static final long serialVersionUID = 1L;

 @Id
 @SequenceGenerator(name="PRODUTO_IDPRODUTO_GENERATOR", sequenceName="PRODUTO_ID_PRODUTO_SEQ")
 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PRODUTO_IDPRODUTO_GENERATOR")
 @Column(name="id_produto")
 private Integer idProduto;

 @Column(name="nm_produto")
 private String nomeProduto;

 private Integer quantidade;

 private Double valor;

 //bi-directional many-to-many association to Cliente
    @ManyToMany(mappedBy="listaProdutos")
 private List listaClientes;

 //bi-directional many-to-one association to Categoria
    @ManyToOne
 @JoinColumn(name="id_categoria")
 private Categoria categoria;

Observe que ambas entidades, Cliente e Produto, possuem uma List referenciando-se uma a outra, o que caracteriza o relacionamento N:N. No mapeamento da entidade Cliente, observe que o join que interliga as 2 entidades por meio da entidade rel, é realizado por meio da anotação própria: @JoinTable.

Devemos criar a camada de persistência da nova entidade, Cliente. Faça de forma análoga as demais entidades (em caso de dúvidas consulte os posts anteriores sobre JPA).

Considerando que já temos produtos persistidos no database, vamos recuperá-los e associálos a um novo cliente que supostamente está visitando aqueles produtos em uma página; como o método save implementado no dao genérico (DAOImpl) retorna o objeto persistido (cliente), conseguiremos também obter os produtos associados ao cliente, por meio da relação, como mostra a implementação:


ProdutoDAO produtoDAO = new ProdutoDAOImpl();
  ClienteDAO clienteDAO = new ClienteDAOImpl();
  
  //obtem-se a lista de produtos salvos 
  List<Produto> listaProdutosVisitados = produtoDAO.getAll(Produto.class);
  
  Cliente cliente = new Cliente();
  //atribuição dos produtos a um cliente
  cliente.setListaProdutos(listaProdutosVisitados);
  cliente.setNome("Fábio");
  
  //salva e obtém um cliente sincronizado com o BD
  Cliente clienteSalvo = clienteDAO.save(cliente);
  
  System.out.println("Nome cliente: " + clienteSalvo.getNome());
  System.out.println("Produtos visitados (associados) ao cliente:");
  
  //percorre a lista de produtos associados ao cliente salvo
  for (Produto produto : cliente.getProdutos()) {
   System.out.println(produto.getNomeProduto());
  }

Observe que a relação no banco dá-se mediante a tabela de "rel" entre cliente e produtos. Mas em qual momento fizemos a relação dos identificados das entidades Cliente e Produto? A resposta é: quando atribuímos a lista de produtos ao objeto de cliente, e o JPA realizou todo o trabalho "braçal" pra gente. Veja a tabela associativa como ficou:


Neste exemplo, observe que temos 3 produtos com os ids: 16, 22 e 23. Lembre-se que recuperamos TODOS os produtos para, em seguida, associá-los ao cliente. O cliente Fábio tem o id 4. Logo, se os 3 produtos estão associados ao cliente 3, na tabela de rel, vemos tal relação contemplada!

Observe quanto trabalho o JPA lhe poupou! Espero que tenham gostado!