Páginas

quarta-feira, 13 de julho de 2011

Adobe lança Beta do AIR 3.0 e do FlashPlayer 11

A Adobe lançou hoje (13/07/2011) o BETA do AIR 3.0 e do FlashPlayer 11, onde foram corrigidas algumas questões de segurança e de performance, também adicionaram suporte a 64bits.

Você poderá fazer o download das versões betas aqui: AIR 3.0 e FlashPlayer11.

Agora é só testar!!!

sexta-feira, 24 de junho de 2011

quinta-feira, 16 de junho de 2011

Flex com Multilinguagem (internacionalização)

Olá!!


Hoje vou mostrar como fazer um sistema Multilinguagem (alterando locales) no Flex. Conforme o exemplo:

*Para ver o fonte, clique com o botão direito do mouse e ViewSource.

Para isso você precisa ter os locales das linguagens. Os locales podem ser baixados nesses links:
Estes locales devem ser colocados no diretório: "{instalaçãodoflex}/sdks/{versaodosdk}/frameworks/locale/".

Configurando o projeto
Clique com o botão direito do mouse no projeto, vá em "properties" depois em "Flex Compiler", em "Additional compiler arguments:" coloque o seguinte:
  -locale en_US pt_BR -source-path+=../locale/{locale}


Ficando assim:


Após configurar o locale do seu projeto, você deve criar as pastas "{projeto}/locale/en_US" e "{projeto}/locale/pt_BR" e adicionar o arquivo "localization.properties" dentro de cada pasta.

en_US
label_selecione_linguagem=Select your language
label_nome=Name
label_sobrenome=Last Name
send_btn=Send

pt_BR
label_selecione_linguagem=Selecione a linguagem
label_nome=Nome
label_sobrenome=Sobrenome
send_btn=Enviar


Para ler estes arquivos faz assim:
<?xml version="1.0" encoding="utf-8"?>
<s:Application viewSourceURL="srcview/index.html"
               xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Script>
        <![CDATA[
            import mx.resources.ResourceBundle;
            
            [Bindable]
            private var locales:Array = ['pt_BR', 'en_US'];
            
            private static const LOCALIZATION:String = 'localization';
            
            private function changeLanguage():void {
                this.resourceManager.localeChain = [cbxLanguage.selectedItem];
            }
        ]]>
    </fx:Script>

    <fx:Metadata>
  [ResourceBundle('localization')]
 </fx:Metadata>

    <mx:Form>
        <mx:FormItem label="{resourceManager.getString( LOCALIZATION , 'label_selecione_linguagem' )}:">
            <mx:ComboBox id="cbxLanguage"
                         change="changeLanguage()"
                         dataProvider="{locales}"/>
        </mx:FormItem>

        <mx:FormItem label="{resourceManager.getString( LOCALIZATION , 'label_nome' )}:">
            <s:TextInput/>
        </mx:FormItem>

        <mx:FormItem label="{resourceManager.getString( LOCALIZATION , 'label_sobrenome' )}:">
            <s:TextInput/>
        </mx:FormItem>

        <s:Button label="{resourceManager.getString( LOCALIZATION , 'send_btn' )}"/>
    </mx:Form>
</s:Application>


sendo a variável LOCALIZATION o nome do arquivo criado (pode ter vários).
para ler cada linha do arquivo utiliza-se:
resourceManager.getString(LOCALIZATION, 'string')


Por hoje é isso!!

Comente!


sábado, 11 de junho de 2011

#FlexMania 2011

Olá!

Este ano ocorre a 3ª edição do FlexMania. É um evento online e gratuito que junta vários palestrantes falando sobre diversos assuntos.

O evento acontece dias 07, 08, 09 e 10 de Julho de 2011.

Eu e todos aqui da @PontoSistemas vamos participar!!

Para saber mais acesse: http://www.flexmania.com.br/

Até mais!

sexta-feira, 10 de junho de 2011

Variáveis Globais no Flex.

Olá.

