Preâmbulo

Tempo é um recurso valioso. Por isso princípios como KISS e DRY são importantes e aplicáveis aqui.

Desculpo-me previamente pelas simplificações extremas e utilização excessiva de hyperlinks. Sintam-se à vontade para discutirem o que julgarem relevante, usando os meios adequados.

Por que Groovy e Grails?

Groovy = Java++

Grails = (Spring Framework + Hibernate)++

Com o tempo e o amadurecimento do desenvolvedor e da própria tecnologia:

Groovy = Java**

Grails = (Spring Framework + Hibernate)**

Escreve-se o mesmo tipo de aplicação, em um tempo significativamente menor.

E se eu descobrir que parte do código em Groovy está afetando o desempenho da minha aplicação?

Continue reading

Nova jornada

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.

Novo plugin para Grails: hibernate-spatial

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.

Dicas de scripts Gant em Grails

  1. Enquanto GRAILS-7274 não for corrigido, use try-catch ao escrever build event handlers;
        eventCreateWarEnd = {warName, stagingDir ->
             try {
                 // Script logic goes here...
             } catch (Exception e) {
                 e.printStackTrace()
                 throw e
             }
        }
    
  2. Adicione “verbosidade” ao log do Gant, sempre que necessário:
    import org.codehaus.gant.GantState
    // (...)
    GantState.verbosity = GantState.VERBOSE
    ant.logger.setMessageOutputLevel(GantState.verbosity)
    
  3. Prefira AntBuilder.path à utilização de elementos aninhados de classpath:
            ant.path(id: 'myClasspath', { pathelement(location: 'somewhere') })
            ant.java(classname: 'aClass', dir: 'anyDir', fork: true, 
                        classpathref:'myClasspath') {}
    

O “prêmio” 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 criação do arquivo .war do seu projeto:

// _Events.groovy
import org.codehaus.gant.GantState

eventCreateWarEnd = {warName, stagingDir ->

    def beaHome = System.getenv('BEA_HOME')?: 'C:/bea'
    try {
        println "Executing weblogic.appc ${beaHome} ${warName}"

        //GantState.dryRun = true
        GantState.verbosity = GantState.VERBOSE
        ant.logger.setMessageOutputLevel(GantState.verbosity)

        File warFile = new File(warName)
        File tmpFile = new File(warFile.parentFile, "${warFile.name.tokenize('.')[0]}_tmp.war")
        ant.move(file: warFile, tofile: tmpFile)

        ant.path(id: 'appcClasspath', { pathelement(location: "${beaHome}/wlserver_10.3/server/lib/weblogic.jar") })

        ant.java(classname: 'weblogic.appc', dir: warFile.parentFile, fork: true, classpathref:'appcClasspath') {
            arg(line: "-output ${warFile.name} -lineNumbers -g -O -keepgenerated ${tmpFile.name}")
        }
    } catch (Throwable e) {
        e.printStackTrace()
        throw e
    }
}

Referências adicionais:

Código-fonte buscável e navegável

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:

Continue reading

Melhoria de desempenho do freemarker-tags

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á muito próxima à de uma página GSP compilada:

A) Aplicação quick_start iniciada usando ‘grails prod run-war’ e testada usando ‘ab -n 3000 -c 30 url’

#request/second (mean)

freemarker-tags-0.6.1

list: 165.99 #/sec, 403.29 #/sec, 448.74 #/sec, 421.15 #/sec
create: 201.49 #/sec, 407.45 #/sec, 449.79 #/sec, 436.02 #/sec
show: 231.39 #/sec, 428.36 #/sec, 496.63 #/sec, 468.14 #/sec
edit: 186.29 #/sec, 348.25 #/sec, 388.07 #/sec, 372.15 #/sec

gsp

list: 248.94 #/sec, 714.39 #/sec, 777.56 #/sec, 688.66 #/sec
create: 251.24 #/sec, 712.82 #/sec, 891.65 #/sec, 813.68 #/sec
show: 250.04 #/sec, 742.08 #/sec, 990.49 #/sec, 918.49 #/sec
edit: 230.59 #/sec, 720.73 #/sec, 903.11 #/sec, 783.17 #/sec

freemarker-tags-0.7.0

list: 222.27 #/sec, 670.82 #/sec, 720.34 #/sec, 627.70 #/sec
create: 218.92 #/sec, 618.93 #/sec, 750.98 #/sec, 695.02 #/sec
show: 250.08 #/sec, 786.39 #/sec, 1040.83 #/sec, 878.74 #/sec
edit: 211.43 #/sec, 636.35 #/sec, 823.98 #/sec, 757.29 #/sec

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 FreeMarker:
Continue reading

