Archive for the ‘Dicas’ category

Dica: melhorando o tempo de execução do Selenium

November 3rd, 2011

Aqui vai uma dica rápida de como agilizar a execução dos seus testes:

FirefoxProfile profile = new FirefoxProfile();
// here's the important part
profile.setPreference("permissions.default.image", 2);
 
WebDriver driver = new FirefoxDriver(profile);
selenium = new WebDriverBackedSelenium(driver, "http://rafaelliu.net");

Com isso o Firefox não irá requisitar, baixar e renderizar imagens. A diferença varia de acordo a quantidade de imagens na página e hits no cache. Executei um teste no http://g1.globo.com/ com 10 iterações, o que resultou nos seguintes tempos (em milissegundos):

NormalSeleniumTest - 39021ms
TweakedSeleniumTest - 29072ms

Hope that helps!

 

Referência: http://kb.mozillazine.org/Permissions.default.image

Separando logs por aplicação no JBoss

October 20th, 2011

Separar logs de aplicações no JBoss é uma tarefa comum e existem alguns modos de fazer isso:

1. Adicionando uma Category ao $JBOSS_CONF/conf/jboss-log4j.xml pegando todos o package da aplicação e usando um Appender específico. Por exemplo:

   <category name="net.rafaelliu">
     <priority value="INFO" />
     <appender-ref ref="BLOG_LOG"/>
   </category>

Embora seja a solução mais fácil, a separação não está perfeita. Como estamos separando por pacotes, um erro no Hibernate por exemplo, ainda vai ser escrito no server.log, mesmo tendo sido lançado pela aplicação.

 

2. Usando Filters é possível criar um TCLFilter para pegar apenas logs de determinada aplicação. Basta criar um Appender específico:

   <appender name="BLOG_LOG" class="org.jboss.logging.appender.DailyRollingFileAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
      <param name="File" value="${jboss.server.log.dir}/blog.log"/>
      <param name="Append" value="true"/>
      <param name="DatePattern" value="'.'yyyy-MM-dd"/>
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
      </layout>
 
      <!-- filter -->
      <filter class="org.jboss.logging.filter.TCLFilter">
         <param name="AcceptOnMatch" value="true"/>
         <param name="DeployURL" value="blog.war"/>
      </filter>    
      <filter class="org.apache.log4j.varia.DenyAllFilter"></filter>
   </appender>

O problema aqui é que, embora o log seja gravado separadamente (inclusive de pacotes do Hibernate, por exemplo), ele será gravado duas vezes: uma vez no blog.log que definimos e uma vez no server.log do JBoss. Isso resulta em mais IO e mais espaço em disco.

 

3. Empacotando um log4j na própria aplicação, em WEB-INF/lib, é possível inverter o classloader e fazer com que as configurações do log4j valham apenas para sua aplicação:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
	<class-loading java2ClassLoadingCompliance="false">
		<loader-repository>
			net.rafaelliu:loader=blog.war
			<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
		</loader-repository>
	</class-loading>
</jboss-web>

Feito isso, é preciso criar o log4j.properties (ou xml) normalmente:

log4j.rootLogger=${jboss.server.log.threshold}, fileout
 
log4j.appender.fileout=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileout.File=${jboss.server.log.dir}/blog.log
log4j.appender.fileout.Append=true
log4j.appender.fileout.DatePattern='.'yyyy-MM-dd
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=%d %-5p [%c] (%t) %m%n

O log4j faz parse de system properties, que podem ser usadas no arquivo de configuração. Uma observação importante é que não é possível usar classes do JBoss aqui! Isso causaria ClassCastExceptions. Algumas dicas:

  • No JBoss 5, use o jboss.server.log.dir e o jboss.server.log.threshold. Isso facilitará o deploy da sua aplicação em outros ambientes;
  • Use o mesmo Appender do jboss-log4j (provavelmente uma classe da JBoss estará lá, veja o equivalente da Apache). Isso deixa os logs do JBoss e das aplicações sincronizados, facilitando o correlacionamento de erros;

O problema dessa abordagem é que perdemos o “hot deploy” do jboss-log4j.xml, que nos permite alterar o nível de log sem indisponibilidade.

Referências:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PropertyConfigurator.html
http://viragine.blogspot.com/2009/02/separando-o-log-do-jboss-as-por.html
http://community.jboss.org/wiki/SeparatingApplicationLogs

Weld no Tomcat 7

May 29th, 2011

Havia escrito há muito tempo atrás como fazer o deploy de uma aplicação Seam no Tomcat. Daquele tempo para cá muita coisa mudou: o Seam junto com outros frameworks de IoC gerou a JSR-299 de Contexts and Dependency Injection (CDI), a JBoss criou o Weld (implementação de referência CDI), o Seam 3 foi lançado baseado na nova especificação.

Com a padronização numa JSR, agora implementações CDI são obrigadas a suportar uma variedade maior de ambientes de forma vendor neutral. O Weld faz isso e entre os ambientes suportados está o Tomcat. Portanto não há necessidade de configurações extras e gambiarras! O próprio projeto Weld provê archetypes maven com várias configuração, para criar uma aplicação para rodar em um servlet container:

