<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Grails</title>
	<atom:link href="http://techdm.com/grails/?feed=rss2&#038;page_id=7" rel="self" type="application/rss+xml" />
	<link>http://techdm.com/grails</link>
	<description>Development</description>
	<lastBuildDate>Tue, 29 Nov 2011 10:46:34 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
		<item>
		<title>Nova jornada</title>
		<link>http://techdm.com/grails/?p=1062</link>
		<comments>http://techdm.com/grails/?p=1062#comments</comments>
		<pubDate>Fri, 07 Oct 2011 16:25:32 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Não classificado]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=1062</guid>
		<description><![CDATA[Após tantos anos trabalhando diretamente com análise e desenvolvimento de software, decidi por mudar de foco. Caso queiram acompanhar a nova jornada: http://inconvencional.com.br/ Infelizmente, está disponível somente em português. Informações para contato (ainda em atualização): LinkedIn Facebook Twitter Obrigado.]]></description>
			<content:encoded><![CDATA[<p>Após tantos anos trabalhando diretamente com análise e desenvolvimento de software, decidi por mudar de foco. Caso queiram acompanhar a nova jornada:</p>
<p><a href="http://inconvencional.com.br/">http://inconvencional.com.br/</a></p>
<p>Infelizmente, está disponível somente em português.</p>
<p>Informações para contato (ainda em atualização):</p>
<p><a href="http://www.linkedin.com/pub/daniel-henrique-alves-lima/0/115/509">LinkedIn</a><br />
<a href="http://www.facebook.com/daniel.halima">Facebook</a><br />
<a href="http://twitter.com/#!/daniel_halima">Twitter</a></p>
<p>Obrigado.</p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=1062</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Novo plugin para Grails: hibernate-spatial</title>
		<link>http://techdm.com/grails/?p=1039</link>
		<comments>http://techdm.com/grails/?p=1039#comments</comments>
		<pubDate>Sat, 01 Oct 2011 15:32:10 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Notas rápidas]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=1039</guid>
		<description><![CDATA[http://www.grails.org/plugin/hibernate-spatial http://www.grails.org/plugin/hibernate-spatial-hdb http://www.grails.org/plugin/hibernate-spatial-postgresql O anúncio foi feito aqui.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.grails.org/plugin/hibernate-spatial">http://www.grails.org/plugin/hibernate-spatial</a><br />
<a href="http://www.grails.org/plugin/hibernate-spatial-hdb">http://www.grails.org/plugin/hibernate-spatial-hdb</a><br />
<a href="http://www.grails.org/plugin/hibernate-spatial-postgresql">http://www.grails.org/plugin/hibernate-spatial-postgresql</a></p>
<p>O anúncio foi feito <a href="http://grails.1312388.n4.nabble.com/ANN-Hibernate-Spatial-Plugin-Beta-td3841942.html">aqui</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=1039</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Material do mini-curso de Groovy e Grails na Semcomp 14 da USP/São Carlos</title>
		<link>http://techdm.com/grails/?p=1032</link>
		<comments>http://techdm.com/grails/?p=1032#comments</comments>
		<pubDate>Wed, 21 Sep 2011 05:13:20 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Notas rápidas]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=1032</guid>
		<description><![CDATA[Groovy &#038; Grails – Semcomp 14]]></description>
			<content:encoded><![CDATA[<p><a href="http://techdm.com/grails/?page_id=628">Groovy &#038; Grails – Semcomp 14</a></p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=1032</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dicas de scripts Gant em Grails</title>
		<link>http://techdm.com/grails/?p=585</link>
		<comments>http://techdm.com/grails/?p=585#comments</comments>
		<pubDate>Mon, 08 Aug 2011 18:55:02 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Notas rápidas]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=585</guid>
		<description><![CDATA[Enquanto GRAILS-7274 não for corrigido, use try-catch ao escrever build event handlers; Adicione &#8220;verbosidade&#8221; ao log do Gant, sempre que necessário: Prefira AntBuilder.path à utilização de elementos aninhados de classpath: O &#8220;prêmio&#8221; por ter lido até aqui é trecho de código necessário à execução do weblogic.appc (entre outras atividades, ele pré-compilará os JSPs) após a [...]]]></description>
			<content:encoded><![CDATA[<ol>
<li>Enquanto <a href="http://jira.grails.org/browse/GRAILS-7274">GRAILS-7274</a> não for corrigido, use try-catch ao escrever <a href="http://www.grails.org/doc/latest/guide/4.%20The%20Command%20Line.html#4.3%20Hooking%20into%20Events">build event handlers</a>;
<pre class="brush: groovy; title: ; notranslate">
    eventCreateWarEnd = {warName, stagingDir -&gt;
         try {
             // Script logic goes here...
         } catch (Exception e) {
             e.printStackTrace()
             throw e
         }
    }
</pre>
</li>
<li>Adicione &#8220;verbosidade&#8221; ao log do <a href="http://gant.codehaus.org/">Gant</a>, sempre que necessário:
<pre class="brush: groovy; title: ; notranslate">
import org.codehaus.gant.GantState
// (...)
GantState.verbosity = GantState.VERBOSE
ant.logger.setMessageOutputLevel(GantState.verbosity)
</pre>
</li>
<li>Prefira AntBuilder.path à utilização de elementos aninhados de classpath:
<pre class="brush: groovy; title: ; notranslate">
        ant.path(id: 'myClasspath', { pathelement(location: 'somewhere') })
        ant.java(classname: 'aClass', dir: 'anyDir', fork: true, 
                    classpathref:'myClasspath') {}
</pre>
</li>
</ol>
<p>O &#8220;prêmio&#8221; por ter lido até aqui é trecho de código necessário à execução do <a href="http://download.oracle.com/docs/cd/E11035_01/wls100/ejb/appc_ejbc.html">weblogic.appc</a> (entre outras atividades, ele pré-compilará os JSPs) após a <a ref="http://grails.org/doc/latest/ref/Command%20Line/war.html">criação do arquivo .war</a> do seu projeto:</p>
<pre class="brush: groovy; title: ; notranslate">
// _Events.groovy
import org.codehaus.gant.GantState

eventCreateWarEnd = {warName, stagingDir -&gt;

    def beaHome = System.getenv('BEA_HOME')?: 'C:/bea'
    try {
        println &quot;Executing weblogic.appc ${beaHome} ${warName}&quot;

        //GantState.dryRun = true
        GantState.verbosity = GantState.VERBOSE
        ant.logger.setMessageOutputLevel(GantState.verbosity)

        File warFile = new File(warName)
        File tmpFile = new File(warFile.parentFile, &quot;${warFile.name.tokenize('.')[0]}_tmp.war&quot;)
        ant.move(file: warFile, tofile: tmpFile)

        ant.path(id: 'appcClasspath', { pathelement(location: &quot;${beaHome}/wlserver_10.3/server/lib/weblogic.jar&quot;) })

        ant.java(classname: 'weblogic.appc', dir: warFile.parentFile, fork: true, classpathref:'appcClasspath') {
            arg(line: &quot;-output ${warFile.name} -lineNumbers -g -O -keepgenerated ${tmpFile.name}&quot;)
        }
    } catch (Throwable e) {
        e.printStackTrace()
        throw e
    }
}
</pre>
<p>Referências adicionais:</p>
<ul>
<li><a href="http://grails.1312388.n4.nabble.com/Gant-scripts-java-task-and-nested-classpath-element-td3734398.html">Gant scripts, java task and nested classpath element (Grails mailing list)</a></li>
<li><a href="http://groovy.329449.n5.nabble.com/Gant-scripts-java-task-and-nested-classpath-element-td4687493.html">Gant scripts, java task and nested classpath element (Groovy mailing list)</a></li>
</ul>
<p><!-- more --></p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=585</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Código-fonte buscável e navegável</title>
		<link>http://techdm.com/grails/?p=563</link>
		<comments>http://techdm.com/grails/?p=563#comments</comments>
		<pubDate>Mon, 25 Jul 2011 23:21:33 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Notas rápidas]]></category>
		<category><![CDATA[Técnicas gerais]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=563</guid>
		<description><![CDATA[Para código-fonte público e escrito em Java, GrepCode pode ser útil. Para código-fonte privado e/ou escrito em outras linguagens (ou armazenado usando inusitados softwares de controle de versão), vale a pena conhecer o OpenGrok. Referências adicionais: OpenGrok (Wikipedia) OpenGrok in action (opensolaris.org) OpenGrok internals Available analyzers (source code) Install OpenGrok on Windows Installing Opengrok on [...]]]></description>
			<content:encoded><![CDATA[<p>Para código-fonte público e escrito em Java, <a href="http://grepcode.com/">GrepCode</a> pode ser útil.</p>
<p>Para código-fonte privado e/ou escrito em outras linguagens (ou armazenado usando inusitados <a href="http://en.wikipedia.org/wiki/Software_configuration_management">softwares de controle de versão</a>), vale a pena conhecer o <a href="http://hub.opensolaris.org/bin/view/Project+opengrok/WebHome">OpenGrok</a>.</p>
<p>Referências adicionais:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/OpenGrok">OpenGrok (Wikipedia)</a></li>
<li><a href="http://src.opensolaris.org/source/">OpenGrok in action (opensolaris.org)</a></li>
<li><a href="http://hub.opensolaris.org/bin/view/Project+opengrok/internals">OpenGrok internals</a></li>
<li><a href="http://src.opensolaris.org/source/xref/opengrok/trunk/src/org/opensolaris/opengrok/analysis/">Available analyzers (source code)</a></li>
<li><a href="http://lifeisbetter.in/blog/2009/05/11/install-opengrok-on-windows/">Install OpenGrok on Windows</a></li>
<li><a href="http://blog.vinceliu.com/2008/06/installing-opengrok-on-ubuntu-linux.html">Installing Opengrok on Ubuntu Linux</a></li>
</ul>
<p><span id="more-563"></span></p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=563</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Melhoria de desempenho do freemarker-tags</title>
		<link>http://techdm.com/grails/?p=532</link>
		<comments>http://techdm.com/grails/?p=532#comments</comments>
		<pubDate>Sun, 17 Jul 2011 16:18:46 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Desempenho]]></category>
		<category><![CDATA[Notas rápidas]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=532</guid>
		<description><![CDATA[Para a maioria das aplicações o tempo gasto na geração das saídas das views é pequeno e, portanto, qualquer melhoria nesse aspecto será desprezível. Para as aplicações sensíveis a esse tempo, freemarker-tags foi redesenhado, melhorando seu desempenho. Na versão 0.7.0 do plugin, a velocidade de renderização das Grails Tag Libraries, em um template FTL, estará [...]]]></description>
			<content:encoded><![CDATA[<p>Para a maioria das aplicações o tempo gasto na geração das saídas das views é pequeno e, portanto, qualquer melhoria nesse aspecto será desprezível.<br />
Para as aplicações sensíveis a esse tempo, <a href="http://www.grails.org/plugin/freemarker-tags">freemarker-tags</a> foi redesenhado, melhorando seu desempenho. Na versão <a href="http://grails-freemarker-tags-plugin.googlecode.com/svn/doc/manual/guide/4.%20Version%20History.html">0.7.0 do plugin</a>, a velocidade de renderização das <a href="http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.3%20Tag%20Libraries">Grails Tag Libraries</a>, em um template FTL, estará muito próxima à de uma página GSP compilada:</p>
<p><b>A) </b><a href="https://github.com/daniel-lima/grails-examples-gsp-ftl/tree/master/quick_start">Aplicação quick_start</a> iniciada usando <a href="http://grails.org/doc/latest/ref/Command%20Line/run-war.html">&#8216;grails prod run-war&#8217;</a> e testada usando <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">&#8216;ab -n 3000 -c 30 url&#8217;</a></p>
<p><font size="-1"><i>#request/second (mean)</p>
<p><b>freemarker-tags-0.6.1</b></p>
<p>list: 165.99 #/sec, 403.29 #/sec, 448.74 #/sec, 421.15 #/sec<br />
create: 201.49 #/sec, 407.45 #/sec, 449.79 #/sec, 436.02 #/sec<br />
show: 231.39 #/sec, 428.36 #/sec, 496.63 #/sec, 468.14 #/sec<br />
edit: 186.29 #/sec, 348.25 #/sec, 388.07 #/sec, 372.15 #/sec</p>
<p><b>gsp</b></p>
<p>list: 248.94 #/sec, 714.39 #/sec, 777.56 #/sec, 688.66 #/sec<br />
create: 251.24 #/sec, 712.82 #/sec, 891.65 #/sec, 813.68 #/sec<br />
show: 250.04 #/sec, 742.08 #/sec, 990.49 #/sec, 918.49 #/sec<br />
edit: 230.59 #/sec, 720.73 #/sec, 903.11 #/sec, 783.17 #/sec</p>
<p><b>freemarker-tags-0.7.0</b></p>
<p>list: 222.27 #/sec, 670.82 #/sec, 720.34 #/sec, 627.70 #/sec<br />
create: 218.92 #/sec, 618.93 #/sec, 750.98 #/sec, 695.02 #/sec<br />
show: 250.08 #/sec, 786.39 #/sec, 1040.83 #/sec, 878.74 #/sec<br />
edit: 211.43 #/sec, 636.35 #/sec, 823.98 #/sec, 757.29 #/sec</i></font></p>
<p>Em situações particulares, o desempenho do template FTL será ainda melhor do que o de uma página GSP, graças ao próprio <a href="http://freemarker.sourceforge.net/">FreeMarker</a>:<br />
<span id="more-532"></span><br />
<b>B) </b><a href="https://github.com/daniel-lima/grails-examples-gsp-ftl/tree/master/dynamic_rendering">Aplicação dynamic_rendering</a> iniciada usando <a href="http://grails.org/doc/latest/ref/Command%20Line/run-app.html">&#8216;grails run-app&#8217;</a> e testada usando &#8216;ab -n 3000 -c 30 url&#8217;<br />
<font size="-1"><i><br />
<b>freemarker-tags-0.6.1</b></p>
<p>Template Creation: 9687ms, 8652ms, 8142ms, 8056ms, 8068ms<br />
Rendering: 14188ms, 9820ms, 9184ms, 8944ms, 8913ms<br />
Both: 17489ms, 17655ms, 17698ms, 17575ms, 17629ms</p>
<p><b>gsp</b></p>
<p>Template Creation: java.lang.OutOfMemoryError: PermGen space<br />
Rendering: 12492ms, 8571ms, 7680ms, 7293ms, 7280ms<br />
Both: ?</p>
<p><b>freemarker-tags-0.7.0</b></p>
<p>Template Creation: 9630ms, 8640ms, 8182ms, 8204ms, 8216ms<br />
Rendering: 8740ms, 5861ms, 5156ms, 4933ms, 4941ms<br />
Both: 13377ms, 13327ms, 13374ms, 13273ms, 13240ms<br />
</font></i></p>
<p><b>C) </b>Aplicação dynamic_rendering iniciada usando &#8216;grails run-app&#8217; e testada usando &#8216;ab -n 3000 -c 30 url&#8217;<br />
freemarker-tags-0.6.1</p>
<p><font size="-1"><i><br />
<b>freemarker-tags-0.6.1</b><br />
Template Creation: 9924ms, 8725ms, 8027ms, 7969ms, 7950ms<br />
Rendering: 13098ms, 8682ms, 8035ms, 7827ms, 7860ms<br />
Both: 16271ms, 16271ms, 16194ms, 16178ms, 16176ms</p>
<p><b>gsp</b></p>
<p>Template Creation: java.lang.OutOfMemoryError: PermGen space<br />
Rendering: 10687ms, 7084ms, 6311ms, 5941ms, 5867ms<br />
Both: java.lang.OutOfMemoryError: PermGen space at gspTemplate415:63</p>
<p><b>freemarker-tags-0.7.0</b></p>
<p>Template Creation: 9941ms, 8556ms, 8028ms, 7868ms, 7864ms<br />
Rendering: 8900ms, 5646ms, 4855ms, 4747ms, 4748ms<br />
Both: 13014ms, 13034ms, 13001ms, 13018ms, 12953ms<br />
</font></i></p>
<p>O tempo de &#8220;dynamic rendering&#8221; é o mesmo percebido pelo desenvolvedor, durante o ciclo alteração <-> atualização da view. Para uma referência, abra as URLs <a href="http://localhost:8080/dynamic_rendering/benchmark/freemarkerPage">http://localhost:8080/dynamic_rendering/benchmark/freemarkerPage</a> e <a href="http://localhost:8080/dynamic_rendering/benchmark/gspPage">http://localhost:8080/dynamic_rendering/benchmark/gspPage</a> em abas distintas do seu navegador e, para cada uma delas, clique algumas vezes no botão &#8220;atualizar&#8221;.</p>
<p><a href="https://github.com/daniel-lima/grails-examples-gsp-ftl/">Projeto no GitHub</a>.<br />
<a href="http://techdm.com/grails/wp-content/uploads/2011/07/performance_improvement_of_freemarker_tags/grails-examples-gsp-ftl.zip">Download</a> do código-fonte e dos resultados completos.</p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=532</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gerenciamento programático de transações em Grails</title>
		<link>http://techdm.com/grails/?p=515</link>
		<comments>http://techdm.com/grails/?p=515#comments</comments>
		<pubDate>Sat, 02 Jul 2011 16:22:10 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Notas rápidas]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=515</guid>
		<description><![CDATA[Até que GRAILS-7093 faça parte do core, a funcionalidade permanecerá disponível na forma de um plugin para Grails: transaction-handling. Exemplos de utilização: Referências adicionais Spring Framework Transaction Management TransactionTemplate (Javadoc) TransactionDefinition (Javadoc)]]></description>
			<content:encoded><![CDATA[<p>Até que <a href="http://jira.grails.org/browse/GRAILS-7093">GRAILS-7093</a> faça parte do core, a funcionalidade permanecerá disponível na forma de um plugin para Grails: <a href="http://www.grails.org/plugin/transaction-handling">transaction-handling</a>.</p>
<p>Exemplos de utilização:</p>
<pre class="brush: groovy; title: ; notranslate">
        User.withTransaction {
        }

        User.withTransaction(isolation: 'readUncommitted') {
        }

        User.withTransaction(readOnly: true, timeout: 'default') {
        }

        User.withTransaction(propagationBehaviorName: 'PROPAGATION_MANDATORY', timeout: 765) {
        }

        User.withTransaction(propagation: &quot;mandatory&quot;) {
        }

        User.withNewTransaction {
        }

        User.withNewTransaction(isolationLevel: TransactionDefinition.ISOLATION_SERIALIZABLE) {
        }

        User.withNewTransaction(propagation: 'supports', readOnly: true, timeout: 612) {
        }

        User.withNewTransaction(isolationLevelName: 'ISOLATION_REPEATABLE_READ') {
        } 
</pre>
<p><span id="more-515"></span></p>
<p>Referências adicionais</p>
<ul>
<li><a href="http://static.springsource.org/spring/docs/2.5.0/reference/transaction.html">Spring Framework Transaction Management</a></li>
<li><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/support/TransactionTemplate.html">TransactionTemplate (Javadoc)</a></li>
<li><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/TransactionDefinition.html">TransactionDefinition (Javadoc)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=515</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GSP x FTL (microbenchmark)</title>
		<link>http://techdm.com/grails/?p=445</link>
		<comments>http://techdm.com/grails/?p=445#comments</comments>
		<pubDate>Fri, 10 Jun 2011 01:35:10 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Desempenho]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=445</guid>
		<description><![CDATA[Groovy Server Pages x FreeMarker Templates. Ambas são boas ferramentas, são mantidas por equipes extremamente qualificadas e estão disponíveis para Grails (FreeMarker através dos plugins freemarker e freemarker-tags). Conforme já mencionado anteriormente, microbenchmarks são apenas microbenchmarks. Os testes a seguir foram motivados por uma antiga discussão sobre a renderização de templates dinâmicos e pelo recente [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.2%20Groovy%20Server%20Pages">Groovy Server Pages</a> x <a href="http://freemarker.sourceforge.net/">FreeMarker</a> Templates. Ambas são boas ferramentas, são mantidas por equipes extremamente qualificadas e estão disponíveis para Grails (FreeMarker através dos plugins <a href="http://www.grails.org/plugin/freemarker">freemarker</a> e <a href="http://www.grails.org/plugin/freemarker-tags">freemarker-tags</a>). </p>
<p>Conforme já mencionado anteriormente, <a href="http://techdm.com/grails/?p=164">microbenchmarks são apenas microbenchmarks.</a> Os testes a seguir foram motivados por uma antiga discussão sobre a <a href="http://grails.1312388.n4.nabble.com/FreeMarker-vs-GSP-for-Dynamic-Template-Rendering-td3213939.html">renderização de templates dinâmicos</a> e pelo recente tópico sobre o <a href="http://www.jtict.com/blog/rails-wicket-grails-play-lift-jsp/">desempenho de renderização de vários frameworks web</a>.</p>
<p>Seguem-se os resultados obtidos, para o cenário particular do tópico em questão:</p>
<p><strong><a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apache HTTP server benchmarking tool (ab)</a></strong></p>
<ul>
<li>
      <b>GSP</b><br />
      <font size="-1"><i><br />
Document Path:          /grailsapp/products<br />
Document Length:        1037698 bytes</p>
<p>Concurrency Level:      30<br />
<b>Time taken for tests:   383.757685 seconds</b><br />
<b>Complete requests:      3000</b><br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      3113592000 bytes<br />
HTML transferred:       3113094000 bytes<br />
<b>Requests per second:    7.82 [#/sec] (mean)</b><br />
Time per request:       3837.577 [ms] (mean)<br />
Time per request:       127.919 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          7923.27 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
              min  mean[+/-sd] median   max<br />
Connect:        0    0   1.1      0      14<br />
Processing:  2105 3829 380.8   3831    5122<br />
Waiting:     2097 3824 381.0   3825    5120<br />
Total:       2105 3829 380.9   3831    5122</p>
<p>Percentage of the requests served within a certain time (ms)<br />
  50%   3831<br />
  66%   3987<br />
  <b>75%   4092</b><br />
<br />
</i></font>
  </li>
<li>
     <b>FTL</b><br />
       <font size="-1"><i><br />
Document Path:          /grailsapp-fm/products<br />
Document Length:        1026697 bytes</p>
<p>Concurrency Level:      30<br />
<b>Time taken for tests:   103.94286 seconds</b><br />
<b>Complete requests:      3000</b><br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      3080604000 bytes<br />
HTML transferred:       3080091000 bytes<br />
<b>Requests per second:    29.10 [#/sec] (mean)</b><br />
Time per request:       1030.943 [ms] (mean)<br />
Time per request:       34.365 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          29181.07 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
              min  mean[+/-sd] median   max<br />
Connect:        0    0   0.0      0       0<br />
Processing:    74 1027 646.1    962    4373<br />
Waiting:       71  988 643.3    915    4006<br />
Total:         74 1027 646.1    962    4373</p>
<p>Percentage of the requests served within a certain time (ms)<br />
  50%    962<br />
  66%   1212<br />
  <b>75%   1376</b><br />
       </i><br />
     </font>
   </li>
</ul>
<p><strong><a href="http://jakarta.apache.org/jmeter/">JMeter</a></strong><br />
<span id="more-445"></span></p>
<ul>
<li>
      <b>GSP</b><br />
<br />
      <a title="Clique para ampliar a imagem" href="/grails/wp-content/uploads/2011/06/gsp_ftl/jmeter-grailsapp-1.png"><img src="/grails/wp-content/uploads/2011/06/gsp_ftl/th-jmeter-grailsapp-1.jpg" /></a></p>
</li>
<p></p>
<li>
      <b>FTL</b><br />
<br />
      <a title="Clique para ampliar a imagem" href="/grails/wp-content/uploads/2011/06/gsp_ftl/jmeter-grailsapp-fm-1.png"><img src="/grails/wp-content/uploads/2011/06/gsp_ftl/th-jmeter-grailsapp-fm-1.jpg" /></a></p>
<p>
  </li>
</ul>
<p>Informações relevantes:</p>
<ul>
<li>As aplicações foram iniciadas usando-se <i>&#8216;grails prod run-war&#8217;</i>;</li>
<li>Para a execução do Apache benchmarking foi usado o comando <i>&#8216;ab -n 3000 -c 30 URL&#8217;</i>;</li>
<li>O arquivo de configuração do JMeter pode ser encontrado <a href="https://github.com/daniel-lima/blogpost_files/blob/master/JMeter-benchmark.jmx">aqui</a>;</li>
<li>Os resultados completos encontram-se <a href="/grails/wp-content/uploads/2011/06/gsp_ftl/gsp_ftl.zip">aqui</a>;</li>
<li>O desempenho de renderização dos GSPs foi melhorado na versão 1.4 de Grails: <a href="http://jira.grails.org/browse/GRAILS-7582">GRAILS-7582</a>.</li>
</ul>
<p><a href="https://github.com/daniel-lima/blogpost_files">Projeto no github</a>.</p>
<p>Referências adicionais:</p>
<ul>
<li><a href="http://grails.1312388.n4.nabble.com/Template-GSP-vs-FTL-td3578664.html">Template: GSP vs. FTL</a></li>
<li><a href="http://freemarker.624813.n4.nabble.com/micro-bench-FTL-vs-GSP-td3579422.html">micro bench: FTL vs. GSP</a></li>
<li><a href="https://github.com/daniel-lima/grails-examples-gsp-ftl">Exemplos de uso de GSP and FTL (GitHub)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=445</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Usando Grails para construir um sistema batch simples</title>
		<link>http://techdm.com/grails/?p=371</link>
		<comments>http://techdm.com/grails/?p=371#comments</comments>
		<pubDate>Mon, 06 Jun 2011 00:22:31 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Não classificado]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=371</guid>
		<description><![CDATA[Inspirado pela discussão sobre &#8216;Como eu carregaria um job Quartz a partir de um script&#8217; e baseando-me na postagem sobre o &#8216;Tiny GroovyServ&#8217;, resolvi implementar um sistema batch simples usando Grails e os plugins quartz, spring-security-core e batch-launcher. O batch-launcher foi adotado porque, na empresa na qual trabalho, os ambientes para aplicações online (web) e [...]]]></description>
			<content:encoded><![CDATA[<p>Inspirado pela discussão sobre <a href="http://grails.1312388.n4.nabble.com/How-would-you-launch-a-Quartz-job-from-a-script-td3561601.html">&#8216;Como eu carregaria um job Quartz a partir de um script&#8217;</a> e baseando-me na postagem sobre o <a href="http://techdm.com/grails/?p=323">&#8216;Tiny GroovyServ&#8217;</a>, resolvi implementar um <a href="http://en.wikipedia.org/wiki/Job_scheduler">sistema batch</a> simples usando Grails e os plugins <a href="http://grails.org/plugin/quartz">quartz</a>, <a href="http://www.grails.org/plugin/spring-security-core">spring-security-core</a> e <a href="http://www.grails.org/plugin/batch-launcher">batch-launcher</a>.</p>
<p>O batch-launcher foi adotado porque, na empresa na qual trabalho, os ambientes para aplicações online (web) e batch são segregados. Dessa forma, no ambiente exclusivo a aplicações batch não há Tomcat, WebLogic ou qualquer Web Container ou Application Server. Nesse contexto, as aplicações batch são responsáveis por todo processamento massivo e assíncrono, principalmente aquele necessário à integração de dois ou mais sistemas. </p>
<p>Basicamente foi criada uma aplicação composta por serviços e tarefas agendadas cuja invocação síncrona ou assíncrona pode ser feita através de um cliente de SSH. O passo-a-passo para teste:</p>
<ol>
<li>Efetuar download do arquivo <a href="http://techdm.com/grails/wp-content/uploads/2011/06/simple_batch_system/simple_batch_system-0.1.zip">simple_batch_system-0.1.zip</a> (o arquivo possui, aproximadamente, 25 MBytes e contém todas as dependências necessárias à execução da aplicação)</li>
<p></p>
<li>Descompactar o arquivo em um diretório qualquer</li>
<p></p>
<li>Iniciar a aplicação (o único pré-requisito para esse passo é ter uma JRE instalada e o java estar disponível no PATH)
<p><i>[daniel@techdm simple_batch_system-0.1]$ ./simple_batch_system.sh</i></p>
<p>ou</p>
<p><i>simple_batch_system.bat</i>
</li>
<p></p>
<li>Disparar a execução de serviços ou tarefas agendadas, como admin0 (a senha é admin):
<p><i>ssh -p 8123 admin0@localhost task1Job,task3Service</i>
</li>
</ol>
<p><span id="more-371"></span></p>
<p>Algumas observações importantes:</p>
<ul>
<li>Para os casos onde não há segregação dos ambientes online (web) e batch, uma abordagem semelhante pode ser adotada na implementação de aplicações Grails &#8220;comuns&#8221; (web). O código-fonte, para a execução dos comandos ssh, pode ser encontrado <a href="https://github.com/daniel-lima/simple-batch-system/blob/master/grails-app/utils/Sshd.groovy">aqui</a>;</li>
<li>O plugin spring-security-core é opcional e foi utilizado somente para a criação de um modelo de domínio conhecido de usuários e perfis;</li>
<li>O mecanismo de chaves públicas e privadas pode ser adotado como alternativa de autenticação. Isso combinado a um ssh-agent eliminaria a necessidade da troca de senhas, sem reduzir a segurança da solução;</li>
<li>É possível implementar uma sessão SSH interativa, para a execução dos comandos;</li>
<li>Durante qualquer desenvolvimento usando batch-launcher, os comandos de maior destaque são <i>&#8216;grails batch-run-app&#8217;</i>, <i>&#8216;grails interactive&#8217;</i> (combinado com <i>&#8216;batch-reload-app&#8217;</i>) e <i>&#8216;grails batch-war&#8217;</i>.</li>
</ul>
<p><a href="https://github.com/daniel-lima/simple-batch-system">Projeto no gitbub</a>.<br />
<a href="http://techdm.com/grails/wp-content/uploads/2011/06/simple_batch_system/simple-batch-system.zip">Download</a> do código-fonte.</p>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=371</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tiny GroovyServ</title>
		<link>http://techdm.com/grails/?p=323</link>
		<comments>http://techdm.com/grails/?p=323#comments</comments>
		<pubDate>Fri, 03 Jun 2011 04:35:54 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[Desempenho]]></category>

		<guid isPermaLink="false">http://techdm.com/grails/?p=323</guid>
		<description><![CDATA[GroovyServ é uma solução interessante para a execução de múltiplos scripts Groovy em uma JVM compartilhada. Infelizmente, conforme citado nesse tópico, a limitação em relação aos sistemas operacionais suportados pode se tornar um problema. Como abordagem alternativa, foi escrito um pequeno servidor SSH usando Groovy. Dessa maneira, qualquer cliente SSH nativo estaria apto a enviar [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://kobo.github.com/groovyserv/">GroovyServ</a> é uma solução interessante para a execução de múltiplos scripts Groovy em uma JVM compartilhada. Infelizmente, conforme citado <a href="http://groovy.329449.n5.nabble.com/Executing-multiple-unrelated-Groovy-scripts-in-a-single-shared-JVM-td4368518.html">nesse tópico</a>, a limitação em relação aos <a href="http://kobo.github.com/groovyserv/faq.html#what-environments-are-supported">sistemas operacionais suportados</a> pode se tornar um problema.</p>
<p>Como abordagem alternativa, foi escrito um pequeno servidor <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a> usando Groovy. Dessa maneira, qualquer cliente SSH nativo estaria apto a enviar comandos de execução de script ao servidor. A idéia segue a mesma linha de raciocínio da combinação <a href="http://mrhaki.blogspot.com/2009/10/groovy-goodness-using-groovy-on-command.html">&#8216;groovy -l&#8217; e telnet</a>. Para todo o tratamento do protocolo SSH, foi utilizado o <a href="http://mina.apache.org/sshd/">Apache Mina SSHD</a>.</p>
<p>Vale ressaltar que o <a href="https://github.com/daniel-lima/tiny-groovyserv/blob/master/tgserv_impl.groovy">servidor</a> desenvolvido é apenas um primo distante, não otimizado, inseguro e funcionalmente limitado do GroovyServ, não tendo a pretensão de substituí-lo. Para a execução em ambientes não controlados, aconselha-se a utilização de um <a href="http://download.oracle.com/javase/6/docs/api/java/lang/SecurityManager.html">SecurityManager</a> devidamente configurado, bem como a adoção de <a href="http://mina.apache.org/sshd/configuring-security.html">mecanismo de autenticação</a> adequado. </p>
<p>Passo-a-passo para a utilização:</p>
<p><b>1. Efetuar <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/tiny-groovyserv.tar.gz">download</a> do código-fonte do servidor</b></p>
<p><b>2. Descompactar o conteúdo do arquivo em um diretório</b></p>
<p><b>3. Iniciar o servidor</b></p>
<p><i>[user@techdm tiny-groovyserv]$ groovy tgserv.groovy</i></p>
<p>ou </p>
<p><i>[user@techdm tiny-groovyserv]$ groovy tgserv.groovy 8123</i></p>
<p><b>4. Escrever alguns scripts no mesmo computador</b></p>
<p><b>5. Iniciar mais de prompt de comando ou shell e executar, simultaneamente, os scripts criados</b></p>
<p><i>[user@techdm test]$ ssh -p 8123 localhost <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/a.groovy">/tmp/test/a.groovy</a> abc 123</i></p>
<p><i>[user@techdm dir1]$ ssh -p 8123 localhost <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/b.groovy">/tmp/test/dir1/b.groovy</a></i></p>
<p><i>[user@techdm dir2]$ ssh -p 8123 localhost <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/c.groovy">/tmp/test/dir2/c.groovy</a></i></p>
<p>ou usando <a href="http://the.earth.li/~sgtatham/putty/0.61/htmldoc/Chapter7.html#plink">plink</a>:</p>
<p><i>C:\tmp\test> plink -P 8123 -ssh -l x localhost  <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/a.groovy">c:/tmp/test/a.groovy</a> abc 123</i></p>
<p><i>C:\tmp\test\dir1> plink -P 8123 -ssh -l x localhost  <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/b.groovy">c:/tmp/test/dir1/b.groovy</a></i></p>
<p><i>C:\tmp\test\dir2> plink -P 8123 -ssh -l x localhost  <a href="http://techdm.com/grails/wp-content/uploads/2011/06/tiny_groovyserv/c.groovy">c:/tmp/test/dir2/c.groovy</a></i></p>
<p><a href="https://github.com/daniel-lima/tiny-groovyserv">Projeto no github</a>.</p>
<p>Referências adicionais:</p>
<ul>
<li><a href="http://www.openssh.com/">OpenSSH</a></li>
<li><a href="http://www.privateshell.com/docs/cmd_line_ssh.htm">privateshell ssh.exe</a></li>
<li><a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">Plink (PuTTY)</a></li>
<li><a href="http://groovy.329449.n5.nabble.com/Tiny-GroovyServ-td4450173.html">Anúncio desta postagem</a></li>
</ul>
<p><span id="more-323"></span></p>
<pre class="brush: groovy; collapse: true; light: false; title: ; toolbar: true; notranslate">
/*
 * http://www.apache.org/licenses/LICENSE-2.0
 */

/**
 * @author Daniel Henrique Alves Lima
 */
import java.io.IOException;

import groovy.lang.GroovyClassLoader
import org.codehaus.groovy.runtime.StackTraceUtils

import org.apache.sshd.SshServer
import org.apache.sshd.server.auth.UserAuthNone
import org.apache.sshd.server.Command
import org.apache.sshd.server.CommandFactory
import org.apache.sshd.server.command.ScpCommandFactory
import org.apache.sshd.server.Environment
import org.apache.sshd.server.ExitCallback
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider

//import org.apache.sshd.server.PasswordAuthenticator
//import org.apache.sshd.server.PublickeyAuthenticator

SshServer sshd = SshServer.setUpDefaultServer()
sshd.port = args &amp;&amp; args.length &gt; 0? args[0] as int : 8123
sshd.keyPairProvider = new SimpleGeneratorHostKeyProvider('hostkey.ser')

def sysOut = System.out

def findMyClassLoader = {ClassLoader cl = Thread.currentThread().contextClassLoader -&gt;
    while (cl != null &amp;&amp; !(cl instanceof MyGroovyClassLoader)) {
        cl = cl.parent
    }
    return cl
}

sshd.commandFactory = new ScpCommandFactory(
    {command -&gt;

        command = command.tokenize(' ')
        def cmd
        cmd = [
            input: null, output: null, error:null, callback: null,
            setExitCallback: {cb -&gt; cmd.callback = cb},
            setInputStream: {is -&gt; cmd.input = is as InputStream},
            setOutputStream: {out -&gt; cmd.output = new PrintStream(out)},
            setErrorStream: {err -&gt; cmd.error = new PrintStream(err)},
            destroy: {},
            start: {env -&gt;
                Thread currentThread = Thread.currentThread()
                sysOut.println &quot;${currentThread} begin&quot;
                def oldThreadCl = currentThread.contextClassLoader
                def cl = new MyGroovyClassLoader(oldThreadCl? oldThreadCl : this.class.classLoader)
                cl.errorStream = cmd.error; cl.inputStream = cmd.input; cl.outputStream = cmd.output
				
                def scriptName = command.size() &gt; 0?&quot;${command[0]}&quot;:''
                def scriptArgs = (command.size() &gt; 1? command.subList(1, command.size()): []) as String[]
                ThreadGroup tg = new ThreadGroup(currentThread.threadGroup, 
                                                 &quot;${currentThread.threadGroup.name}:${scriptName}&quot;)
                Thread t = new Thread(tg,
                                      {
                                          long time = -1; int result = -1
                                          try {							
                                              def scriptFile = new File(scriptName)
                                              if (scriptFile.parentFile) {cl.addURL(scriptFile.parentFile.toURI().toURL())}
                                              def script = cl.parseClass(scriptFile)
                                              assert cl.equals(findMyClassLoader(script.classLoader))
                                              time = System.currentTimeMillis()
                                              script = script.newInstance()
                                              script.args = scriptArgs; script.run()
                                              result = 0
                                          } catch (Exception e) {
                                              e =  StackTraceUtils.deepSanitize(e)
                                              sshd.log.error(&quot;Error running script ${scriptName}&quot;, e)
                                              e.printStackTrace()
                                              throw e
                                          } finally {
                                              try {
                                                  while (tg.activeCount() &gt; 1 || tg.activeGroupCount() &gt; 1) {Thread.sleep 100}
                                                  System.err.flush(); System.out.flush()
                                                  cl.release()
                                              } finally {
                                                  if (time &gt; 0) {time = System.currentTimeMillis() - time; sysOut.println &quot;${Thread.currentThread()} ${time} (ms)&quot;}
                                                  sysOut.println &quot;${Thread.currentThread()} end&quot;
                                                  cmd.callback.onExit(result)
                                              }
                                          }
                                      }
                                      as Runnable
                                     )
                t.contextClassLoader = cl
                t.start()	
            }
        ]
        
        return cmd as Command

    } as CommandFactory
)

/*sshd.publickeyAuthenticator = {username, key, session -&gt;
    return true
    } as PublickeyAuthenticator*/


/*sshd.passwordAuthenticator = {username, password, session -&gt;
    return true
    } as PasswordAuthenticator*/


def userAuthFactories = sshd.userAuthFactories
if (!userAuthFactories) {userAuthFactories = []}
userAuthFactories &lt;&lt; new UserAuthNone.Factory()
sshd.userAuthFactories = userAuthFactories


System.err = new PrintStream(new MyOutputStream(System.err, findMyClassLoader))
System.out = new PrintStream(new MyOutputStream(System.out, findMyClassLoader))
System.in = new MyInputStream(System.in, findMyClassLoader)

sshd.start()


class MyGroovyClassLoader extends GroovyClassLoader {

    def inputStream
    def outputStream
    def errorStream
    
    public MyGroovyClassLoader() {
        super()
    }

    public MyGroovyClassLoader(ClassLoader loader) {
        super(loader)
    }

    public MyGroovyClassLoader(GroovyClassLoader parent) {
        super(parent)
    }
    
    public void release() {
        errorStream?.flush(); outputStream?.flush()
        errorStream?.close(); outputStream?.close(); inputStream?.close()
    }
    
}

class MyInputStream extends InputStream {
    
    private InputStream input
    private Closure selectCl
    
    public MyInputStream(InputStream input, Closure selectCl) {this.input = input; this.selectCl = selectCl}

    @Override
    public int read() throws IOException {
        def cl = selectCl()
        return (cl? cl.inputStream : input).read()
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        def cl = selectCl()
        return (cl? cl.inputStream : input).read(b, off, len)
    }
          
}

class MyOutputStream extends OutputStream {
    
    private OutputStream output
    private Closure selectCl
    
    public MyOutputStream(OutputStream output, Closure selectCl) {this.output = output; this.selectCl = selectCl}

    @Override
    public void write(int b) throws IOException {
        def cl = selectCl()
        (cl? cl.outputStream : output).write(b)
    }
    
    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        def cl = selectCl()
        (cl? cl.outputStream : output).write(b, off, len)
        flush() //
    }

    @Override
    public void flush() throws IOException {
        def cl = selectCl()
        (cl? cl.outputStream : output).flush()
    }
    
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://techdm.com/grails/?feed=rss2&#038;p=323</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: basic

Served from: techdm.com @ 2013-05-24 11:01:56 -->