I’m big fan of JRuby. The Ruby language’s flexibility with the JVM’s power give to us a big weapon to create amazing applications.
Durante esse feriado de natal, estive testando o suporte a JRuby no Google App Engine. Conseguir rodar tanto uma aplicação feita com Sinatra quanto uma feita em Rails 2.3.10. Infelizmente a gem google-appengine ainda não suporta o Rails 3, mas esse suporte já está sendo desenvolvido.
Então pesquisando no Github achei um gist mostrando como gerar uma aplicação com Rails 2.3.10 e DataMapper, infelizmente não funcionou como deveria. Mas ao analisar percebi que o problema era não está incluindo o DataMapper::Resource no model, então fiz um fork do gist e modifiquei, testei e agora tudo está funcionando. Para acessar o gist clique aqui e divirta-se.
Esse é o primeiro post de uma séria voltada para como melhorar o desempenho de seu site/sistema web. Hoje em dia, trabalhar com desenvolvimento web envolve vários fatores. Um deles é o desempenho, desenvolver um sistema/site que tenha uma performance boa também envolve diversos aspectos. Existem algumas extensões para o firefox capaz de testar o desempenho da sua camada de visão, são eles o yslow do Yahoo! e o Page Speed do Google. Ambos tem basicamente as mesmas funcionalidades, que no geral se resume a testar a performance da sua camada de visão e lhe dá dicas de como melhora-las. Ele lhe avisa, por exemplo, quando você tem uma imagem grande e está reduzindo sua visualização no html ou css. Dentre outras coisas, tais como: habilitar a compressão GZIP, diminuir o tamanho dos cookies, habilitar o cache para determinadas áreas/arquivos. Enfim, é uma extensão super simples de usar e que não pode faltar a um Desenvolvedor web.
Um das principais fontes de dúvida para quem está começando a aprender JSF é o componente SelectOneMenu. Basta uma simples garimpada no google e você confirmará isso. Diversas soluções para o uso do SelectOneMenu são indicadas, uma das que mais vejo é utilizar um converter para converter o objeto selecionada na SelectOneMenu no objeto desejado. Porém eu prefiro uma maneira que acho mais simples, que irei mostrar a seguir. No nosso exemplo, terei um objeto do tipo “Classe” que representará uma classe de alunos, cada classe contem um objeto do tipo “Professor”. Ao cadastrar uma classe o usuário deverá selecionar o professor em uma determinada lista. Então vamos lá: Teremos um backing bean chamado ClasseBean que conterá uma objeto do tipo classe.
public class ClasseBean {
private Classe classe;
private ClasseDao classeDao;
private List<SelectItem> listaItem;
private int professorSelecionado;
public ClasseBean() {
classe = new Classe();
classeDao = new ClasseDao();
listaItem = getLista();
}
public List<SelectItem> getLista() {
ArrayList<SelectItem> lista = new ArrayList<SelectItem>();
ProfessorDao professorDao = new ProfessorDao();
List<Professor> resultado = (List<Professor>) professorDao.listAll();
for (Professor teste : resultado) {
SelectItem item = new SelectItem(teste.getId(), teste.getNome());
lista.add(item);
}
return lista;
}
public String salvar() {
ProfessorDao professorDao = new ProfessorDao();
professor = professorDao.procurar(professorSelecionado);
this.classe.setProfessor(professor);
classeDao.salvar(classe);
classe = new Classe();
return "listarClasses";
}
//métodos getters e setters omitidos
}
No exemplos não irei me apegar a camada de persistência, devendo essa ter sido criada previamente pelo programador e conter os métodos de busca pelo ID e buscar todos os registros.
Iremos começar pelo método getLista(), nesse método é criado uma lista de SelectItem que será usada como exibição, os objetos SelectItem recebem como parametro no construtor dois atributos, o primeiro é a chave do selectItem (que será igual ao id do professor) e o valor de exibição (que no nosso caso será o nome do professor).
Já o método salvar() utilizar o ProfessorDao para efetuar uma busca através do atributo professorSelecionado (o valor desse atributo será igual a chave do item escolhido no SelectOneMenu, que no nosso caso será o id do professor. Lembra-se do: “SelectItem item = new SelectItem(teste.getId(), teste.getNome());” ) após isso o atributo professor do objeto Classe é setado e o o objeto é persistido.
Agora iremos para a criação da página jsf:
<h:selectOneMenu value="#{classeBean.professorSelecionado}">
classeBean.listaItem}">
<f:selectItems value="#{classeBean.listaItem}"/>
</h:selectOneMenu>
O atributo value do SelectOneMenu recebe como parametro o atributo que receberá o valor da chave do atributo selecionado da lista.
E utilizamos o selectItems para informar em qual atributo está a lista de SelectItem’s a ser exibida.Esse post faz parte de uma série que estou preparando sobre o hibernate, o primeiro foi sobre a extensão especial Hibernate Spatial e esse segundo irei falar sobre um pouco sobre um poderoso recurso do Hibernate, a API Criteria. Nesse tutorial não irei entrar em detalhes sobre configuração do Hibernate, assume-se que você tem o hibernate pré-configurado, irei apenas falar da API. Primeiro criaremos nossa entidade exemplo “Cliente” :
package modelo;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
*
* @author lucas
*/
@Entity
public class Cliente implements Serializable {
@Id
@GeneratedValue
private int id;
private String nome;
private int idade;
private String cpf;
private double saldo;
public String getCpf() {
return cpf;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
this.idade = idade;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public double getSaldo() {
return saldo;
}
public void setSaldo(double saldo) {
this.saldo = saldo;
}
}
Até aqui nada de novo, marcamos a classe com a anotação @Entity, para indicar que é uma entidade e marcamos o atributo id com as anotações @Id e @GeneratedValue, a primeira diz que esse atributo é a chave primaria e segunda que seu valor será gerado automaticamente. O cliente também tem um atributo saldo, que representará um valor de saldo, tecnicamente o cliente não deveria possuir um saldo e sim um objeto conta e a conta possuir um saldo, porém como o objetivo desse tutorial é demonstrar a api Criteria, não me apeguei a regras de modelagem OO.
Agora criaremos a classe HibernateUtil, que irá conter um método estático que devolve um objeto Session. Com essa classe não precisaremos ficar instanciando o objeto Session toda vez que precisarmos acessar o banco. O próprio netbeans tem um assistente que gera automaticamente essa classe.
package util;
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
/**
* Hibernate Utility class with a convenient method to get Session object.
*
* @author lucas
*/
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() {
return sessionFactory.openSession();
}
}
Agora criaremos um Dao genérico com os métodos padrão em todos os DAO’s, evitando assim o trabalho de implementar os mesmos métodos em todos os DAO’s.
package Dao;
import org.hibernate.Session;
import org.hibernate.Transaction;
import util.HibernateUtil;
/**
*
* @author lucas
*/
public class Dao<T> {
private Class classe;
private Session session;
protected Session getSession() {
return session;
}
public Dao(Class classe) {
this.session = HibernateUtil.getSession();
this.classe = classe;
}
public void salvar(T objeto){
session.save(objeto);
}
public void remover(T objeto){
Transaction ts = session.beginTransaction();
session.save(objeto);
ts.commit();
}
public void atualizar(T objeto){
Transaction ts = session.beginTransaction();
session.update(objeto);
ts.commit();
}
public T load(long id){
return (T) session.load(classe, id);
}
}
Utilizamos na declaração da classe o tipo parametrizado T (de type), indicando que essa classe terá um tipo de Objeto.
No seu construtor, ela receberá um objeto que definirá o tipo usado na classe e utiliza o HibernateUtil para receber uma session. Observe que o método getSession() do Dao genérico é protected pois suas classes filhas precisarão acessa-lo para seus próprios métodos.
Agora criaremos o ClienteDao, que herdará todos os métodos do Dao genérico, sendo assim não será necessário criar os métodos básicos (Salvar, Atualzar, Remover e Carregar).
package Dao;
import java.util.Collection;
import modelo.Cliente;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
/**
*
* @author lucas
*/
public class ClienteDao extends Dao<Cliente> {
public ClienteDao(){
super(Cliente.class);
}
public Collection<Cliente> buscaPorNome(String nome){
Criteria c = getSession().createCriteria(Cliente.class);
c.add(Restrictions.ilike("nome", nome));
c.addOrder(Order.asc("idade"));
return c.list();
}
public int qtdeTotalCliente(){
Criteria c = getSession().createCriteria(Cliente.class);
c.setProjection(Projections.rowCount());
return (Integer) c.uniqueResult();
}
public int totalSaldo(){
Criteria c = getSession().createCriteria(Cliente.class);
c.setProjection(Projections.sum("saldo"));
return (Integer) c.uniqueResult();
}
}
Agora conheceremos o poder da API Criteria.
No método buscaPorNome, é recebido como parametro uma String que representa o nome do Cliente a ser buscado.
Em seguida é criado o objeto Criteria, através do método createCriteria() e esse recebe como argumento o tipo de objeto a ser pesquisado, como o objeto está mapeado para uma tabela do banco (eu não demonstrei aqui como mapear, porque como disse não é o objetivo do artigo) a API Criteria já sabe exatamente em qual(is) tabela(s) buscar.
Na linha seguinte utilizamos o método add() para refirnarmos a busca, no nosso caso adicionamos uma restrição através do ilike() do objeto Restrictions e passamos dois parâmetros o primeiro é o campo que será aplicada a restrição e o segundo o valor da restrição. Então no nosso caso informamos que queremos apenas os registros com o campo nome igual ao valor da variável nome.
Para melhorar ainda mais a busca, podemos definir a ordem que os objetos será apresentados. Para isso na linha seguinte usamos o método addOrder() e usamos o objeto Order para definir a ordem, que no nosso caso será o campo idade.
Na linha seguinte é usado o método list() que retorna uma lista de objetos que se encaixa no perfil informado ou null caso não encontre nada.
No método qtdeTotalCliente() é retornado um inteiro com a quantidade total de registro de Clientes salvos no banco. Para isso é utilizado o método setProjection e é passado como parâmetro o que queremos fazer, no caso utilizamos o método rowCount() do Projections para contar a quantidade de registros.
Para finalizar usamos o uniqueResult() para retornar a quantidade de registros.
E para finalizar o artigo, no totalSaldo() estamos utilizando também o setProjection para somar os valores de um determinado campo de todos os registros do banco, para isso utilizamos o método sum() do objeto Projections
Bom, no geral é isso. A API Criteria é muito poderosa, podemos ser utilizada para realizar (quase) todas as queries que você desejar, porém muita gente acha mais rápido e produtivo escrever as queries utilizando a HQL (Hibernate Querie Language) que irei mostrar no próximo artigo.Esse tutorial tem como objetivo fazer uma introdução ao uso do Hibernate Spatial juntamente com o banco de dados postgresql e a extensão espacial postgis. Nesse exemplo estarei utilizando o netbeans 6.8. Para começar, crie um projeto Java no netbeans, clique com o botão direito sobre o projeto e adicione as bibliotecas do “Hibernate” e “Hibernate JPA” ambas disponíveis no netbeans. Você também irá precisar das seguintes bibliotecas:
Adicione todas as listadas acima ao projeto. Agora iremos criar o hibernate.cfg.xml, o próprio netbeans fornece um utilitário para criação. Clique com o botão direito no projeto, selecione o menu Novo -> Outro -> Hibernate -> Assistente para configuração do hibernate. Configure seu hibernate da seguinte maneira: [sourcecode language=”xml”] <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE hibernate-configuration PUBLIC “-//Hibernate/Hibernate Configuration DTD 3.0//EN” “http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd”> <hibernate-configuration> <session-factory> <property name=”hibernate.dialect”>org.hibernate.dialect.PostgreSQLDialect</property> <property name=”hibernate.connection.driver_class”>org.postgresql.Driver</property> <property name=”hibernate.connection.url”>jdbc:postgresql://localhost/teste</property> <property name=”hibernate.connection.username”>postgres</property> <property name=”hibernate.connection.password”>web</property> <property name=”hibernate.show_sql”>true</property> <property name=”hibernate.format_sql”>true</property> <mapping class=”modelo.Evento”/> </session-factory> </hibernate-configuration> [/sourcecode] Agora iremos criar a classe “Eventos” que será nossa entidade. Ela irá conter o atributo Id que será um inteiro, descrição que será uma string contendo a descrição e o atributo ponto que será do tipo geográfico “Point”. [sourcecode language=”java”] package modelo; import com.vividsolutions.jts.geom.Point; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.annotations.Type; /** * * @author lucas */ @Entity public class Evento implements Serializable { @Id @GeneratedValue private long id; private String descricao; @Type(type=”org.hibernatespatial.GeometryUserType”) @Column(columnDefinition=”Point”) private Point ponto; public String getDescricao() { return descricao; } public void setDescricao(String descricao) { this.descricao = descricao; } public long getId() { return id; } public void setId(long id) { this.id = id; } public Point getPonto() { return ponto; } public void setPonto(Point ponto) { this.ponto = ponto; } } [/sourcecode] Agora criaremos a classe HibernateUtil, que possuirá um atributo SessionFactory do hibernate, um método que retorne uma Session criada pelo SessionFactory e um bloco de código, todos estáticos. O próprio netbeans possui uma opção de criar automaticamente o HibernateUtil, ela está no mesmo menu que foi usado anteriormente para gerar o arquivo de configuração. [sourcecode language=”java”] package util; import org.hibernate.Session; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.SessionFactory; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static Session getSession() { return sessionFactory.openSession(); } } [/sourcecode] Criaremos agora a classe que irá ler a configuração do hibernate e a partir dos mapeamentos das classes irá gerar automaticamente as tabelas do banco. [sourcecode language=”java”] package util; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; /** * * @author lucas */ public class GeraBanco { public static void main(String args[]){ Configuration conf = new AnnotationConfiguration(); conf.configure(); SchemaExport se = new SchemaExport(conf); se.create(true, true); } } [/sourcecode] O próximo passo é mapear a entidade Evento no hibernate, para isso adicionaremos abaixo do último ‘property’ a linha a seguir: [sourcecode language=”xml”] <mapping class=”modelo.Evento”/> [/sourcecode] Deixando o hibernate.cfg.xml da seguinte maneira: [sourcecode language=”xml”] <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE hibernate-configuration PUBLIC “-//Hibernate/Hibernate Configuration DTD 3.0//EN” “http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd”> <hibernate-configuration> <session-factory> <property name=”hibernate.dialect”>org.hibernate.dialect.PostgreSQLDialect</property> <property name=”hibernate.connection.driver_class”>org.postgresql.Driver</property> <property name=”hibernate.connection.url”>jdbc:postgresql://localhost/teste</property> <property name=”hibernate.connection.username”>postgres</property> <property name=”hibernate.connection.password”>web</property> <property name=”hibernate.show_sql”>true</property> <property name=”hibernate.format_sql”>true</property> <mapping class=”modelo.Evento”/> </session-factory> </hibernate-configuration> [/sourcecode] E por fim iremos trabalhar na classe main: [sourcecode language=”java”] import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Point; import modelo.Evento; import org.hibernate.Session; import org.hibernate.Transaction; import util.HibernateUtil; /** * * @author lucas */ public class Main { public static void main(String[] args) { Evento evento = new Evento(); evento.setDescricao(“Testando”); Geometry geom = null; evento.setPonto((Point) geom); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(evento); tx.commit(); session.close(); } } [/sourcecode] Agora rode o GeraBanco para que a tabela do banco seja criada e em seguinda o main. Após fazer isso dê uma conferida no banco e se tiver ocorrido tudo bem o registro estará lá.O Hibernate Spatial é uma extensão do famoso framework de persistência Hibernate. Ele faz o mapeamento objeto relacional de tipos de dados geográficos. Para quem trabalha com desenvolvimento de SIG é uma excelente idéia dá uma conferida.
Ele suporta a maioria das funções da OGC (Open Geospatial Consortium) além de suportar também os SGBD Oracle 10g/11g, Postgresql/Postgis, and MySQL.
O site oficial é http://www.hibernatespatial.org/ e para quem trabalha com a plataforma .NET NHibernate
Uma coisa que sempre gosto de fazer quando estou programando usando JSF, é criar uma classe mensageira para facilitar o trabalho com mensagens (de erro, informação e etc..).
Essa classe, me livra do trabalho de:
package lucasallan.com.blog.exemplo
import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
/**
*
* @author Lucas Allan Cardoso
*/
public class Mensageiro {
private static ResourceBundle bundle = ResourceBundle.getBundle(“messages”, FacesContext. getCurrentInstance().getViewRoot().getLocale());public static void errorMsg(String msg){ msg = bundle.getString(msg); FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR,msg, msg); FacesContext fc = FacesContext.getCurrentInstance(); fc.addMessage(“erro”, fm); }public static void infoMsg(String msg){ msg = bundle.getString(msg); FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); FacesContext fc = FacesContext.getCurrentInstance(); fc.addMessage(“info”, fm); } } |
Se é boato ou verdade eu não sei, o fato é: o rails vem crescendo de maneira assustadora e é claro que grandes empresas como RedHat, SUN e etc… não iam ficar de fora disso.
Não é atoa que em 2006 a SUN contratou o Charles Nutter e Tom Enebo para colocar pra frente o projeto JRuby, o que deve permitir codigos Ruby serem executados na JVM.
Agora é esperar para ver.
Fonte:
http://blog.seatecnologia.com.br/articles/2008/10/20/jboss-on-rails