Neste post vou mostrar como fazer com que uma (ou várias) variável seja utilizada e compartilhe o mesmo valor em toda a aplicação.

Para isto basta criar uma classe, com o método getInstance() e chamar esta classe em qualquer lugar do sistema através do getInstance(), e pronto você terá a mesma variável com o mesmo valor.


Classe de exemplo:

VariaveisGlobais.as
package com.blogspot.desenvolvendoemflex.utils {
 import mx.collections.ArrayCollection;
    
    [Bindable]
    public class VariaveisGlobais {
        private static var instance:VariaveisGlobais;
        
        public var variavel:ArrayCollection;
  
        public static function getInstance():VariaveisGlobais {
            if (instance==null) {
                instance = new VariaveisGlobais();
            }
            return instance;
        }
    }
}


para utiliza-la basta instanciar desta maneira em qualquer parte de seu programa:
            [Bindable]
            public var varGlobal:VariaveisGlobais = VariaveisGlobais.getInstance();

Tenha cuidado ao utilizar desta forma, pois dependendo da quantidade de variáveis e informações, pode ficar pesado o sistema.

Por hoje é isso!

Até a próxima.

Comentem!!

quarta-feira, 8 de junho de 2011

Java + JPA + Hibernate + DAO Genérico

Olá, hoje vou mostrar como fazer um DAO Genérico no Java (contendo SaveOrUpdate, Remove, FindAll, FindByID) que pode ser usado por todos os DAOs. Facilitando a criação de novos projetos, podendo ser usado com a integração com o Adobe Flex através do RemoteObject.

Isto é para quem não quer usar nenhuma espécie de Framework (ex: Spring, que faz isso de uma forma mais genérica).

Primeiramente criei minha classe contendo todos os métodos (save, update, delete, find), para minha classe ficar "genérica" ao invés de receber as entidades específicas, recebe Object (pode passar as Entidades que o java consegue reconhecer). Após criar esta classe contendo os métodos, é só criar os DAOs extendendo da classe genérica, com isso já terá todos os métodos implementados. Podendo fazer validações específicas para cada DAO.

Vamos a prática:

Este é minha classe genérica contendo todos os métodos.
GenericDAO.java
package com.blogspot.desenvolvendoemflex.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;

import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * @author SAMUEL FACCHINELLO
 * @version 1.0
 */
public class GenericDAO {

 /**
  * Salva ou Atualiza dependendo se já existe ou não o objeto no banco de dados. 
  * @param o: Entidade a ser Salva (se ainda não existir) ou a ser Atualizada (se já existir)
  * @return Retorna a Entidade passada como parâmetro.
  * @throws Exception
  */
 public Object saveOrUpdate(Object o) throws Exception {
  Session em = HibernateSessionFactory.getSession();
  Transaction trans = em.beginTransaction();
  try {
   trans.begin();
   em.merge(o);
   trans.commit();
   return o;
  } catch (Exception e) {
   if (trans.isActive()) {
    trans.rollback();
   }
   e.printStackTrace();
   throw e;
  } finally {
   em.close();
  }
 }

 /**
  * Salva ou Atualiza dependendo se já existe ou não o objeto no banco de dados. 
  * @param list: lista das Entidades a serem Salvas (se ainda não existir) ou a serem Atualizadas (se já existir)
  * @return Retorna a Entidade passada como parâmetro.
  * @throws Exception
  */
 public void saveOrUpdateAll(ArrayList<Object> list) throws Exception {
  Session em = HibernateSessionFactory.getSession();
  Transaction trans = em.beginTransaction();
  try {
   trans.begin();
   for (Object o : list) {
    em.merge(o);
   }
   trans.commit();
  } catch (Exception e) {
   if (trans.isActive()) {
    trans.rollback();
   }
   e.printStackTrace();
   throw e;
  } finally {
   em.close();
  }
 }