Gerenciamento programático de transações em Grails

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:

        User.withTransaction {
        }

        User.withTransaction(isolation: 'readUncommitted') {
        }

        User.withTransaction(readOnly: true, timeout: 'default') {
        }

        User.withTransaction(propagationBehaviorName: 'PROPAGATION_MANDATORY', timeout: 765) {
        }

        User.withTransaction(propagation: "mandatory") {
        }

        User.withNewTransaction {
        }

        User.withNewTransaction(isolationLevel: TransactionDefinition.ISOLATION_SERIALIZABLE) {
        }

        User.withNewTransaction(propagation: 'supports', readOnly: true, timeout: 612) {
        }

        User.withNewTransaction(isolationLevelName: 'ISOLATION_REPEATABLE_READ') {
        } 

Continue reading

GSP x FTL (microbenchmark)

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 tópico sobre o desempenho de renderização de vários frameworks web.

Seguem-se os resultados obtidos, para o cenário particular do tópico em questão:

Apache HTTP server benchmarking tool (ab)

  • GSP

    Document Path: /grailsapp/products
    Document Length: 1037698 bytes

    Concurrency Level: 30
    Time taken for tests: 383.757685 seconds
    Complete requests: 3000
    Failed requests: 0
    Write errors: 0
    Total transferred: 3113592000 bytes
    HTML transferred: 3113094000 bytes
    Requests per second: 7.82 [#/sec] (mean)
    Time per request: 3837.577 [ms] (mean)
    Time per request: 127.919 [ms] (mean, across all concurrent requests)
    Transfer rate: 7923.27 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 1.1 0 14
    Processing: 2105 3829 380.8 3831 5122
    Waiting: 2097 3824 381.0 3825 5120
    Total: 2105 3829 380.9 3831 5122

    Percentage of the requests served within a certain time (ms)
    50% 3831
    66% 3987
    75% 4092

  • FTL

    Document Path: /grailsapp-fm/products
    Document Length: 1026697 bytes

    Concurrency Level: 30
    Time taken for tests: 103.94286 seconds
    Complete requests: 3000
    Failed requests: 0
    Write errors: 0
    Total transferred: 3080604000 bytes
    HTML transferred: 3080091000 bytes
    Requests per second: 29.10 [#/sec] (mean)
    Time per request: 1030.943 [ms] (mean)
    Time per request: 34.365 [ms] (mean, across all concurrent requests)
    Transfer rate: 29181.07 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.0 0 0
    Processing: 74 1027 646.1 962 4373
    Waiting: 71 988 643.3 915 4006
    Total: 74 1027 646.1 962 4373

    Percentage of the requests served within a certain time (ms)
    50% 962
    66% 1212
    75% 1376

JMeter
Continue reading

Usando Grails para construir um sistema batch simples

Inspirado pela discussão sobre ‘Como eu carregaria um job Quartz a partir de um script’ e baseando-me na postagem sobre o ‘Tiny GroovyServ’, 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 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.

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:

  1. Efetuar download do arquivo simple_batch_system-0.1.zip (o arquivo possui, aproximadamente, 25 MBytes e contém todas as dependências necessárias à execução da aplicação)
  2. Descompactar o arquivo em um diretório qualquer
  3. Iniciar a aplicação (o único pré-requisito para esse passo é ter uma JRE instalada e o java estar disponível no PATH)

    [daniel@techdm simple_batch_system-0.1]$ ./simple_batch_system.sh

    ou

    simple_batch_system.bat

  4. Disparar a execução de serviços ou tarefas agendadas, como admin0 (a senha é admin):

    ssh -p 8123 admin0@localhost task1Job,task3Service

Continue reading

Tiny GroovyServ

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 comandos de execução de script ao servidor. A idéia segue a mesma linha de raciocínio da combinação ‘groovy -l’ e telnet. Para todo o tratamento do protocolo SSH, foi utilizado o Apache Mina SSHD.

Vale ressaltar que o servidor 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 SecurityManager devidamente configurado, bem como a adoção de mecanismo de autenticação adequado.

Passo-a-passo para a utilização:

1. Efetuar download do código-fonte do servidor

2. Descompactar o conteúdo do arquivo em um diretório

3. Iniciar o servidor

[user@techdm tiny-groovyserv]$ groovy tgserv.groovy

ou

[user@techdm tiny-groovyserv]$ groovy tgserv.groovy 8123

4. Escrever alguns scripts no mesmo computador

5. Iniciar mais de prompt de comando ou shell e executar, simultaneamente, os scripts criados

[user@techdm test]$ ssh -p 8123 localhost /tmp/test/a.groovy abc 123

[user@techdm dir1]$ ssh -p 8123 localhost /tmp/test/dir1/b.groovy

[user@techdm dir2]$ ssh -p 8123 localhost /tmp/test/dir2/c.groovy

ou usando plink:

C:\tmp\test> plink -P 8123 -ssh -l x localhost c:/tmp/test/a.groovy abc 123

C:\tmp\test\dir1> plink -P 8123 -ssh -l x localhost c:/tmp/test/dir1/b.groovy

C:\tmp\test\dir2> plink -P 8123 -ssh -l x localhost c:/tmp/test/dir2/c.groovy

Projeto no github.

Referências adicionais:

Continue reading