Maven e o Google Code

Vocês já sabem: eu tenho vários projetos hospedados no Google Code. Acho um lugar legal para projetos pessoais, pequenos. Contudo, acho que carece de mais funcionalidades para abraçar um projeto maior. Para mim e meus projetos, está ótimo. Os dois principais projetos que tenho hospedados lá são o Alfred e o VeículoZ. O primeiro em Java, o segundo em .NET Compact.

Agora também resolvi aderir ao Maven. Nunca havia usado, mas me integrei em um novo projeto no Serpro e que faz uso constante desta ferramenta. Aprendi, gostei e agora estou usando em todos meus novos projetos. O primeiro desafio foi integrar o Maven ao Google Code. Por exemplo, como eu poderia fazer um Deploy de meu site Maven lá? Como eu posso hospedar meu repositório lá? De pouco em pouco, acabei descobrindo o caminho das pedras e compartilho com vocês.

Primeiro, vamos configurar o nosso arquivo POM para que use o Google Code como repositório. A ideia é simples, nosso repositório Subversion servirá como repositório Maven. Então, na seção de repositórios no POM, você coloca algo parecido com este código:

	
		
			alfred-site
			Deployment Server
			ftp://alfredlibrary.org/var/www/alfred/maven
		
		
			googlecode-release
			dav:https://alfredlibrary.googlecode.com/svn/repository/release
		
		
			googlecode-snapshot
			dav:https://alfredlibrary.googlecode.com/svn/repository/snapshot
		
	

Este aí é o repositório do Alfred. Observe a tag ID. O importante agora é você editar seu arquivo settings.xml, que normalmente fica em uma pasta .m2 em sua pasta de usuário. Lá você deve colocar duas entradas na seção de Servers.

		
			googlecode-snapshot
			marlon.carvalho
			meupassword
		
		
			googlecode-release
			marlon.carvalho
			meupassword
		

Não se esqueça também de incluir o Wagon na seção de build. Fica mais ou menos assim:

	
		
			
				org.apache.maven.wagon
				wagon-webdav
				1.0-beta-2
			
		

Pronto, caso você faça agora um mvn deploy, ele colocará seus arquivos no SVN do Google Code. A segundo questão agora é como automaticamente já incluir na lista de Downloads os seus arquivos. Agora você terá que usar um plugin de terceiros. Este plugin se chama Google Code Upload e está localizado em http://maven.riedelcastro.org/gcupload-maven-plugin/. Agora vamos configurar este plugin. Primeiro, temos que adicionar ele na seção de plugins.

			
				org.riedelcastro
				gcupload-maven-plugin
				0.9
				
					googlecode
					false
					alfredlibrary
					
						
							jar
							Featured
						
						
							javadoc
							jar
							Featured
						
						
							sources
							jar
							Featured
						
					
				
			

Observe aí a seção de uploads! Eu estou informando quais arquivos serão enviados para a lista de downloads. No meu caso, o primeiro será o próprio jar do projeto. Depois, o Javadoc e, finalmente, o código fonte. Este plugin tentará encontrar os arquivos alfred-1.0.0.jar, alfred-1.0.0-sources.jar e alfred-1.0.0-javadoc.jar. É importante estar atento ao nome que você coloca ali no <postfix>. Um outro detalhe importantíssimo. Definir no seu settings.xml um Server com seu login e senha no Google Code. A ideia é fazer igual a como foi feito logo acima. Observe neste último trecho de código a tag <serverId>. Coloca aí o ID que você deu lá no settings.xml.

Concluído isto, faça um mvn gcupload:gcupload para fazer um teste e verificar se o arquivo encontra-se lá na lista de downloads.

AuctionX – Informações do Mercado Livre

Fale sério pra mim! Você já fez um sistema, biblioteca, ou algo que o valha, que não tem a mínima ideia se é útil? 🙂 Estou neste dilema. Na falta do que fazer numa noite dessas, resolvi brincar com o Mercado Livre, Java, XML e Maven.

E no que deu isso? Nasceu o AuctionX. Uma biblioteca pra você fazer consultas aos produtos vendidos no Mercado Livre. E aí? Tem utilidade isso? Sei lá, oras! Só sei que eu fiz e tá legal.

Pra usar é bem simples. A API eu fiz com o Hibernate em mente, logo, você verá algumas semelhanças com a classe Criteria deles. Vamos começar com os exemplos. Você quer pesquisar “iphones” vendidos apenas por vendedores certificados (Gold, Platinum):

	Search search = AuctionXService.createSearch("ML");
	Collection<Auction> auctions = search
				.addRestriction(Restriction.onlyCertifiedSellers())
				.search("iphone");

Certo. Legal. Agora você quer pesquisar por “iphones” que não estão em leilão, mas em venda direta. E também que os vendedores sejam da Bahia e mais, que os produtos sejam apenas novos!

	Search search = AuctionXService.createSearch("ML");
	Collection<Auction> auctions = search
			.addRestriction(Restriction.onlyCertifiedSellers())
			.addRestriction(Restriction.buyNow())
			.addRestriction(Restriction.location("BAHIA"))
			.addRestriction(Restriction.onlyNewProducts())
			.search("iphone");

