Usando Templates, Controller.groovy alterado não é respeitad
28/01/2010 00:00
0
Pessoal estou com o seguinte problema:
Instalei os templates em meu projeto (Controller.groovy, create.gsp, edit.gsp, list.gsp, renderEditor.template, show.gsp) para poder customizá-los. Os arquivos foram instalados na pasta src/templates/scaffolding.

Quando faço alterações nos arquivos create.gsp, edit.gsp, list.gsp e show.gsp funciona tudo normal.
Entretanto, quando altero o arquivo Controller.groovy o Grails não respeita as alterações que eu faço.

Vejam só um exemplo: pretendo retornar na action 'list' um parâmetro adicional chamado 'exibir'. Este parâmetro irá conter um Map com as propriedades que devem ser exibidas na lista.

Para obter o valor do parâmtro 'exibir' eu uso a função 'listExibir' que é sobrescrita no controller individual de cada class-domain.

Vejam só como está o meu arquivo Controller.groovy:
<%=packageName ? &quot;package ${packageName}\n\n&quot; &#58; ''%>class ${className}Controller {
static allowedMethods = [save&#58; &quot;POST&quot;, update&#58; &quot;POST&quot;, delete&#58; &quot;POST&quot;]
def index = {
redirect(action&#58; &quot;list&quot;, params&#58; params)
}
def list = {
params.max = Math.min(params.max ? params.int('max') &#58; 10, 100)
[${propertyName}List&#58; ${className}.list(params),
${propertyName}Total&#58; ${className}.count(),
exibir&#58; listExibir()]
}
Map listExibir() {
return [&quot;nenhum&quot;&#58; false];
}
// .... DEMAIS BLOCOS DE CÓDIGO ....
}


Agora, vejam como está o meu arquivo DotacaoOrcamentariaController.groovy que serve como controlador para a domain-class DotacaoOrcamentaria.groovy:
package planejamento

class DotacaoOrcamentariaController {

def scaffold = DotacaoOrcamentaria;
Map listExibir() {
return [&quot;orgao&quot;&#58;true,
&quot;classificacao&quot;&#58;true,
&quot;valorDotacao&quot;&#58;true,
&quot;valorAutorizacao&quot;&#58;true,
&quot;saldoAposAutorizacao&quot;&#58;true,
&quot;valorEmpenho&quot;&#58;true,
&quot;saldoAposEmpenho&quot;&#58;true
];
}
}


O meu arquivo de template list.groovy possui o seguinte código na parte principal que lista os dados:
<div class=&quot;list&quot;>
<table>
<thead>
<tr>
<% excludedProps = Event.allEvents.toList() << 'version'
props = domainClass.properties.findAll { !excludedProps.contains(it.name) &amp;&amp; it.type != Set.class }
Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
props.eachWithIndex { p, i ->
boolean bListar = ((i == 0) || (exibir.size() == 0));
if(!bListar) {
bListar = (exibir.containsKey(p.name) ? exibir.get(p.name) &#58; false);
}
if (bListar) {
if (p.isAssociation()) { %>
<th><g&#58;message code=&quot;${domainClass.propertyName}.${p.name}.label&quot; default=&quot;${p.naturalName}&quot; /></th>
<% } else { %>
<g&#58;sortableColumn params=&quot;\${filterParams}&quot; property=&quot;${p.name}&quot; title=&quot;\${message(code&#58; '${domainClass.propertyName}.${p.name}.label', default&#58; '${p.naturalName}')}&quot; />
<% } } }%>
</tr>
</thead>
<tbody>
<g&#58;each in=&quot;\${${propertyName}List}&quot; status=&quot;i&quot; var=&quot;${propertyName}&quot;>
<tr class=&quot;\${(i % 2) == 0 ? 'odd' &#58; 'even'}&quot;>
<% props.eachWithIndex { p, i ->
if (i == 0) { %>
<td><g&#58;link action=&quot;show&quot; id=&quot;\${${propertyName}.id}&quot;>\${fieldValue(bean&#58; ${propertyName}, field&#58; &quot;${p.name}&quot;)}</g&#58;link></td>
<% } else {
boolean bListar = (exibir.size() == 0);
if(!bListar) {
bListar = (exibir.containsKey(p.name) ? exibir.get(p.name) &#58; false);
}
if (bListar) {
if (p.type == Boolean.class || p.type == boolean.class) { %>
<td><g&#58;formatBoolean boolean=&quot;\${${propertyName}.${p.name}}&quot; /></td>
<% } else if (p.type == Date.class || p.type == java.sql.Date.class || p.type == java.sql.Time.class || p.type == Calendar.class) { %>
<td><g&#58;formatDate date=&quot;\${${propertyName}.${p.name}}&quot; /></td>
<% } else { %>
<td>\${fieldValue(bean&#58; ${propertyName}, field&#58; &quot;${p.name}&quot;)}</td>
<% }}}}%>
</tr>
</g&#58;each>
</tbody>
</table>
</div>


Ao executar o aplicativo, assim que acesso o controller dotacaoorcamentaria/list , recebo a seguinte mensagem de erro:
2010-01-28 17:49:34,166 [http-8080-1] ERROR view.ScaffoldingViewResolver - Error generating scaffolded view [/dotacaoOrcamentaria/list]: No such property: exibir for class: SimpleTemplateScript6
groovy.lang.MissingPropertyException: No such property: exibir for class: SimpleTemplateScript6
at SimpleTemplateScript6$_run_closure2.doCall(SimpleTemplateScript6.groovy:46)
at SimpleTemplateScript6.run(SimpleTemplateScript6.groovy:45)
at java.lang.Thread.run(Thread.java:619)


Observem que o erro acontece porque o Grails não consegue encontrar a propriedade exibir da classe SimpleTemplateScript6.
O único exibir que possuo é o parâmetro que eu estou tentando retornar através do template Controller.groovy.

A impressão que eu tenho é que o Grails não está usando o arquivo Controller.groovy para gerar os controladores com scaffold. Entretanto ele está usando os demais arquivos e como o list.gsp exige o parâmetro exibir o problema ocorre.

É como se o Grails continuasse usando o Controller.groovy original, ignorando o que está dentro da minha aplicação.

Alguém já passou por problema semelhante?
Será que alguém consegue me ajudar?

Fico grato pela atenção.
Tags: Ferramentas/Plugins


0
Pontos a serem observados:

qual a versão do Grails que você está usando?
já tentou executar o coamndo grails clear?


0
Olá!
Estou usando o grails-1.2.0.
executei o comando grails clean e foi limpo o cache do grails.

Eu não mencionei que estou usando o SpringSource Tool Suite 2.3.0.RELEASE para editar o código fonte.

Entretanto, eu criei um novo projeto usando um editor de textos &quot;comum&quot; e o problema continua o mesmo.

Eu reinstalei o Grails e não adiantou.

Fiz o seguinte teste: declarar EXPLICITAMENTE a variável exibir dentro do list.groovy.
Vejam como ficou:
...
<thead>
<tr>
<% excludedProps = Event.allEvents.toList() << 'version'
props = domainClass.properties.findAll { !excludedProps.contains(it.name) &amp;&amp; it.type != Set.class }
Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
Map exibir = [&quot;orgao&quot;&#58;true,
&quot;classificacao&quot;&#58;true,
&quot;valorDotacao&quot;&#58;true,
&quot;valorAutorizacao&quot;&#58;true,
&quot;saldoAposAutorizacao&quot;&#58;true,
&quot;valorEmpenho&quot;&#58;true,
&quot;saldoAposEmpenho&quot;&#58;true
];
props.eachWithIndex { p, i ->
boolean bListar = ((i == 0) || (exibir.size() == 0));
if(!bListar) {
bListar = (exibir.containsKey(p.name) ? exibir.get(p.name) &#58; false);
}
if (bListar) {
if (p.isAssociation()) { %>
<th><g&#58;message code=&quot;${domainClass.propertyName}.${p.name}.label&quot; default=&quot;${p.naturalName}&quot; /></th>
<% } else { %>
<g&#58;sortableColumn params=&quot;\${filterParams}&quot; property=&quot;${p.name}&quot; title=&quot;\${message(code&#58; '${domainClass.propertyName}.${p.name}.label', default&#58; '${p.naturalName}')}&quot; />
<% } } }%>
</tr>
</thead>
...

Tudo funcionou perfeitamente.

Realmente, parece que o Controller.groovy não está retornando o parâmetro 'exibir'.

Eita, deste problema eu estou apanhando feio. O pior é que não consigo identificar o que estou fazendo algo de errado.
<!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( -->
29/01/2010 00:00


0
Pessoal, ainda não encontrei solução para este problema.
Entretanto, busquei uma saída alternativa:

Como as alterações que eu faço no arquivo list.gsp são respeitadas pelo Grails, eu resolvi fazer o seguite:
1 - criar uma nova classe com um método estático para recuperar as colunas que eu gostaria de listar(ControladorDeExibicao.obterListaAtributos): para este método eu informo o nome completo da classe de domínio que eu quero que sejam retornados os atributos, incluindo o pacote;
class ControladorDeExibicao {
public static Map obterListaAtributos(String p_sClasseDeDominio) {
// retorno os atributos aqui
}
}

2 - alterar o arquivo list.gsp para chamar este método e obter a lista dos atributos que eu gostaria de listar;
Map oLstExibir = ControladorDeExibicao.obterListaAtributos(domainClass.fullName);

3 - Percorrer esta lista de atributos e gerar o html para cada um deles;
oLstExibir.each(){ key, value ->
def p = domainClass.properties.find { it.name == key };
// Aqui entra o código original do template list.gsp para gerar o html
}


Eu penso que esta não é a melhor solução, pois acho que o controlador de cada classe de domínio é quem deveria responder quais colunas deveriam ser listadas.

PS.: Seguindo a mesma estratégia eu mexi também nos arquivos create.gsp, edit.gsp e show.gsp para que apenas fossem exibidos nas respectivas páginas os atributos retornados pelo método estático ControladorDeExibicao.obterListaAtributos.

É isso aí pessoal, se alguém tivem alguma idéia melhor, não deixe de comentar.
08/02/2010 00:00


0
Pessoal,

resolvi este problema da seguinte forma:

Na classe:

class Pessoa {

String nomePessoa
String cpf
String nomeMae
String nomePai
String sexo

static List obterListaDeAtributosParaExibir() {
[&quot;id&quot;,&quot;nomePessoa&quot;,&quot;cpf&quot;]
}
}

No list.gsp:

Coloquei este código antes da tag <htm> para pegar o nome do pacote, se existir, e o nome da classe


<%
String packageAndClassName = className
if (packageName.length() > 0) {
packageAndClassName = domainClass.packageName + &quot;.&quot; + className
}
%>

Depois, a onde o grails já traz alguma codificação alterei para isto

<%
1- List listaDeAtributosParaExibir = Class.forName(packageAndClassName, true,
2- Thread.currentThread().getContextClassLoader()).obterListaDeAtributosParaExibir()
3- int numberFields = listaDeAtributosParaExibir.size()
4- if (listaDeAtributosParaExibir.isEmpty()) {
/* Inclui as primeiras 4 linhas
5- excludedProps = Event.allEvents.toList() << 'version'
6- allowedNames = domainClass.persistentProperties*.name << 'id' << 'dateCreated' << 'lastUpdated'
7- props = domainClass.properties.findAll { allowedNames.contains(it.name) &amp;&amp; !excludedProps.contains(it.name) &amp;&amp;
8- !Collection.isAssignableFrom(it.type) }
/* As linhas 5,6,7 e 8 são as que vieram do template
9- numberFields = 6
10- } else {
11- props = domainClass.properties.findAll {listaDeAtributosParaExibir.contains(it.name)}
12- }
/* Inclui as linhas 9,10,11 e 12
.
(outros comandos gerandos pelo template


Espero ter ajudado
26/08/2010 00:00


0
Olá Valdinei!
Sua resposta me ajudou muito.

Muito obrigado!
21/01/2011 00:00



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto