http://www.developer.com/

Back to article

Extend Your Java Studio Creator Options with JSTL


May 4, 2005

This article covers the use of JSTL within Creator: How to set it up and make use of the JSTL, and how to deploy a JSTL-enabled Web app to Sun App Server PE 8 or another App Server.

What is the JSTL?

The JSP Standard Template Library (JSTL for short) is a tag library for creating dynamic JSP Web pages. It defines a number of useful tags that allow conditionals, iterations, and other common operations on data. If you are familiar with struts, you will notice a lot of similarities within the JSTL to the struts bean and logic tags in particular.

Why use the JSTL in Creator?

Clearly within Java Studio Creator, the emphasis is on component controls and data binding. This allows you to put data-bound pages together very quickly. It is very successful; however, data binding does limit you in some ways. For example, when binding a data grid, you need to know the number of columns ahead of time and provide header information for them. Now, suppose that you have data that you want to display in a grid for a time period that you do not know ahead of time, or maybe you simply have a very large number of columns to display and don't want to create large numbers of pre-defined column details for a grid.

JSTL allows you to build up an HTML table completely dynamically. By nesting a couple of iterations inside one another, you can make an HTML table to display data of variable dimensions in both X and Y axes. This will form the example that you examine in this article. There are numerous other reasons I can think of to use JSTL in Creator (conditionals on what to display, and so forth), but there are also a lot of reasons that I cannot think of but that you will probably hit at some time or other. Either way, knowing you have a backup to the strict data-binding model only increases your options when creating dynamic Web apps in Creator.

About this Article

Unlike previous articles, I have chosen to make this one a descriptive one rather than a follow-along article. Full sources are available in the accompanying zip file: JSTLDemo.zip.

Getting Started

Using the Source View

JSTL has no GUI support in Creator. This means it is necessary to switch to the source view of the JSP page (use the tab at the bottom of the JSP window). It is possible to mix and match JSF and JSTL, and for the JSF parts of the page, you can use the GUI view and drag and drop. I recommend using a group panel to hold the JSTL code you are going to use because it makes an easy handle to move and lay out the JSTL part on the page in the GUI view.

Quick JSTL Primer

The JSTL is a JSP tag library; that is, after importing, it defines a set of new tags that can be used in a JSP page. The tags are typically imported into the JSP using the namespace c: so the tags look like this: <c:if>, <c:forEach>, <c:choose>, <c:out>, and so on.

This article is not intended to be a tutorial on JSTL. For that, I recommend the following links:

You may also notice that there are more namespaces included with JSTL than the c: namespace. For example, there is an x: namespace for XML operations, and a sql: namespace for SQL queries and manipulations of DBs. Although this article does not cover these other JSTL namespaces, the techniques used here can be employed to harness those in Creator in the same way.

About the Sample Project

The sample project accompanying this article is a simplification of a solution to a real-world problem I faced in the my latest project at NewEnergy Associates.

The requirements for the display of hourly schedule data went beyond what could be accomplished easily (or even at all) in the Creator Grid component. These included (in no particular order) 96 quarter-hourly interval values (I could have created a bound grid with over 100 columns in it, but I really didn't have the patience). Also, the data was not organized into a readily bindable grid, but rather into a fairly sophisticated set of nested beans. Finally, user requirements stated that a mismatched row should be highlighted in some way (colored to draw the user's attention).

From my knowledge of Struts in previous projects, it became apparent that an HTML table constructed using iterators over the nested data beans would be far easier than trying to force the model into a grid with over 100 columns.

For the accompanying example project used in this article, I reduced the number of interval values to 24 hourly intervals instead of 96 quarter-hourly ones. Also, some of the more arbitrary logic is ommitted for brevity. However, it shows the potential value of a JSTL solution in this case.

A JSTL Example

Setup Steps for the Example Project

Download the zip file referenced at the top of the article, unzip it, and then open it using Creator. Feel free to look around the project. The layout is simple. There is a package called jstldemo.bean with three classes in it.

The Schedule class is a simple Schedule bean that is used to hold some basic details about the Schedule (name, in party, out party, and the like) and also in and out time series with 24 hourly values in each time series.

TimeSeries is the object that holds the hourly values. It also holds a name for the time series and a status to show whether the time series is matched to its partner.

DataSetup is just a very simple class with static methods to set up some random demo data in the two data beans above.

This is only a demo data set. The structure of the beans made more sense when it was part of the larger system I was working on. Don't get too bogged down in the way this data is structured; it is sufficient to demonstrate the use of JSTL, which is the point of this article.

The clever stuff is all in Page1.jsp. Page1.java simply gets the demo data and puts it into a TreeMap in the page so that the JSTL in the jsp page can access it.

Once you have examined the project, run it to see the resulting grid. You will dig into how this was achieved below.

Using JSTL in a Creator Page

There are several steps necessary to use JSTL inside a Creator Page. First, the JSTL tags must be included in the page. You must do this from the source code view of the page, and also the JSTL tags can only be added and manipulated in the page source view.

