Showing posts with label JSTL. Show all posts
Showing posts with label JSTL. Show all posts

Tuesday, August 10, 2010

"RowSet Wrapper List Strategy" and reality

"RowSet Wrapper List Strategy" and reality....

From Core J2EE Patterns: Best Practices and Design Strategies.

While the Transfer Object Collection strategy is one way to implement your finder methods,it might prove expensive if the query returns a large set of results and you end up creating a large collection of transfer objects, which are used sparingly by the client. Clients typically search and use the first few result items and discard the rest. When an application is executing a query that returns a large set of results, the RowSet Wrapper List strategy might be more efficient though it requires additional work and adds more complexity.

Code presented in the book is focused on RowSet wrapper and the code has 61+73 lines just as sample, and is
suitable only for RowSets. Get the book, read the samples, it is nice reading. However:

Using generics and AbstractList we can rewrite the original to 20lines long
"General Wrapper List" implementation, capable to transform any List<O> into List<E> by supplied convert method.


import java.util.AbstractList;
import java.util.List;

public abstract class WrappedList<O, E> extends AbstractList<E> {
public abstract E convert(O original);
private List<? extends O> original;
public WrappedList(List<? extends O> original) {
this.original = original;
// TODO: defensive copy ?, performance will suffer,
// and here we code for performance
// this.original=new ArrayList<O>(original);
}
public E get(int index) {
// TODO: caching ?
return this.convert(original.get(index));
}
public int size() {
return original.size();
}
}


This code has the same "quality" as the one presented in the book, and creates:
unmodifiable list (unexpected that view modifies list) which is
indirectly mutable (for sake of performance we do not make defensive copy of supplied original list),
that produce not equals (!=) instances with subsequent get(index) for the same index.

Using this to produce RowSet Wrapperfrom book, requires subclasing (anonymous inner class)
and this extra code (from book):

21 public Object get(int index) {
22 try {
23 rowSet.absolute(index);
24 } catch (SQLException anException) {
25 // handle exception
26 }
27 // create a new transfer object and return
28 return
29 TORowMapper.createCustomerTO(this);
30 }

moved to overrided convert method.

This way we have implemented optimized collection suitable to be used inside
c:forEach or jsf:table tags supporting start and end attribues.

Imagine situation where you have 1000 records from model and need to view only 10 of them.


<c:forEach items="${list}" var="l" begin="0" end="9">....


If list is constructed with the usuall "Value Object Collection" (copy and transform all)
it caouses 1000 calls to convert instances
of Value Object of type O into Value Objects of type E,
and creates 1000 of new instances of E.
In out case only 10 calls will be made and 10 new objects will be created.

Surprise:

<c:forEach items="${list}" var="l" begin="10" end="19">....


I would expect 10 again. But wrong it is 20 !.

<c:forEach items="${list}" var="l" begin="990" end="999">....

Will be 1000.

Thanx for clever code inside javax.servlet.jsp.jstl.core.LoopTagSupport.

Another idea of "too early full copy" arrays can be found here:
org/apache/taglibs/standard/tag/common/core/ForEachSupport.

Conclusions:

Even if you try to design with performance in mind,
even if you try to design by patterns and strategies,
choice of other libraries can eliminate
or even negate your efford.
.

Maybe, we will fix this soon, stay tuned.

Thursday, August 5, 2010

${}, fmt:message and fn:escapeXml

As expected ${exp} nor fmt:message
DO NOT PERFORM xml escaping.

99% of mine usage of both is to produce texts (text elements, or attribute values).
Only 1% of mine situations contain markup inside "exp" expression.

As EL values come from various and 99% enescaped sources (params,resources, db...)
I have to use c:out or fn:escapeXml over and over which enlarges the source code,
and creates unnecesary mess.

This is very sad, and I would like to propose new $$ operator for EL
which I would like to use as default,
(shall I implement this my self ? How ? When ? Where ?)
or I have missed some trivial trick ?

The hope for declarative tag based markup, disapears soon with my paranoid escaping of output:

<fmt:setBundle var="localizationContext" basename="tags" />
<c:set var="bundle" value="${localizationContext.resourceBundle}" />
.....

<fmt:message bundle="${localizationContext}" key="fileTable.lastModified" var="strLastModified"/>
<c:out value="${strLastModified}"/>

the last two lines hurt my eyes,
and polute pageScope with useless variable,
so I tend to rewrite it soon into:

${fn:escapeXml(bundle['fileTable.lastModified'])}

Apart from losing the declarative beauty, I have no clue about runtime consequences ;-) I have to read, thing and reverse engineer maybe a bit.

Please is anyone willing to educate me ?
Thanx.

Update:

c:out CAN HAVE BODY,
just stupid design,
since it MUST have value attribute.

Only when value is null, the body is processed.

<c:out value="${null}">
<fmt:message bundle="${localizationContext}" key="parametrized.markup">
<fmt:param value="${bundle['namespaced.markup']}"/>
<fmt:param value="${fn:escapeXml(bundle['namespaced.markup'])}"/>
<!-- probably wrong, double escaping -->
</fmt:message>
</c:out>

This can save us from exporting strLastModified.

But, how do you specify null in EL ?
After reading specs again I have found
NullLiteral ::= 'null'

Look at MS ideas here:

http://weblogs.asp.net/scottgu/archive/2010/04/06/new-lt-gt-syntax-for-html-encoding-output-in-asp-net-4-and-asp-net-mvc-2.aspx

Thursday, July 29, 2010

<c:url> DANGER !


<c:url value="/foobar.jspx#fragment">
<c:param name="p1" value="v1" />
<c:param name="p2" value="v2" />
</c:url>

fragment is not recognized as fragment and taken as part of path:

/BasicConcepts/foobar.jspx#fragment?p1=v1&p2=v2


JSTL Specification 7.5 for c:url
reffers to old
JSP 1.2 in JSP.2.2.1 "Relative URL Specification"
which refers to old RFC
Elements may use relative URL specifications, called “URI paths” in the Servlet
2.3 specification. These paths are as described in the RFC 2396 specification.
So it becomes very unclear
if the value can contain fragments and/or query.

I vote for YES it can, even if the JSTL would want to advocate NO,
as I developer I would request it.

Tested on Suns jstl-impl-1.2.jar, Tomcat 6.0,
and after decompilation and quick look in the code,
I have strong suggestion

DO NOT USE !!!!!
it is dangerous and combined with lax EL, it can lead to
serious "security troubles" (search CWE, OWASP or others).

I will post fixed reliable version of
ainthek:url when ported from my other libraries.
And it will use IRI (I have not found anything better so far).
http://jena.sourceforge.net/iri/