 /**
  * Remove a Entidade do banco de dados.
  * @param o: Entidade a ser removido do banco de dados.
  * @throws Exception
  */
 public void remove(Object o) throws Exception {
  Session em = HibernateSessionFactory.getSession();
  Transaction trans = em.beginTransaction();
  try {
   trans.begin();
   em.delete(o);
   trans.commit();
  } catch (Exception e) {
   if (trans.isActive()) {
    trans.rollback();
   }
   throw e;
  } finally {
   em.close();
  }
 }

 /**
  * Remove a Entidade do banco de dados.
  * @param list: Lista de Entidades a serem removidas do banco de dados.
  * @throws Exception
  */
 public void removeAll(ArrayList<Object> list) throws Exception {
  Session em = HibernateSessionFactory.getSession();
  Transaction trans = em.beginTransaction();
  try {
   trans.begin();
   for (Object o : list) {
    em.delete(o);
   }
   trans.commit();
  } catch (Exception e) {
   if (trans.isActive()) {
    trans.rollback();
   }
   throw e;
  } finally {
   em.close();
  }
 }

 /**
  * Retorna a lista de itens salvo no banco de dados de acordo com a Entidade passada como parâmetro.
  * @param classe : Entidade que deverá buscar no banco de dados.
  * @return List contendo todos os objetos encontrados da entidade passada como parâmetro.
  */
 @SuppressWarnings("unchecked")
 public static List findAll(Class classe) {
  Session em = HibernateSessionFactory.getSession();
  Query query = em.createQuery("Select a from " + classe.getName() + " a");
  return query.list();
 }

 /**
  * Faz a busca no banco pelo ID da entidade
  * @param classe : Entidade a ser buscada
  * @param id : valor a ser procurado
  * @return Objeto encontrado no banco, caso não encontre será retornado NULL
  * @throws Exception
  */
 @SuppressWarnings("unchecked")
 public static Object findById(Class classe, Object id) throws Exception {
  if (classe == null) {
   throw new Exception("classe não pode ser nula.");
  }

  if (id == null) {
   throw new Exception("id não pode ser nulo.");
  }

  Field[] fields = classe.getDeclaredFields();
  String chave = "";
  for (Field field : fields) {
   if (field.getAnnotation(Id.class) != null) {
    chave = field.getName();
    break;
   }
  }

  if (chave.equals("")) {
   throw new Exception("Annotation @Id não encontrada na classe " + classe.getName());
  }

  Session em = HibernateSessionFactory.getSession();
  Query query = em.createQuery("Select a from " + classe.getName() + " a" +
          " where a." + chave + " = :id").setParameter("id", id);
  query.setMaxResults(1);
  return query.uniqueResult();
 }

 /**
  * Retorna objeto de acordo com a UniqueConstraint definida na Entidade
  * @param classe : Entidade a ser buscada
  * @param ids : Array contendo os IDS a serem buscados (na mesma ordem em que a UniqueConstraint foi definido)
  * @return Objeto encontrado no banco, caso não encontre será retornado NULL 
  * @throws Exception
  */
 @SuppressWarnings("unchecked")
 public static Object findByUniqueConstraints(Class classe, ArrayList<Object> ids) throws Exception {
  if (classe == null) {
   throw new Exception("classe não pode ser nula.");
  }

  if (ids == null || ids.size() == 0) {
   throw new Exception("ids não pode ser nulo.");
  }

  ArrayList<String> chaves = new ArrayList<String>();
  ArrayList<Class> tipos = new ArrayList<Class>();
  Annotation annotation = classe.getAnnotation(Table.class);
  if (annotation != null) {
   Table table = (Table) annotation;

   for (UniqueConstraint uniqueConstraint : table.uniqueConstraints()) {
    for (String column : uniqueConstraint.columnNames()) {
     tipos.add(classe.getDeclaredField(column).getType());
     chaves.add(column);
    }
   }
  } else {
   throw new Exception("Annotation @Table não encontrada na classe " + classe.getName());
  }

  if (chaves.size() == 0) {
   throw new Exception("UniqueConstraints não encontrada na annotation @Table da classe " + classe.getName());
  }

  if (chaves.size() != ids.size()) {
   throw new Exception("O número de parâmetros passados não confere com o número de UniqueConstraints encontrados na classe " + classe.getName() + ". " + ids.size() + " foram passados, mas " + chaves.size() + " eram esparados.");
  }

  String str = "";
  for (int i = 0; i < chaves.size(); i++) {
   if (!ids.get(i).getClass().equals(tipos.get(i))) {
    throw new Exception("Tipos de dados incompatíveis. O parâmetro número " + i + " é incompatível, foi passado:" + ids.get(i).getClass().toString() + " e estava esperando: " + tipos.get(i).toString());
   }
   if (str.length() == 0) {
    str = " where a." + chaves.get(i) + " = " + ids.get(i);
   } else {
    str += " and " + chaves.get(i) + " = " + ids.get(i);
   }
  }

  Session em = HibernateSessionFactory.getSession();
  Query query = em.createQuery("Select a from " + classe.getName() + " a " + str);
  query.setMaxResults(1);
  return query.uniqueResult();
 }
}


