Syntax coloring

quinta-feira, 27 de março de 2008

Main layout by convention in Grails

Grails supports selecting the page layout either using the <meta name="layout" content="NAME"> tag or by convention, where the layout is grails-app/views/layouts/CONTROLLER.gsp or grails-app/views/layouts/CONTROLLER/ACTION.gsp.

I've asked myself several times why doesn't it support the main layout by convention? Maybe because of the partial pages retrieved by Ajax (like the <g:remoteLink> tag). Even on those cases, an heuristic might be applied to determine those cases. Let's go to the actual implementation:

Create a class called CustomLayoutDecoratorMapper on src/groovy:
import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest
import org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper
import com.opensymphony.module.sitemesh.*
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods

class CustomLayoutDecoratorMapper extends GrailsLayoutDecoratorMapper {

public Decorator getDecorator(HttpServletRequest request, Page page) {
Decorator decorator = super.getDecorator(request, page)
if (decorator == null) {
decorator = getNamedDecorator(request, "main")
}
return decorator
}
}


Then reference it on web-app/WEB-INF/sitemesh.xml, by changing the mapper tag, so that it looks like this: <mapper class="CustomLayoutDecoratorMapper">. Note that when running grails upgrade the file will be reverted to it's original form!.

Ready! No more need to declare the layout on every page. But, if the layout is declared, it will be honored.

But what about the Ajax requests? I can think of 2 approaches: The first one is easier for people using the Prototype framework. Just change the line:
if (decorator == null) {
to:
if (decorator == null && request.getHeader("X-Requested-With") != "XMLHttpRequest") {
Prototype adds the header X-Requested-With: XMLHttpRequest for Ajax requests. I don't know whether Dojo does something like that...

The second option is to declare an empty layout on Ajax pages with <meta name="layout" content="empty">, and create the layout called empty only with the tag <g:layoutBody>.

Hope this helps!

Layout principal por convenção no Grails

O Grails suporta a seleção do layout da página usando usando uma tag , ou por convenção para casos onde o layout é grails-app/views/layouts/CONTROLLER.gsp ou grails-app/views/layouts/CONTROLLER/ACTION.gsp.

Mas me perguntei algumas vezes porque ele não suporta um layout principal por convenção? Talvez por causa das requisições por ajax (como o com a tag %lt;g:remoteLink>), que retorna uma página parcial. Mas mesmo assim poderia usar um layout principal usando alguma heurística para esse caso. Vamos à implementação:

Crie uma classe chamada CustomLayoutDecoratorMapper no src/groovy:
import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest
import org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper
import com.opensymphony.module.sitemesh.*
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods

/**
* Decorador de layout para permitir o uso de um layout global
*/
class CustomLayoutDecoratorMapper extends GrailsLayoutDecoratorMapper {

public Decorator getDecorator(HttpServletRequest request, Page page) {
Decorator decorator = super.getDecorator(request, page)
if (decorator == null) {
decorator = getNamedDecorator(request, "main")
}
return decorator
}
}


Depois referencie essa classe no web-app/WEB-INF/sitemesh.xml, alterando a tag mapper para que ela fique assim: <mapper class="CustomLayoutDecoratorMapper">.

Pronto! Não precisa mais declarar o layout em cada página. Mas caso isso seja feito, será respeitado o layout definido.

Mas e os casos de requisições Ajax? Há duas abordagens. A primeira é mais fácil para quem usa o Prototype: Basta alterar a linha
if (decorator == null) {
para:
if (decorator == null && request.getHeader("X-Requested-With") != "XMLHttpRequest") {
Isso porque o prototype adiciona o cabeçalho X-Requested-With: XMLHttpRequest para requisições Ajax. Não sei se o Dojo faz algo do tipo...

A segunda opção é declarar um layout vazio em cada página parcial usar a <meta name="layout" content="empty">, e criar um arquivo de layout apenas com a tag <g:layoutBody>.

Espero que tenha ajudado!

Esta postagem também está disponível em inglês.

segunda-feira, 3 de março de 2008

Linguagens de programação - De programador Java para programador Java

Aprendi programação em Visual Basic 3 (eca!), lá por 1995. De lá passei pro ASP (bah) em 2000, pro Java em 2001 e aí estou até hoje.
Mas desde o ano passado, venho estudando linguagens dinâmicas, como o Ruby e o Groovy. Já conheço há anos (e acho bem legal) o JavaScript, uma linguagem tão odiada entre os programadores para a web (o que acho uma injustiça). Mas cito Ruby e Groovy porque são linguagens que estão bem faladas hoje em dia, e têm uma infraestrutura bem completa.
Primeiro foi o Ruby. A linguagem é nota 10. É possível fazer coisas do tipo:

class String
def bold
"#{self}"
end
end
Resultado: todas as Strings possuem um método bold, e se for invocado "teste".bold retornará teste. Para horror dos programadores Java mais conservadores, foi reaberta a definição de uma classe existente (e importante como a String), adicionado um método que nem tem um comando return e ainda por cima invocado sem usar parênteses!
E o que dizer de código tipo:
[1, 2, 3].collect {|x| x + 2}

O resultado? Um array contendo [3, 4, 5]. Assim também vários outros exemplos interessantes.
O Ruby tem sido muito impulsionado ultimamente pelo framework Ruby on Rails, que mudou drasticamente o conceito de framework web (Struts, Spring MVC...).
Apesar de muito interessante, a linguagem é bem distante do Java, e quem investiu pesado em formação e tecnologia Java (quem dirá servidores de aplicação) não vai querer jogar tudo fora...
Claro que existe o JRuby, que é uma implementação do Ruby para Java que é muito boa e permite fácil integração com classes Java, mas o "gap" ainda é grande.
Então conheci o Groovy, que tenta ser o mais próximo possível do Ruby, mantendo uma sintaxe bem semelhante à do Java. E tem também o framework Grails, que tenta trazer para o Groovy as facilidades do Ruby on Rails.
E o Groovy, junto com o Grails, é a minha aposta para o framework web. Certamente minha escolha para o próximo projeto Java. Ele "nasceu" integrado ao Spring e ao Hibernate, e pode ser instalado (algum termo melhor para deployed?) em qualquer servidor web Java.
Vale a pena dar uma olhada.
Claro que muitos ainda resistem à idéia de linguagens dinâmicas, pois se "perde o controle" que a tipagem estática oferece (apesar do Groovy permitir usar tipagem estática) e que "efeitos colaterais" de adicionar métodos dinâmicos em classes. Mas assim foi quando se passou do assembly para o C. Assim foi quando se passou do C para o Java. E assim está sendo para tornar o próprio Java obsoleto. Muito se fala hoje que o Java como linguagem está condenado. Mas a JVM é um ambiente sólido, performático e confiável, e esse sim, vai durar muito tempo.