Grails: entendendo o SiteMesh

Ao aprender Grails um dos componentes que mais me confundiu foi o SiteMesh. Intuitivamente eu sabia o que estava acontecendo, mas toda vez que buscava escrever a respeito acabava me enrolando.

E acredite: você só conhece de fato algo se consegue descrevê-lo em palavras, por escrito. Trabalhando na última parte da minha série “Grails: do Groovy à Web” que está sendo publicada na Java Magazine tive a certeza de finalmente compreender de fato o que é o SiteMesh e como funciona. E a razão pela qual tinha tanta dificuldade é simples: estava viciado no Tiles.

Enquanto o Tiles é baseado no padrão composição (composite), o SiteMesh é baseado no padrão decorador (decorator).  A diferença entre os dois  é: no composite temos um layout central que contém uma série de espaços a serem preenchidos por  templates.

Já o padrão decorator possui um layout central que também possui espaços a serem preenchidos: a diferença é que apenas os elementos ausentes serão preenchidos. Eu não preciso adicionar todos os componentes tal como estava acostumado na época do Struts 1/Tiles.

Bla bla bla demais, é hora de irmos à prática. No Grails, todos os layouts do SiteMesh ficam armazenados no diretório grails-app/views/layouts. Por padrão já há um layout pré-definido, cujo nome é main.gsp armazenado neste diretório. É importante lembrar que se trata de um arquivo GSP convencional, cujo código exponho abaixo:

<html>
<head>
<title><strong><g:layoutTitle default="Grails" /></strong></title>
<link rel="stylesheet" href="${resource(dir:’css’,file:’main.css’)}" />
<link rel="shortcut icon" href="${resource(dir:’images’,file:’favicon.ico’)}" type="image/x-icon" />
<strong><g:layoutHead /></strong>
<g:javascript library="application" />
</head>
<body>
<div id="spinner" style="display:none;">
<img src="${resource(dir:’images’,file:’spinner.gif’)}" alt="Spinner" />
</div>
<div id="grailsLogo"><a href="http://grails.org"><img src="${resource(dir:’images’,file:’grails_logo.png’)}" alt="Grails" border="0" /></a></div>
<strong><g:layoutBody /></strong>
</body>
</html>

A única diferença entre o arquvo GSP e uma view convencional é a presença de três tags: g:layoutTitle, g:layoutHead, g:layoutBody. Falarei delas logo a seguir, porém antes de continuar, vou expor a view mais idiota possível: algo que não exponha basicamente nada, e cujo código fonte é o seguinte:


<html>
 <head>
 <meta name="layout" content="main"/>
 </head>
 <body>

 </body>
</html>

Colocando a aplicação para executar, e acessando-a, no entanto, é renderizado algo inicialmente inexperado:

De onde saiu este logotipo do Grails? Do layout main que defini anteriormente. No caso, eu instrui o Grails a usar o SiteMesh ao inserir a seguinte tag na minha view:


<meta name="layout" content="main"/>

Esta tag basicamente diz: “aplique o layout definido no arquivo grails-app/views/layouts/main.gsp a esta view”. E aqui entra a jusitificativa do mesh no nome SiteMesh: ao invés de incluir o conteúdo de um arquivo em outro, o que é feito na realidade é a fusão do conteúdo da view no corpo do layout!

Isto fica claro com a descrição das 3 tags que descrevi acima (consulte a primeira listagem para que fique claro):

g:layoutTitle – define qual será o conteúdo da tag title embutido na tag head. Repare qeu esta tag possui um atributo chamado “default”. Caso na view a tag title já esteja preenchida, será incluido no arquivo HTML final o conteúdo da tag title da view. Caso contrário, o conteúdo será aquele especificado no parâmetro default

g:layoutHead – o conteúdo da tag <head> da view será inserido no local do layout aonde a tag g:layoutHead se encontra.

g:layoutBody – o conteúdo da tag <body> da view será inserido no local do layout aonde a tag se encontra.

Resumindo: no SiteMesh não temos inclusão, mas sim fusão.

Espero que com esta descrição o recurso fique tão claro para vocês quanto pra mim.

Grande abraço e até a próxima!

13 thoughts on “Grails: entendendo o SiteMesh

  1. Valew show de bola… é o mesmo conceito de facelets

    Responda

    admin Reply:

    OI Gustavo. Fico feliz que tenha gostado. Mas convém mencionar que não é exatamente a mesma coisa.

    No Facelets você tem basicamente substituição de valores. No Sitemesh você tem fusão. Lembre-se disto.

    Responda

  2. Olá Kico, estou tentando aplicar um css no main.gsp, mas não estou conseguindo.
    Sou iniciante em grails também. Estou qrendo customizar minha aplicação.

    Responda

    admin Reply:

    Oi Amanda, faz o seguinte. Posta o seu problema com detalhes no Grails Brasil (porque tem mais espaço e gente pra ver o seu problema) e eu te ajudo ok?

    Grande abraço!

    Responda

  3. Nós passamos por um problema causado pelo Sitemesh: o filter dele remove a funcionalidade de flush de uma respons text/html.

    Explicando melhor: vamos supor que você queira fazer renderização parcial de páginas (como por exemplo faz o Facebook com a implementação de BigPipe) a medida que elas vão sendo processadas. É natural imaginar que o response.writer.flush faria o flush da resposta escrita até o momento. No entanto, o Sitemesh substitui o Writer da response por um que não realiza o flush até o fim do processamento (para poder fazer a fusão dos layouts)

    Em resumo: caso você tenha alguma página que precisa fazer flush parcial, você vai querer configurar o sitemesh para excluí-la.

    Solução: http://jira.grails.org/browse/GRAILS-5770

    Responda

    Rafael Augusto Reply:

    Um link melhor descrevendo a solução do problema:

    http://jira.grails.org/browse/GRAILS-5773

    Responda

  4. Olá Kico,

    Não entendi a diferença entre composição e decoração. Poderia explicar melhor esta frase? “a diferença é que apenas os elementos ausentes serão preenchidos”

    Obrigado!
    André

    Responda

  5. E se no meu body, eu tiver vários blocos para inserção de código?
    No meu caso, meu body tem side bar com um menu e o content.
    Como faço nesse caso? Já que no meu layout, só coloco um
    Poderia ter algo como e na outra parte do meu body, eu colocasse
    E na minha pagina gsp, eu pudesse informar qual parte vai para o sidebar e qual vai para o content.
    Existe alguma uma maneira de fazer isso?
    Abs

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    oi Leonardo, tem como postar esta sua duvida no Grails Brasil? é que costumo resolver este tipo dd duvida por la. assim ajudamos ao mesmo tempo pessoas que possuam a nesna duvida.

    Responda

  6. Nao sei porque, mas quando exemplifico com codigo html nao aparece nada no post

    Responda

    Kico (Henrique Lobo Weissmann) Reply:

    Motor recente do blog. To melhorando isto aos poucos, valeu pelo toque.

    Responda

Leave a Reply

Your email address will not be published. Required fields are marked *