Onde está o projeto? No lugar de sempre: Google Code! http://code.google.com/p/auctionx/. Tá completo? Não. Ainda falta implementar a ordenação do resultado. Mas vai ser rapidinho! 🙂 Vá lá, tou só esperando você me chamar de maluco e coisa de quem não tem o que fazer.

Vaadin

Você já ouviu falar do Vaadin? Ainda não? É um framework muito legal. Ele usa o GWT para construir sua interface, mas trabalha de uma forma um pouco diferenciada. Quer saber mais detalhes? Então acesse o blog do JavaBahia que tem o primeiro artigo que lançarei por lá. É o primeiro, bem introdutório, mas já serve para apresentar um pouco a ideia.
É isso. Ah, claro. Faltou o link!

http://javabahia.blogspot.com/
http://javabahia.blogspot.com/2010/03/vaadin-parte-1.html

Abraços e espero que gostem.

Hibernate e Queries por Exemplos

Você já usou as queries do tipo Example no Hibernate? É uma mão na roda! Serve, principalmente, para fazer filtros de forma bastante simplificada. Como assim? Imagine que você tem um grid onde exibe os dados de uma entidade. Você aí precisa fazer filtros para o usuário pesquisar e exibir apenas os resultados que lhe interessa. Você, normalmente, vai colocar campos desta entidade para que o usuário informe um valor que será usado como filtro.

Imagine uma classe chamada Projeto, que está listada logo abaixo.

@Entity
@Table(name="AUDITA_PROJETO")
public class Projeto implements EntidadePersistente {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;

	@Column(name="IDENTIFICACAO")
	private String identificacao;

	@ManyToOne
	@JoinColumn(name="ID_TIPOPROJETO")
	private TipoProjeto tipoProjeto;

	@ManyToOne
	@JoinColumn(name="ID_SITUACAOPROJETO")
	private SituacaoProjeto situacaoProjeto;

	@Column(name="ATIVO")
	private Boolean ativo;

	@ManyToOne
	@JoinColumn(name="ID_REVISOR")
	private Usuario revisor;

	@ManyToOne
	@JoinColumn(name="ID_AUDITOR")
	private Usuario auditor;

	@Column(name="DATAINICIOPREVISTA")
	private Date dataInicioPrevista;

	@Column(name="DATAFIMPREVISTA")
	private Date dataFimPrevista;

	@ManyToOne
	@JoinColumn(name="ID_SETOR")
	private Setor setor;

      // Aqui vem todos Gets e Sets.

}

Você, então, quer fazer um filtro por Situação do Projeto e pelo Identificador do Projeto. Aí vai lá e coloca dois campos na tela: uma caixa de texto para o usuário digitar o identificador e um combobox para o usuário selecionar uma Situação. Certo? Mas, observe que a query será filtrada pelo identificador, mas não pela situação. Por que? Está dito na documentação do Hibernate: Version properties, identifiers and associations are ignored. By default, null valued properties are excluded.

E como resolver isto, então? Ahhh! Podemos usar reflexão para identificar as associações e colocar elas também! E como é isso? Bom, nossa primeira versão será esta aqui:

	private void gerarExemplosAninhados(Criteria criteria, E entidade) throws DAOException {
		Method[] methods = entidade.getClass().getMethods();
		for(Method method:methods) {

			// Verificar se é um "Get".
			if ( method.getName().indexOf("get") > -1 ) {
				try {
					Object o = method.invoke(entidade, null);
					if ( o instanceof EntidadePersistente ) {
						Example example = Example.create(o).enableLike(MatchMode.ANYWHERE).ignoreCase();
						String m = method.getName().substring(3);
						m = m.substring(0,1).toLowerCase() + m.substring(1);
						criteria.createCriteria(m).add(example);
					}
				} catch (IllegalArgumentException e) {
					throw new DAOException(e);
				} catch (IllegalAccessException e) {
					throw new DAOException(e);
				} catch (InvocationTargetException e) {
					throw new DAOException(e);
				}
			}
		}
	}

Entendeu? Este método ainda pode ser melhorado, é claro. Tratar melhor as exceções. Ir mais abaixo no aninhamento de classes. O que está sendo feito é basicamente “passear” por todos os métodos “get” da entidade e verificar aqueles que são também entidades mapeadas. No meu caso, eu sempre implemento a interface EntidadePersistente nestas classes, assim como você pode ver na entidade Projeto. Se for uma instância desta interface, então incluo ela no Criteria!

Firefox e Certificados sem Senha

Você já tentou importar no Firefox um certificado que foi criado sem uma senha? Por exemplo, você está testando sua aplicação que requer SSL e um certificado válido para conectar. Então, gera uns certificados sem senha, só para facilitar os testes. Tudo certo? Que nada, o sujeito não aceita importar certificados sem senha. Vai dar erro.

O que fazer? Sugestão: mudar a senha de vazio para algo! Como? Primeiro, baixe o OpenSSL. Instale-o também, é claro. Use os comandos abaixo:

  • openssl pkcs12 -in my_cert.p12 -out my_cert.pem
  • openssl pkcs12 -export -in my_cert.pem -out my_new_cert.p12

Ele vai pedir as novas senhas. Basta redefinir e importar no FF. Belezinha? Não posso deixar de dar os créditos ao site Vazio.