Showing posts with label Servlet/JSP. Show all posts
Showing posts with label Servlet/JSP. Show all posts

Wednesday, August 25, 2010

request.getRequestDispatcher vs servletContext.getRequestDispatcher

ServletRequest.getRequestDispatcher(String path)

The pathname specified may be relative,
although it cannot extend outside the current servlet context.
If the path begins with a "/" it is interpreted as relative to the current context root.
...
If it is relative, it must be relative against the current servlet

ServletContext.getRequestDispatcher(String path)

The pathname must begin with a "/" and
is interpreted as relative to the current context root.
Use getContext to obtain a RequestDispatcher
for resources in foreign contexts.

Basic difference is that

request.getRequestDispatcher allows for relative paths.
Relative to what ?

relative path as coincidence

If the servlet (let's call him B) is accessible using only one URI (/ctx/B)
that seems to be easy answer.
Event if mapped with with url-pattern /path/B,
most containers are "trailing slash ignorant" and your servlet will be accessible with
both /ctx/path/B and /ctx/path/B/ variants.
With the same code in servlet:
request.getRequestDispatcher("../c.jspx").include(request, response);
you will get two different results of course,
/ctx/c.jsp and /ctx/path/c.jspx
one of them will end up with null pointer of course.


Usually using realtive path is coincidence and not design decision.


relative path as design

But wait "relative path" can be used as intentional design:

Imagine that the same servlet is accessible using

/a/a/a
/a/b
/f/g/h/ mappings

and based on the requested uri you want to include different view (c.jspx).
If the view exists in the relative location use it, otherwise use predefined global view.


// get view on current level
d=request.getRequestDispatcher("./c.jspx");
if(d==null)
{
d=request.getRequestDispatcher("/c.jspx");
}
d.include();


Reative Path - Double dispatch

what if b is already dispathed.
If the call goes througn A to B and the to C.
What "it must be relative against the current servlet" means ?
(test your self on several containers, reading specs is not enough for this case ;-))


My suggestion


PREFERE:
getServletContext().getRequestDispatcher() and /contextRelativePath

OVER:
request.getRequestDispatcher and relativePath

Otherwise you code may
not be movable up and down in web hierarchy withou moving views,
not work when mapped to different level URIs" without duplicating views,
and probably will suffer from container's trailing slash ignoracy.

Use realtivePaths only "as design not as coincidence",
and always document relative path dependencies in your servlet documentation.

Wednesday, August 11, 2010

Expression Language, Conditional Operator , WebLogic Tomcat incompatibility problem

Web logic server requires extra whitespaces in this situation:

<td>${fn:escapeXml(r.queryString==null?'null':r.queryString)}</td>


Apache Tomcat/6.0.28 - works fine
WebLogic Server 10.3.3.0 fails with


weblogic.servlet.jsp.CompilationException: Failed to compile JSP /RequestUrl.jspx
RequestUrl.jspx:44:50: Syntax error in expression. Encountered ":r". Expected one of ...


WLS requires extra space after :

<td>${fn:escapeXml(r.queryString==null?'null': r.queryString)}</td>

//TODO: check grammar in specs .... please
//JSP.2.3.8 Conditional Operator - A ? B : C
//and find out who is right or wrong.

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

OL snipped (valid HTML from your JSP components, PLEASE !)

many component authors are lazy to read HTML specification,
and lazy to write extra if in the code as well.
One of the examples is title tag absence in code generated by
myfaces components (see older posts).
Proposal for correct list rendering:

<c:if test="${!empty files}">
<ol>

<c:forEach var="file" items="${files}">
<li><c:out value="${file.name}"/></li>
</c:forEach>
</ol>
</c:if>

The point is that OL without child LI is nonsence from HTML point of view.
Later we will talk about what element
to generate instead for empty list
and if null and empty is the same (EL does not care of course).

Wednesday, July 28, 2010

Fix For WST (Web Standard Toolkit) template

This is just sick ;-)

<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page language="java"
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" />

<jsp:text>
<![CDATA[ <?xml version="1.0" encoding="UTF-8" ?> ]]>
</jsp:text>

<jsp:text>
<![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
</jsp:text>


<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>

</body>
</html>
</jsp:root>


My proposed version is:

<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page language="java"
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" />
<jsp:output omit-xml-declaration="no" doctype-root-element="html"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>

</body>
</html>
</jsp:root>

Do you think ther is a reason or just ignorance ?
Fist original WST code is buggy, outputed "XHTML" will have whitespaces before ?xml and whitespaces before doctype. (Authors, please read at least JSP.1.3.8 White Space) if not XML and HTML specs ;-))

Monday, December 7, 2009

Prove Me Wrong, please - First line of HTTP request

There is no reliable way to retrieve EXACT form of URI specified in the first line of HTTP request.
This applies to Servlet API (need for Cross-Container solution working at Tomcat, WebSphere 6.0.2,6.1,7.x , and others), as well as to ASP.NET Runtime (2+) on IIS 5.1 (and maybe others not tested) with standard modules in action.


Sniff:
GET /UriHandler.aspx/[%5d HTTP/1.1

Exected result:
/UriHandler.aspx/[%5d


Mission: tell me THE MAGIC API to achieve this.

Also wanted: description and comparative tables describing IIS and ASP.NET URL normalization with IIS 5,6,7, with/without URLScan and other URL related HTTP.sys and other settings. I mean complete IIS URL handling stack for all IIS versions ;-)