Aqui esta meu DAO com uma validação:

BancosDAO.java
package com.blogspot.desenvolvendoemflex.dao;

import com.blogspot.desenvolvendoemflex.entity.Bancos;
import com.blogspot.desenvolvendoemflex.util.GenericDAO;

public class BancosDAO extends GenericDAO {
 public Object saveOrUpdate(Bancos o) throws Exception {
  //TODO: aqui é possivel fazer algumas validações
  if (o.getDescricao() == null || o.getDescricao().equals("")) {
   throw new Exception("Descrição é obrigatório.");
  }
  //TODO: chamo a classe genérica passando por parâmetro minha Entidade "Banco".
  return super.saveOrUpdate(o);
 }
}

A Entidade, contendo as Annotations @Entity e @Table (com @UniqueConstraint para teste do findByUniqueConstraints)
Bancos.java
package com.blogspot.desenvolvendoemflex.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
/*TODO: uniqueConstraints usado para exemplo do FIND, neste caso ele não era necessário*/
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = "cod") })
public class Bancos {

 @Id
 private Integer cod;

 private String descricao;

 public Integer getCod() {
  return cod;
 }

 public void setCod(Integer cod) {
  this.cod = cod;
 }

 public String getDescricao() {
  return descricao;
 }

 public void setDescricao(String descricao) {
  this.descricao = descricao;
 }

}


Para testar, basta chamar o DAO de qualquer lugar, passando os parâmetros necessários em qualquer um dos métodos do GenericDao.

Exemplo de utilização:
  BancosDAO bancosDAO = new BancosDAO();
  Bancos bancos = new Bancos();
  bancos.setCod(1);
  bancos.setDescricao("Banco 1");

  bancosDAO.saveOrUpdate(bancos);

  bancos.setCod(2);
  bancos.setDescricao("Banco 2");
  bancosDAO.saveOrUpdate(bancos);

  ArrayList<Bancos> allBancos = (ArrayList<Bancos>) BancosDAO.findAll(Bancos.class);

  for (Bancos banco : allBancos) {
   System.out.println(banco.getDescricao());
  }

  bancosDAO.remove(BancosDAO.findById(Bancos.class, 2));

  BancosDAO.findAll(Bancos.class);
  
  /*TODO: Passando um array contendo a UniqueConstraint para pesquisa no banco */
  ArrayList<Object> ids = new ArrayList<Object>();
  ids.add(1);
  BancosDAO.findByUniqueConstraints(Bancos.class, ids);
  
  /*TODO: tratando o erro, Descrição é obrigatório */
  bancos.setCod(2);
  bancos.setDescricao("");
  bancosDAO.saveOrUpdate(bancos);


Espero que tenha ajudado.

Obrigado.

Deixe um comentário.

sábado, 28 de maio de 2011

TextArea com atalho para Desfazer e Refazer

Por padrão o componente TextArea do Flex não possui função de desfazer e refazer, com isso resolvi implementar estas duas funções.

