Trim White Space from JSP

Untitled | FlickrSometimes the resultant HTML from JSP files has too much white space.  This is because a lot of JSP logic will result in only a few lines of actual HTML code and the rest is white space.

One efficient way to get rid of white space is to add this configuration to your web.xml on Tomcat/JBoss as described in this article, Trim Spaces in your JSP’s HTML.

/jboss/jboss-eap-4.2/jboss-as/server/atg/deploy/jboss-web.deployer/conf/web.xml
OR
/jboss/jboss-eap-5.1/jboss-as/server/atg/deployers/jbossweb.deployer/web.xml

<servlet>
    <servlet-name>jsp</servlet-name>
    ...

    <init-param>
        <param-name>trimSpaces</param-name>
        <param-value>true</param-value>
    </init-param>

    ...
</servlet>


However this sometimes has undesired side-effects. For example this DSP:

<div class="foo">
  <dspel:valueof param="displayName" />
</div>


causes this undesired result:

<div class="foo"/>
  Frank Kim


The work around is to do this.

<dspel:getvalueof  var="displayName" param="displayName" />
<div  class="foo"><c:out  value="${displayName}"/></div>

Update 06-09-2010: The above problem might have been happening because we were running with a version of ATG that is for Servlet 2.3. When we run with a version of JBoss that runs with Servlet 2.4, e.g.  ATG 9.1 with JBoss EAP 4.2, we no longer see this problem.

There is another tip on removing white space in this JSP FAQ: Why I am getting extra whitespace in the output of my JSP?  In our code we had one file which included a bunch of tag libraries.  It originally looked like this.

<%/** Taglibs.jsp: include to pull in all taglibs */%>

<%@ taglib uri="/dspELTaglib" prefix="dspel" %>
<%@ taglib uri="/jstlCoreTaglib" prefix="c" %>
<%@ taglib uri="/struts-bean" prefix="bean" %>
<%@ taglib uri="/struts-tiles" prefix="tiles" %


When we changed it to this we saved about 5% in terms of page size in bytes.

<%@ taglib uri="/dspELTaglib" prefix="dspel"
%><%@ taglib uri="/jstlCoreTaglib" prefix="c"
%><%@ taglib uri="/struts-bean" prefix="bean"
%><%@ taglib uri="/struts-tiles" prefix="tiles" %>


You can use this tip with a DSP page and maintain indentation.

<dspel:page    ><dspel:droplet name="/betweengo/droplet/Foo"      ><dspel:oparam name="output"        >Name: <dspel:valueof param="name"      /></dspel:oparam    ></dspel:droplet
></dspel:page>

Mysterious dspel:include problem with flush=true

When I use dspel:include within a custom tag like below things work fine.

<betweengo:link href="/click.do?id=foo"><dspel:include
page="/include/bar.jsp"/></betweengo:link>

However when I add flush=”true” it fails silently.

<betweengo:link href="/click.do?id=foo"><dspel:include
page="/include/bar.jsp" flush="true"/></betweengo:link>

The JSP page no longer renders after it gets to this line of code.  What puzzles me even more is that the documentation says that if you do not explicitly set flush, flush happens automatically.  Therefore theoretically adding flush=”true” should not have an effect though I do it because the documentation recommends doing it.

The above code is happening within a TargetingForEach droplet.  It is running on an ATG 2006.3 Patch 2 app server with JBoss 4.0.4.GA.

I contacted ATG support about this issue and they responded very quickly.  Basically they said don’t use flush=”true” on third party application servers and just rely on the automatic flush.

Entered on 07/29/2008 at 13:12:19 by Nicholas Glover:
Hi Frank,

You should note that JBoss 4.0.4 GA is not supported with any version of ATG and you should not be using it. Please stick with JBoss 4.0.3 SP1.

Also, it is imperative that you upgrade from your ATG version to the latest 2006.3 patch, patch 6. The latest patch has many bugfixes include a fix for one relating to flushing behavior, PR #134387.

Due to various bugs and issues encountered, use of the “flush” attribute with a 3rd party app server, is not really recommended. We are removing all docs for this feature in later versions of our documentation. In this case, flush=true is forcing an explicit flush on the current page; but if this is not set, a more “intelligent” auto flush is done that flushes top-level pages first and then progresses down the tree. This prevents problems with 3rd party app servers such as content getting rendered out of order. I recommend not messing with the “flush” setting.

Is there something you are trying to do that is not working that leads you to want to use the “flush” attribute?

Thanks.


Nick Glover
ATG Support

Entered on 07/29/2008 at 15:02:57 by Nicholas Glover:
Hi Frank,

I had already entered the documentation bug about this previously, but I polished and published it for our site with what I learned when looking into this for a prior customer and when looking into it for you.

It is PR #146637. Here’s the link:
http://www.atg.com/esupport/bugs/index.jsp?FullViewBug=ViewBug&bugId=146637

I’ll close this case now.

Thanks.


Nick Glover
ATG Support

TargetingRange ignoring start param

We were using the TargetingRange droplet to display a number of slides, starting with the 2nd slide.  We would never show more than 9 slides so we set howMany to 9.

What we found was that the TargetingRange droplet was always returning all the slides, including the first slide, no matter what we set for start.

Fortunately ATG support identified this problem as Bug #84551.  If the howMany param > number of targets returned then it ignores the start position parameter.

The work around is to make sure to set the howMany parameter to the number of items you expect.

Jumping to different parts of a page using a dropdown

It is relatively simple to dynamically create a dropdown from which you can jump to different parts of a page using JavaScript and ATG DSPEL.

First create the dropdown.

<form name="jumpTo" action=".">
  <dspel:droplet name="/atg/dynamo/droplet/ForEach">
    <dspel:param name="array" param="categories"/>
    <dspel:setvalue param="category" paramvalue="element"/>
    <dspel:oparam name="outputStart">
      <select name="names">
    </dspel:oparam>
    <dspel:oparam name="output">
      <dspel:getvalueof id="index" param="index"/>
      <c:set var="catShortName" value="cat${index}"/>
      <option value="<c:out value="${catShortName}"/>">
        <dspel:valueof param="category.name"/>
      </option>
    </dspel:oparam>
    <dspel:oparam name="outputEnd">
      </select>
    </dspel:oparam>
  </dspel:droplet>
</form>

Next create the button outside of the form for jumping to different parts of the page. I learned about the window.location.hash from this article. And I learned about how to access the selected value from the dropdown from this article.

 <input type="image" src="/img/buttons/update.gif"
   onClick="window.location.hash=
document.jumpTo.names.options[document.jumpTo.names.selectedIndex].value">

Finally you create the name anchors throughout your document.

<dspel:droplet name="/atg/dynamo/droplet/ForEach">
  <dspel:param name="array" param="categories"/>
  <dspel:setvalue param="category" paramvalue="element"/>
  <dspel:oparam name="output">

    <%-- magazine category --%>
    <dspel:getvalueof id="index" param="index"/>
    <c:set var="catShortName" value="cat${index}"/>
    <a name="<c:out value="${catShortName}"/>"
       id="<c:out value="${catShortName}"/>">
      <dspel:valueof param="category.name"/>
    </a>

  </dspel:oparam>
</dspel:droplet>

Droplet Name Case Sensitivity

In one of our JSP files we included a droplet like this:

<dspel:droplet name="/betweengo/droplet/foo">

However the actual properties file is named Foo.properties. On Windows this was not an issue because Windows file system is case insensitive but when we moved to UNIX we saw this exception:

javax.servlet.jsp.JspException:  CANT_FIND_DROPLET: Unable to find the droplet with name  "/betweengo/droplet/foo"

This is not surprising since UNIX’s file system is case sensitive. Once we corrected the capitalization ATG was able to locate the droplet.

Sorting Nested Properties

ATG’s looping droplet have the nice ability of sorting nested properties. For example say you have a repository item Person and it has a property address which is a repository item Address and you want to sort on the address’s street. Then you can do something like this.

