Configuração Log4J + Spring

Um post individualista – só pra eu não esquecer disso mais uma maldita vez.

Insira isso aqui no web.xml e pronto, o Log4J vai fazer o append das operações gerenciadas pelo Spring também.

<context-param>
<param-name>log4jConfigLocation></param-name>
<param-value>/WEB-INF/log4j.properties></param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

De nada.

JBoss Forge – Projeto Exemplo JSF / CDI / Connection Pool / Scaffolding / I18N

O título já fala praticamente tudo sobre o post. O que faremos aqui é utilizar o JBoss Forge para a geração de:

– Projeto Web padrão JavaEE;
– JSF;
– CDI (Context and Dependency Injection);
– Connection Pool para o MySQL com GlassFish 3.1.2;
– Scaffolding para uma entidade simples.

O que você precisa ter instalado de antemão (com as variáveis de ambiente devidamente configuradas):
– Apache Maven: http://maven.apache.org/download.html (a página tem as instruções todas);
– JBoss Forge: https://docs.jboss.org/author/display/FORGE/Installation
– Glassfish Community: http://glassfish.java.net/public/downloadsindex.html#top
– Plugin do Glassfish configurado no Eclipse
– Driver JDBC do MySQL: http://cdn.mysql.com/Downloads/Connector-J/mysql-connector-java-5.1.22.tar.gz
– Um schema no MySQL com o nome que você definir. Não, não precisa criar tabela nenhuma.

Vamos parar com o trelelê e gerar logo esse negócio, antes que acabe o horário de almoço aqui na empresa e eu me arrependa de ter começado o post, post esse que já ando postergando há milênios.

1º passo: O Pool no GlassFish:
– Coloque o driver JDBC do MySQL na pasta lib do GlassFish; no meu caso aqui: /home/leonardo/Tools/servers/glassfish3/glassfish/lib;
– Não vou perder tempo explicando como faz a configuração em si, porquê ela é ridícula de simples; na dúvida, Pai-Google-de-Logum-Edê lhe responde, mizinfí: http://rafaelomarques.wordpress.com/2011/01/31/configurando-pool-de-conexoes-com-mysql-e-glassfish-v3/
– Batize o JDBC Resource de jdbc/ProjetoExemplo

2º passo: O projeto no Forge:
Abra o forge (no terminal: forge; no prompt do windows: forge; no mac: sou pobre, não faço ideia);
Crie o novo projeto, de nome ProjetoExemplo, com o pacote base br.com.develoraptor e o nome final de ProjetoExemplo; o forge vai pedir confirmação pra criar a pasta. Você sabe o que fazer (eu espero).

new-project --named ProjetoExemplo --type war --topLevelPackage br.com.develoraptor --finalName ProjetoExemplo

Projeto criado, ok. Agora vamos configurar o danado pra se entender com o JSF e o CDI. Há um plugin pro primefaces, mas eu já testei e te garanto: não funciona. É completamente bugado e não vale o uso. Então vamos com o padrão, que é mais jogo.
O forge vai pedir confirmação pra instalação das libs. O asterisco que aparece nas opções é sempre a versão mais atual, e é a padrão. Use a mais atual, por favor. Vai ser melhor pra você, confia no tio.

scaffold setup --scaffoldType faces

Configurando a internacionalização (I18N para os íntimos – e preguiçosos)

i18n setup --bundleName messages

E adicionando um bundle pro locale pt_BR, porquê eu sou patriota

i18n add-locale --locale pt_BR

Vamos configurar a persistência decentemente, agora, apontando pro nosso pool pré-configurado

persistence setup --provider HIBERNATE --container GLASSFISH_3 --jndiDataSource jdbc/ProjetoExemplo

Criamos, então, a entidade Usuario, que vamos usar como exemplo. O forge é tão simpático que já lhe oferece o pacote “model” como destino da entidade nova.

entity --named Usuario --idStrategy AUTO

Criamos o campo ‘nome’ e o campo ‘dataNascimento’ pra essa entidade

field string --named nome
field temporal --type DATE --named dataNascimento

Criamos, então, as telas do CRUD desta entidade. OPCIONAL, claro, já que ninguém com cérebro usa scaffold em produção

scaffold from-entity br.com.develoraptor.model.Usuario

3º passo: A importação para o Eclipse (porquê uma hora você ia ter que trabalhar de verdade)
Ainda no forge, transforme esse negócio aí num projeto do Eclipse:

mvn eclipse:eclipse

Agora, importe esse projeto pro Eclipse.

File > Import > Existing Projects Into Workspace

Aqui a porca torce o rabo. Por algum motivo, esse projeto não vem como projeto Maven pra dentro do Eclipse. Daí é bem difícil de resolver:

Botão direito no projeto > Configure > Convert to Maven Project

Além disso, as dependências do Hibernate no pom.xml não estão configuradas para serem incluídas no build, e sim para estarem já publicadas no Glassfish. Assim, você tem duas opções: baixar manualmente e colocá-las na pasta lib do Glassfish OU alterar isso no pom, excluindo a linha do <scope>provided</scope> para os seguintes artefatos:

<artifactId>hibernate-entitymanager</artifactId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<artifactId>hibernate-entitymanager</artifactId>