It is also recommended to put a group panel in the page to hold the JSTL code. This makes it easier to lay out the page and move the JSTL part of the page around (this is a useful trick in Creator for handling any component or code that Creator cannot render in WYSIWYG mode).

Add Group Panel to hold the JSTL Grid

Creating a group panel to hold the JSTL code (a table in this case) means that it is easy to lay out the page around the otherwise invisible JSTL-generated part. It also lets you move around the container position on the page.

When the group is created, name it something sensible. Then, look in the code and you should see something like the following:

<h:panelGroup binding="#{Page1.jstlTablePanel}" id="jstlTablePanel"
              style="height: 444px; left: 24px; top: 36px;
              position: absolute; width: 720px"/>

To place JSTL code inside the panel, change it to look as follows:

<h:panelGroup binding="#{Page1.jstlTablePanel}" id="jstlTablePanel"
              style="height: 444px; left: 24px; top: 36px;
              position: absolute; width: 720px">

....Insert JSTL Code Here....
</h:panelGroup>
Add the JSTL Core include

To use JSTL on a Creator page, you have to include the JSTL core library in the jsp:root tag of the page. To do this, switch to the source view of the page, find the jsp:root tag at the top of the page, and just before the closing > add:

xmlns:c="http://java.sun.com/jstl/core"

This includes the JSTL tags using the namespace c; in other words, you can now use <c:if>, <c:forEach>, and so forth.

Add the JSTL Grid Code