<dspel :param name="sortProperties" value="+address.street"/>

ATG does this through the magic of DynamicBeans.

Size of collection in a JSP/DSP page

leaf pile on Flickr

(Photo: leaf pile by oeimah)

Sometimes in a JSP/DSP page you will want to get the size of a collection and unless you are within a Range, ForEach or similar droplet you won’t have access to this value.

Struts has a nice solution using the bean:size tag.  JSTL 1.1 has a nice solution using the fn:length function.

Here is an example of how to use Struts, DSPEL and JSTL to get the size of a collection.

  <dspel:getvalueof param="book.pages" var="pages"
                    vartype="java.util.Collection"/>
  <bean:size id="numPages" name="pages"/>
  Number of Pages: <c:out value="${numPages}"/>
  Number of Pages: <dspel:valueof value="${numPages}"/>

Here is an example of how to use JSTL 1.1 and DSPEL to get the size of a collection.

 

  <dspel:getvalueof param="book.pages" var="pages"
                    vartype="java.util.Collection"/>
  Number of Pages: <c:out value="${fn:length(pages)}"/>

Accessing RepositoryItems with JSTL

Often we are accessing repository items in a JSP page like this.

  <dspel:droplet name="RQLQueryForEach" var="query">
    <dspel:param name="repository" bean="/betweengo/repository/Repository"/>
    <dspel:param name="itemDescriptor" value="Account"/>
    <dspel:param name="queryRQL" value="ALL"/>
    <dspel:setvalue param="account" paramvalue="element"/>
    <dspel:oparam name="output">
      <dspel:valueof param="account.name"/><br/>
    </dspel:oparam>
  </dspel:droplet>

With JSTL we could try to display the name like this.

      <c:out value="${query.account.name}"/>

If you are using JSP 2.0 you can display it even more simply.

      ${query.account.name}

However since account is a RepositoryItem object and there is no get method for the name property (i.e. it’s not a JavaBean object) the above will fail and produce an exception.

To get around this you can extend ATG’s RQLQueryForEach class by overriding the protected setElementParameter. In addition to setting the element parameter in the request you can set a new parameter which we will call “item”. This item is of class atg.beans.DynamicBeanMap and wraps a RepositoryItem.

public class RQLQueryForEachEL extends RQLQueryForEach {
  protected void setElementParameter(DynamoHttpServletRequest pRequest,
                                     String pElementName, Object pValue) {
    super.setElementParameter(pRequest, pElementName, pValue);
    DynamicBeanMap itemBean = new DynamicBeanMap(pValue, true);
    pRequest.setParameter("item", itemBean);
  }
}

Now we can access the repository item with JSTL like this.

      ${query.item.name}

Comparison of DSP and DSPEL

ATG has two JSP tag libraries, DSP and DSPEL. Both have similar syntax but DSPEL allows you to use JSTL.

Here’s a simple comparison of how you would use DSP versue how you would use DSPEL to do a simple RQL query.

DSPEL

<dspel:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dspel:param name="repository" bean="/betweengo/Repository"/>
  <dspel:param name="itemDescriptor" value="Merchant"/>
  <dspel:param name="queryRQL"
    value="name EQUALS \"${requestScope['nm']}\""/>
  <dspel:oparam name="empty">
    No merchant with the name "<c:out value="${requestScope['nm']}"/>".
  </dspel:oparam>
  <dspel:oparam name="output">
    Name: <dspel:valueof param="element.name"/>
  </dspel:oparam>
</dspel:droplet>

DSP

<% String query = "name EQUALS \"" + request.getAttribute("nm") + "\"";%>

<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="repository" bean="/betweengo/Repository"/>
  <dsp:param name="itemDescriptor" value="Merchant"/>
  <dsp:param name="queryRQL" value="<%= query %>"/>
  <dsp:oparam name="empty">
    No merchant with the name "<%= request.getAttribute("nm") %>".
  </dsp:oparam>
  <dsp:oparam name="output">
    Name: <dsp:valueof param="element.name"/>
  </dsp:oparam>
</dsp:droplet>