Hi Antonio,

So, we also have this use case where we want to make sure the nested definition gets rendered:
https://github.com/apache/tiles/blob/TILES_3_0_X/tiles-test-pom/tiles-test/src/main/webapp/testinsertnesteddefinition_tags.jsp

I agree that trying to defer evaluation here creates all kinds of challenges. But instead of creating a new tag, I wonder if we shouldn't remove one.

I've never been much of a fan of declaring definitions inline in a JSP, and inserting it later. I think, at the top level it is a bad practice. The only place where it makes sense to me is inside a putAttribute tag, because it allows to defer the evaluation of the attribute.

But then if we defer evaluation anyway, we could use insertTemplate or insertDefinition instead. I'd just like to double check about cascading attributes, making sure we don't loose the feature in the change.

Do I make any sense?

Nick

PS: if there are no other use cases, I feel it is a minor optimization. Inline content (that would be evaluated on "put" instead of "insert") is usually small in practice. If it is big, it is easy to externalize it in a JSP or another definition, and this would be evaluated upon insert, in addition to begin more readable. Do you think the optimization would be worth the effort?

On 05/31/2016 08:48 AM, Antonio Petrelli wrote:
Hi Nicolas, see my answers inline.

2016-05-31 1:53 GMT+02:00 Nicolas Le Bas <[email protected]>:

Concerning put/add-attribute... I'd like to look at some use cases.

There is this one in our selenium test suite:

https://github.com/apache/tiles/blob/TILES_3_0_X/tiles-test-pom/tiles-test/src/main/webapp/testinsertdefinition_inline.jsp
but I think we should look at something more complex.

Yes, this is a static string, so nothing important.


What do you think of this one:

<c:forEach var="line" items="${orderLines}">
     <tiles:insertDefinition name="orderLine">
        <tiles:putAttribute name="description">
            Item ${line.number}: ${line.product.name} for ${line.price} €
        </tiles:putAttribute>
     </tiles:insertDefinition>
</c:forEach>

Is this the kind of thing you mean when you talk about moving JSPFragments
around the request?

Yes it is.


As for the "body renderer"... I like it, but I don't line the map with a
"generated name" in the request.
I think we could just put the renderer as the value of the new attribute
object that we create in putAttribute?

The big problem is a bunch of lines in
BasicTilesContainer.render(Attribute, Request):

<snip>
             if (!(value instanceof String)) {
                 throw new CannotRenderException(
                         "Cannot render an attribute that is not a string,
toString returns: "
                                 + value);
             }
</snip>

In other words, I cannot render an attribute that is not a string. For this
reason I thought of a string key -> body map.

Anyway I think we need another tag. This is because putAttribute's body
must be evaluated when there is a definition inside, so that it can be
connected to it. A new tag, that puts a body as a value, directly or
indirectly via a map, must be created to avoid evaluating the body twice.

Antonio


Reply via email to