4º passo: Execução, o Gran Finale
Execute o rapaz com o Glassfish:

Botão direito no projeto > Run as > Run on Server > Glassfish

5º passo: FUN FUN FUN
O CRUD você sabe usar. Uns screenshots aqui, só pra ninguém dizer que é mentira minha que funciona.

Este slideshow necessita de JavaScript.

O scaffold (essa geração de telas) é completamente opcional. O ‘scaffold setup’ executado após a criação do projeto não é; ela define os facets do projeto. Infelizmente a documentação do forge é pobre feito um mendigo de porta de igreja, então muita coisa é na base da tentativa e (muito) erro.

Dúvidas, tente os comentários e/ou use o google (apesar de que, pro Forge, infelizmente ele não ajuda muito).

Bug Eclipse – Erro ao carregar web.xml

Eis que me deparo com essa mensagem ao fazer o checkout do projeto:

An internal error occurred during: “Loading descriptor for <your_project>”.
org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature ‘tablig-location’ not found.
(platform:/resource/<your_project>/src/main/webapp/WEB-INF/web.xml, <line>, <column>)

“Tudo bem, é só jogar a mensagem no google e vou ter uma solução!”

Eis que vejo isso: https://bugs.eclipse.org/bugs/show_bug.cgi?id=198630

Bug fechado pela própria equipe do Eclipse como “não reproduzível”. Fora, claro, uma série de posts inúteis discutindo se era ou não um bug, se devia ou não ser lançada correção durante aquela major version, ou se deveria aguardar a próxima e de quem era a culpa.

Enfim, eu achei a solução. O problema não é com o arquivo, sequer com o Eclipse propriamente dito: é com o XML Editor. (Léo, você quis dizer o XML Validator) – Não, é o XML Editor mesmo. O validador utiliza a mesma engine do editor para validar o conteúdo. Como há um erro na Engine, ANTES de abrir o arquivo (ao fazer o import, no caso), ele corrompe o arquivo.

A solução é cretinamente simples:

  • Copie o conteúdo do arquivo e salve num novo arquivo, algo como web.txt;
  • Exclua o web.xml;
  • Renomeie o arquivo para web.txt para web.xml.

Sorria e seja feliz.

Duas lições, portanto:

  1.  A solução mais simples nem sempre é deselegante, às vezes ela te atende que é uma beleza e você não deve perder mais tempo procurando pêlo em ovo;
  2.  Quando há um bug, problema, incidente, qualquer coisa: FOCO. Atenda o cliente. O Eclipse é open-source, é uma obrigação inclusive minha, que uso, tentar solucionar o problema; mas serve de lição: discutir sexo dos anjos no bugtracker não vai trazer solução alguma.

Manipulando permissões de arquivos em Java

Manipular arquivos em Java é, em geral, uma tarefa simples (a não ser que você tenha que fazer auto-referências de locais: a API Java até hoje não incluiu um método que permitisse buscar a pasta do próprio arquivo automaticamente). Entretanto, muitas vezes nos deparamos com um entrave até meio óbvio: permissões de arquivos.

Para quem trabalha com Linux, alterar permissão de arquivo é dia-a-dia. No Windows, isso já não é tão comum, quase não se mexe nisso, pois o próprio SO controla isso. Como o assunto aqui não é explicar como funciona permissão de arquivos, eu vou deixar um link que conceitua bem o assunto (com relação ao Linux, que trata esse tema de forma mais completa):

http://www.infowester.com/linuxpermissoes.php

Quando precisamos manipular as permissões dos arquivos pelo Java, o que mais se encontra em sistemas por aí é sua manipulação através da classe Runtime, o que tira da aplicação sua portabilidade, já que a linha de comando executada deverá ser diferente para cada sistema operacional.

Assim, utilizar métodos da classe File é, de longe, o mais indicado. No caso, os métodos setReadable, setWritable e setExecutable. Cada um desses métodos contém duas assinaturas: uma, que recebe apenas um boolean, que representa a permissão em si; e outra, que recebe dois booleans, ou seja, um para a permissão e outro que indica se tal permissão deve ser dada apenas ao dono (owner) do arquivo. O conceito de owner pode ser encontrado no link sobre permissões citado acima.

Como em Java não é possível utilizar parâmetros opcionais, a assinatura que possui apenas um boolean como parâmetro é, na realidade, apenas um método de conveniência para o segundo. Entretanto, quando fazemos métodos de conveniência ocultando booleanos, em geral seu padrão é false. Por algum motivo, neste caso, ele tem como padrão o valor true, o que faz com que, em caso de uso, somente o owner do arquivo receba estas permissões.

Portanto, quando você quiser dar permissão a todos os usuários para alteração, leitura e exclusão de um arquivo, você precisará utilizar a segunda assinatura, com o valor false sendo passado como parâmetro, conforme o exemplo abaixo.

File file = new File("arquivo.txt");
file.setReadable(Boolean.TRUE, Boolean.FALSE);
file.setWritable(Boolean.TRUE, Boolean.FALSE);
file.setExecutable(Boolean.TRUE, Boolean.FALSE);

Claro que o Linux permite maior controle das permissões do que apenas as 6 combinações aqui descritas; mas para a grande maioria dos casos, esses métodos atendem, e sem roubar do sistema sua portabilidade.