For this article, I chose to implement a table for formatting grid data. To do this, a normal HTML table definition is interspersed with JSTL core tags to provide iterations over data items in a TreeMap using the <c:forEach> tag. Also some of the table headers are generated using another form of the <c:forEach> tag that works more like a traditional for loop (providing a begin and end value, and a loop index variable. Finally, I use a c:choose..c:when..c:otherwise tag combination to detect a status code indicating a mismatch, and change the color of the data values based on that status.

Table Header JSTL code

To create the table header, the code looks like this:

<table cellpadding="3" cellspacing="2">
   <thead>
      <tr>
         <th class="list-header" nowrap="nowrap" scope="col">
            Schedule
         </th>
         <th class="list-header" nowrap="nowrap" scope="col">
            Series
         </th>
         <th class="list-header" nowrap="nowrap" scope="col">
            From
         </th>
         <th class="list-header" nowrap="nowrap" scope="col">
            To
         </th>
         <c:forEach var="i" begin="1" end="24">
            <th class="list-header" nowrap="nowrap" scope="col">
               <c:out value="${i}"/>
            </th>
         </c:forEach>
         <th> </th>
         <th> </th>
      </tr>
   </thead>

Note the use of <c:forEach var="i" begin="1" end="24"> and <c:out value="${i}"/>, which are used to create the 24 numbered column headers in the table, instead of writing entries for all of them. Apart from that, this is a fairly standard HTML table header definition. The two empty <th></th> entries at the end provide some padding space for the scrollbar that may be needed when the table is displayed (see below).

Table Body JSTL code

The JSTL code for the table body is:

<tbody style="overflow: auto; max-height: 210px">
  <c:forEach items="${Page1.schedules}" var="scheduleMapEntry">
    <c:set var="schedule" value="${scheduleMapEntry.value}"/>
    <!-- first do the in schedule -->
    <tr class="list-row-odd">
      <td nowrap="nowrap">
        <c:out value="${scheduleMapEntry.key}"/>
      </td>
      <td nowrap="nowrap">
        <c:out value="${schedule.inTimeSeries.timeSeriesName}"/>
      </td>
      <td nowrap="nowrap">
        <c:out value="${schedule.fromParty}"/>
      </td>
      <td>
        <c:out value="${schedule.toParty}"/>
      </td>
      <c:forEach var="hourly"
                 items="${schedule.inTimeSeries.hourlyValues}">
        <td nowrap="nowrap">
          <c:out value="${hourly}"/>
        </td>
      </c:forEach>
    </tr>
    <tr class="list-row-even">
      <td nowrap="nowrap">
      </td>
      <td nowrap="nowrap">
      </td>
      <td nowrap="nowrap">
        <c:out value="${schedule.toParty}"/>
      </td>
      <td nowrap="nowrap">
        <c:out value="${schedule.fromParty}"/>
      </td>
      <c:forEach var="hourly"
                 items="${schedule.outTimeSeries.hourlyValues}">
        <td nowrap="nowrap">
          <c:choose>
            <c:when test="${schedule.outTimeSeries.status == 1}">
              <font color="green">
                <c:out value="${hourly}"/>
              </font>
            </c:when>
            <c:otherwise>
              <font color="red">
                <c:out value="${hourly}"/>
              </font>
            </c:otherwise>
          </c:choose>
        </td>
      </c:forEach>
    </tr>
  </c:forEach>
</tbody>
</table>

A few notes about this:

The style="overflow: auto; max-height: 210px" in the tbody definition means that the table body will have a maximum height of 210 pixels on screen, and when the table data can no longer be displayed in this area, a scrollbar will be automatically added (the overflow: auto part does this). This requires a modern browser such as Mozilla, Firefox, or IE 5.5+ to work correctly.

For each Schedule in the list of schedules iterated over by the <c:forEach items="${Page1.schedules}" var="scheduleMapEntry">, two rows are actually output. The first row is the "in" data, and the second is the "out" data. This also makes it easy to differentiate the rows by using CSS styles to color the row backgrounds differently (the effect is the striping you see when you run the project).

The <c:set var="schedule" value="${scheduleMapEntry.value}"/> sets a variable schedule with the value of the current schedule map item. This is a Schedule bean with two TimeSeries beans nested inside. Once the c:set> tag has been used, you can reference schedule directly within your JSTL EL expressions.

The hourly interval values are output using the:

<c:forEach var="hourly" items="${schedule.inTimeSeries.hourlyValues}">
    <td nowrap="nowrap">
        <c:out value="${hourly}"/>
    </td>
</c:forEach>

and the equivalent part for outTimeSeries. This iterates over the hourly data in the time series and outputs table cells for each value in turn.

Finally, the conditional:

<c:choose>
   <c:when test="${schedule.outTimeSeries.status == 1}">
      <font color="green">
      <c:out value="${hourly}"/>
      </font>
   </c:when>
   <c:otherwise>
      <font color="red">
      <c:out value="${hourly}"/>
      </font>
   </c:otherwise>
</c:choose>

is used to color the values to green if the time series is marked as matched, and to color them red if marked as mismatched.

Test the Example Page

Go ahead and run the sample project to see the JSTL grid in action. The project generates some random values to display in the grid. For the third schedule, a deliberate mismatch is generated to illustrate the conditional in action (the second row in the third schedule should be red rather than green indicating that there is a mismatch in the values).

Note also how the table body scrolls while leaving the table headers in place (this is a nice feature and one I have yet to accomplish using the Grid control provided by Creator).

Deploying a JSTL Enabled Web App

Deploy to Sun App Server PE 8

There are no special steps to deploy this project to the Sun App Server 8 PE. All JSTL libraries necessary to support this project are already provided.

Deploy to Another App Server (Tomcat)

Depending on the App Server you are deploying to, JSTL may not be available in the standard libraries included for that App Server, or it may include an earlier version of the JSTL libraries that is incompatible. For example, Tomcat needs the JSTL libraries to be added to the project that is deployed before it will work.

To include JSTL in the built project WAR file, proceed as follows:

  • Right-click on the Library References section in the project navigator, and select Create New Library Reference.
  • Set the library name to JSTL.
  • Click the add button on the class libraries tab.
  • Navigate to your Creator installation directory, and find the modules/autoload/ext directory.
  • Select both jstl.jar and standard.jar (CTRL-click to select multiple), then click open.
  • Back in the dialog, uncheck the design boxes for both jars, but ensure that the deploy boxes are still checked.
  • Click OK.

This has already been done in the accompanying demo project for this article. Note how, when you select the jars, Creator automatically fills in the {tools.home} path variable, which allows the project to work on other machines with different install locations.

Gotchas

JSTL Nesting Problems

Creator does nesting rule checking, and this is normally a help, but when using JSTL it prevents some common usages of JSTL conditionals nesting.

For example, when I was writing this code for my real project, I actually wanted to highlight the row by changing the background color, doing something like this:

<c:choose>
   <c:when test="${status == -1}">
      <tr bgcolor="red">
   </c:when>
   <c:otherwise>
      <tr bgcolor="green">
   </c:otherwise>
</c:choose>

... rest of table row code here ...
</tr>

Okay, so the default red and green colors for the background might be a bit garish, but the intent is clear, and this is a pattern I have used many times before with the struts tags. However, in practice this fails to compile in Creator because it sees that the nesting of the <tr> and <c:...> tags are messed up (it wants the </tr> paired to the <tr bgcolor>, instead it gets a </c:when> tag first).

This limits what you can do with JSTL inside of Creator at present; hopefully, this will be changed soon to allow more flexibility, but in the meantime you can probably find ways to code around these limitations. If you do find an easy way to color the rows in the manner I was trying above, please let me know and I will incorporate it into a future article (giving you full credit, of course).

Conclusion

Whereas the use of JSTL inside of Creator certainly has its warts, it can be a very useful tool to provide more capability than the Creator controls do on their own. In the past, I have included JavaScript-based tool-tips for rows and cells. Also, the capability of having a scrolling table body is pretty nice. (Note to the Creator guys: Can we have this in a future version of the grid control, please?)

If you have any questions or comments about this or the other articles I have written, please feel free to contact me; Developer.com provides a mechanism to do so.

About the Author

Dick Wall is a Lead Systems Engineer at NewEnergy Associates, a Siemens Company based in Atlanta, GA that provides energy IT and consulting solutions for decision support and energy operations.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date