mvn archetype:generate -DarchetypeArtifactId=weld-jsf-servlet-minimal \
                       -DarchetypeGroupId=org.jboss.weld.archetypes \
                       -DarchetypeVersion=1.0.0.Beta1 \
                       -DarchetypeRepository=central

E um projeto pronto para ser executado no Tomcat/Jetty será criado. O problema é que, devido a um bug, no Tomcat 7 pode ser que você veja a seguinte exceção:

SEVERE: Exception sending context initialized event to listener instance of class org.jboss.weld.environment.servlet.Listener
java.lang.NoClassDefFoundError: org/apache/AnnotationProcessor
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2820)
	at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1143)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1638)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2820)
	at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1143)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1638)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516)
	at org.jboss.weld.environment.tomcat.Tomcat6Container.initialize(Tomcat6Container.java:47)
	at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:184)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4544)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5016)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1035)
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:738)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1035)
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:289)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:442)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:674)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:596)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)
Caused by: java.lang.ClassNotFoundException: org.apache.AnnotationProcessor
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1671)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516)
	... 36 more

O problema é que o Weld identifica erroneamente o Tomcat 7 como Tomcat 6. Para resolver o problema podemos definir explicitamente que o container que estamos usando é o Tomcat 7. Isso é feito criando-se um arquivo META-INF/services/org.jboss.weld.environment.Container no classpath com o conteúdo:

org.jboss.weld.environment.tomcat7.Tomcat7Container

Note que estamos definindo na mão o container! Ou seja, abrimos mão da portabilidade. Vamos esperar o bug ser corrigido, mas até lá é isso!

Referência: https://issues.jboss.org/browse/WELD-879

Dual head com o OpenOffice Impress (fenomenal!!!)

August 26th, 2009

Às vésperas de dar um treinamento JBoss, eis que encontro:  Sun Presenter Console. Fiquei tão excitado com a descoberta que usei o jargão reservado aos esportes por falta de palavra melhor. Tive que postar.

O Sun Presenter Console é uma extensão para o OpenOffice Impress que ajuda [muito] em apresentações em dual head (monitor do notebook e projetor, por exemplo).  Foi no Keynote da Apple e no Powerpoint da Microsoft que primeiro vi essa funcionalidade. Admito que o mais perto que cheguei de conhecê-la foi ver algum palestrante usando-a, mas não creio que seja tão completos quando é essa extensão para o OpenOffice Impress. Com ele é possível pôr a apresentação num monitor em fullscreen e em outro mostrar informações como o slide atual, o próximo slide, as notas para aquele slide e uma lista de thumbnails de slides. Perfeito!!!

Isso mostra a competência e a força de competitividade da comunidade. Devo dizer que deu um certo orgulho, mesmo sendo apenas entusiasta Open Source :p

EDIT: pra não ficar só na conversa, aqui vão uns screenshots do segundo monitor (no primeiro estaria a apresentação)

referência: GullFOSS

Rapidinha: pull vs push MVC

June 24th, 2008

O padrão push é o de mais tradição, nele os dados são previamente carregados e disponibilizados para a camada de apresentação. Na prática: por exemplo o Struts com sua Action carregando os dados no request para serem usados na JSP.

No padrão pull a camada de apresentação é quem faz as chamadas aos componentes que irão lhes retornar os dados. Na prática: pro exemplo a página JSF invocando um getter no backing bean.

Resultado: no padrão do Struts muitas vezes os dados são gerados de forma que não podem ser facilmente reutilizados. Por outro lado JSF torna a reutilizacão muito mais clara e direta, através de componentes, no melhor estilo OO. Pessoalmente vejo a relação página-objetos muito mais intuitiva do que página-ação.

Rapidinha: import.sql

June 18th, 2008

Uma facilidade muito desconhecida do Hibernate é o import.sql, que pode ser usado para popular o banco. Basta o hibernate.hbm2ddl.auto estar setado como create ou create-drop que, logo após o banco ser criado, o script será executado.

fonte: http://in.relation.to/9081.lace

Quick one

May 26th, 2008

This one is for all of you who (like me) keeps wasting time using commands such as find, jar and grep each time you get a classpath error:

#!/bin/bash
if [ "$1" = "" ]; then
	echo "Usage: jarfind REGEXP";
	exit;
fi
 
for d in `find . -name '*.jar'` ; do
	FILES=`unzip -l $d | cut -c 29- | egrep ''$1''`;
 
	if [ "$FILES" != "" ]; then
		echo "$d";
 
		for f in $FILES ; do
			echo " - $f"
		done
	fi
done

I’ve chose to use unzip instead of jar since it’s far more commonly seem. Move it to /usr/local/bin/jarfind (well, that’s a little personal) and chmod it to +x.

I works searching all jars under the current directory for a regular expression, most commonly a simple class name. It returns the jar’s names and all corresponding class matches.

I’m not a bash programmer, so it may not look that pretty to experienced bash programmers, but it looks beautiful to me, as it saves me a lot of time =). Feel free to make any comments.

EDIT:

first known bug: doesn’t escape special characters in paths =/