Tag <c:set />, atributo scope (SCWCD)

Pessoal,

Encontrei uma ocasião aqui em meus estudos, que não achei no livro “Use a Cabeça - Servlet & JSP”:

isso:

	<c:set target="${count}" property="quatro" value="Four" scope="request"/>

Não funciona!!

Erro:

rg.apache.jasper.JasperException: <h3>Validation error messages from TagLibraryValidator for c in /jstl.jsp</h3><p>12: Illegal scope attribute without var in "c:set" tag.</p>
...

Ou seja, o atributo scope só funciona junto com o atributo “var” e não com “target”.

Esta certo…

Achei isso na API

scope java.lang.String Scope for var.

hehe… não deve ser tão importante assim para a prova, senão eles mencionavam no livro…

descobri por acaso, fazendo testes…

scope junto com target não faz sentido.

target diz qual variável será mexida, e seja qual for, ela já tem um escopo definido. Não faz sentido tentar alterar o escopo dela!

Alterar o escopo não, mas alterar uma variavel de determinado escopo faz sentido, é exatamente o que <c:set var> faz, se tem uma variavel no escopo é substituída, não vejo o real motivo de <c:set target> não ter scope. Ou estou perdendo algo aí no conceito…

Vamos supor que haja uma variável “foo” no request e uma “foo” no session.

Se você setar com <c:set var=“foo” blablabla/>, então eve vai colocar a variável naquele escopo não importando se já existia uma outra no lugar.
<c:set var=“foo” scope=“session” var="${requestScope.foo}"/> por exemplo, cria uma variável foo no session com o valor da variável foo do request. Apesar de ter o mesmo nome, são variáveis diferentes.

Mas, no target isso não ocorre, pois o scope é o escopo onde a variável vai ser COLOCADA e não de onde ela vai ser lida. Deste forma, <c:set target="${requestScope.foo}" value=“xxx” scope=“session”/> Tentaria pegar a variável foo do request e colocá-la no session com o valor xxx. Mas isso implica em criar uma nova variável e não setar ela. (se o requestScope for omitido acaba dando na mesma porque o container vai tentar procurar a variável do menor para o maior escopo até encontrar, mas seja lá em qual for o escopo que ele a encontre, a variável não pode ser colocada em um escopo diferente).

E por sinal, mudar o escopo de uma variável é absurdo. Este exemplo mostra que se isso fosse possível, haveriam efeitos colaterais muito estranhos:

<c:set var="foo" value="xxx" scope="request"/> <c:out value="{requestScope.foo}" /> <c:set target="${foo}" value="yyy" scope="session"/> <c:out value="{requestScope.foo}" />

No segundo c:out, a variável misteriosamente teria mudado de escopo como efeito colateral de ter recebido um novo valor, algo que é no mínimo indesejável.

Acho que saquei.

A idéia de <c:set> com “target” é somente mudar o valor de uma variável que já existe, não importando qual “scope”. Se o valor de target calcular pra null dá erro…

Já <c:set> com “var” pode criar variáveis caso não exista no escopo definido, sobrescrever o seu valor, ou ainda excluir do escopo caso o atributo já exista no escopo, passando um valor null em “value”.

mais ou menos por ai?