Para testar é só digitar um texto, e pressionar Ctrl+Z para desfazer e Ctrl+Y para refazer.

*download do fonte: botão direito "View Source"

Código Fonte:
/*############################################################*/
/*                                                            */
/*   Powered by: Samuel Facchinello                           */
/*   http://desenvolvendoemflex.blogspot.com/                 */
/*                                                            */
/*############################################################*/
package com.blogspot.desenvolvendoemflex.utils {
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;
    import mx.controls.TextArea;
    
    /**
     *
     * @author SAMUEL FACCHINELLO
     * @site http://desenvolvendoemflex.blogspot.com/
     */
    public class TextAreaWithUndo extends TextArea {
        
        /**
         * Variable of control position Undo or Redo
         * */
        [Bindable]
        private var _position:int = -1;
        
        public function get position():int {
            return _position;
        }
        
        /**
         * Variable that stores all typed letters
         * */
        [Bindable]
        private var _array:ArrayCollection = new ArrayCollection();
        
        public function get array():ArrayCollection {
            return _array;
        }
        
        /**
         * Constructor
         *
         */
        public function TextAreaWithUndo() {
            super();
            //add value default
            addValue("");
            
            //add Event on KeyDown
            addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
        }
        
        /**
         * Function with KeyDown
         * @param eventObj: KeyboardEvent
         *
         */
        private function myKeyDown(eventObj:KeyboardEvent):void {
            // Was Ctrl key pressed?
            if (eventObj.ctrlKey) {
                var valueReturn:String = null;
                
                switch (eventObj.keyCode) {
                    
                    case 90: // Was Ctrl-Z pressed?  
                        valueReturn = returnPrevisionValue();
                        break;
                    
                    case 89: // Was Ctrl-Y pressed?  
                        valueReturn = returnNextValue();
                        break;
                    
                    default:
                        break;
                }
                
                //if return exist
                if (valueReturn!=null) {
                    //set text with return functions
                    text = valueReturn;
                    
                    //select last _position in TextArea
                    setSelection(text.length, text.length);
                }
            } else {
                //only adds to the list if any of these characters.
                //list from here: http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000520.html
                if ((eventObj.keyCode>=65&&eventObj.keyCode<=90)||(eventObj.keyCode>=48&&eventObj.keyCode<=57)||(eventObj.keyCode>=96&&eventObj.keyCode<=111)||(eventObj.keyCode>=186&&eventObj.keyCode<=222)) {
                    addValue(text);
                }
            }
        }
        
        /**
         * Function that adds the letters in the array
         * @param value: propertie "text" of TextArea
         *
         */
        private function addValue(value:String):void {
            //it was press Ctrl + Z ever, and was entered some value, clears the values ​​of the position in which this forward
            if (_array.length>0&&_array.length-1>_position) {
                for (var i:int = _array.length-1; i>_position; i--) {
                    _array.removeItemAt(i);
                }
            }
            
            //if the value is being added is equal to the last added, not added!
            if (_array.length>0) {
                if (value==_array.getItemAt(_array.length-1)) {
                    return;
                }
            }
            
            _array.addItem(value);
            _position++;
        }
        
        /**
         * triggered when press Ctrl + Y
         * @return : Returns the next value from the list according to position
         *
         */
        private function returnNextValue():String {
            if (_position+1>=0&&_position+1<_array.length) {
                _position++;
                return _array.getItemAt(_position) as String;
            }
            
            return null;
        }
        
        /**
         * triggered when press Ctrl + Z
         * @return : Returns the Prevision value from the list according to position
         *
         */
        private function returnPrevisionValue():String {
            if (_position-1>=0) {
                _position--;
                return _array.getItemAt(_position) as String;
            }
            
            return null;
        }
    }
}

Adicionei este componente ao Google Code, pode ser visto aqui: http://code.google.com/p/textarea-with-undo/

Qualquer elogio, dúvida, sugestão ou melhoria para o componente, deixe um comentário!!

Abraço, até a próxima.



*Tradução para o inglês com o Google Translate. :)