David Sills's muse is fueled by Bach, Beethoven, and Brahms (and Berlioz and Boulez). He has no life, which comports well with the über-geekitude to which he aspires. He reads and writes fitfully in English, Spanish, French, German, Italian (mostly medieval), C, VB, Perl.... Oh, and Java and XSLT, lots and lots of Java and XSLT. Trained somewhere in darkest Central America, he works today at DataSource, Inc., on the product team for the CASE tool Abri. David has posted 9 posts at DZone. View Full User Profile

Running the Table With JMesa

06.18.2008
| 44224 views |
  • submit to reddit

Shhhh. I’ll tell you a secret. I don’t like tables.

I know. Shocking, isn't it?

Don't get me wrong: I don't dislike tables per se. They're great for displaying tabular material. (For page organization, not so much.) But I so dislike the code needed to build a table within a JSP. It usually comes down to something like this:

<c:forEach items="rows" var="row" varStatus="status" begin="${begin}"
end="${end}" step="${step}">
<c:if test="${status.first}">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<th>User ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</c:if>
<c:choose>
<c:when test="${status.count % 2 == 0}">
<tr class="even">
</c:when>
<c:otherwise>
<tr class="odd">
</c:otherwise>
</c:choose>
<td>${row.userID}</td>
<td>${row.name}</td>
<td>${row.email}</td>
</tr>
<c:if test="${status.last}">
</table>
</c:if>
</c:forEach>

All that iterative logic simply looks incomprehensible to me. It's still better than scriptlets or custom tag libraries (both of which were, to be sure, phenomenal in their time), but it's an undigestible mass, and even if I do step through it line by line and understand what it does, I'm still left with just a table. Users accustomed to active, Javascript-assisted widgets don't respond to tables that just lie there. Many more lines of code will be needed to enable them to do useful things like paginating through long lists of items, sorting by column values, and the like. It'll be an unholy mix of HTML, JSP directives, JSP tags, EL, Javascript, Java, XML, properties files, and so forth. The whole thing seems so error-prone (note to self: more code + more languages = more "opportunities" for bugs).

But recently I discovered an open-source Java library called JMesa that provides another way. I'm going to share with you some of the things I've found in JMesa, building up an HTML page containing a table from nothing to, well, considerably more than nothing.

There's a good deal of code here, to give you a sense of the JMesa API; hopefully. you'll come away with some ideas about how you can use JMesa in your own projects. I won't bother with package declarations, imports, or code not relevant to the point at hand; the complete code is available for download in the form of an Eclipse project. Installation instructions will be found at the end of this article.

Join me in exploring JMesa!

Preparation

A Page to Show

Before we can get to JMesa, though, we'll need a few things: a page within which to display our table, for instance. In fact, we'll learn even more if we put this page in a context. I have recently fallen in like with Spring MVC and so will use that to build a simple site with a few pages. Just to be clear, while Spring dependency injection and utilities are woven into the code below, JMesa does not depend upon Spring. The pages are not fancy, and I am going to skip most of the setup. Everything is included in the download, of course.

One thing I shouldn't skip is the controller for the search results page, the page within which we will build our table. We'll start with pretty much the simplest functionality we can:

public class SimpleSearchController extends AbstractController
{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest
request, HttpServletResponse response) throws Exception
{
return new ModelAndView("simple-results", "results",
"Here we will display search results");
}
}

For those not familiar with Spring MVC, the ModelAndView return value contains a string that will be resolved to a view (in this project, it is resolved to "/WEB-INF/jsp/simple-results.jsp"), and a key-value pair (the second and third constructor arguments) that can be accessed using EL on the JSP page:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<tags:layout-top>
<jsp:attribute name="titleBar"><spring:message
code="title.bar.results"/></jsp:attribute>
<jsp:attribute name="titleInternal"><spring:message
code="internal.title.results"/></jsp:attribute>
</tags:layout-top>
${results}
<tags:layout-bottom/>

Finally, we use the Spring jmesa-servlet.xml configuration file to create and associate a URL with our controller:

<bean id="simpleSearchController"
class="com.javalobby.article.jmesa.web.SimpleSearchController"/>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.html">welcomeController</prop>
<prop key="/search.html">simpleSearchController</prop>
</props>
</property>
</bean>

Clicking on the "Search" link in the menu now produces:

Figure 1.: A simple page for our tableFigure 1.: A simple page for our table



All right, not much. But it's the page we need.

Something to Display

Another thing we need before we can build a table is something to show in it. This "domain" object should be pretty easy to display:

public class HelloWorld implements Comparable<HelloWorld>
{
private int pk;
private String hello = "Hello";
private String world = "world";
private String from = "from";
private String firstName;
private String lastName;
private String format = "{0}, {1}! {2} {3} {4}";

// ... accessors and mutators

public String toString()
{
return MessageFormat.format(getFormat(), hello, world,
from, getFirstName(), getLastName());
}

// ... implementations of equals, hashCode, and compareTo
}
 

Persistence Service

Of course, we need instances of this domain object. Normally, we'd get them from a persistence service; for now, we'll just create them in memory:

public class HelloWorldService
{
private int nextId;
private Set<HelloWorld> helloWorlds = new TreeSet<HelloWorld>();

public HelloWorldService()
{
nextId = 1;
helloWorlds.add(newInstance("Albert", "Einstein"));
helloWorlds.add(newInstance("Grazia", "Deledda"));
helloWorlds.add(newInstance("Francis", "Crick"));
helloWorlds.add(newInstance("Linus", "Pauling"));
helloWorlds.add(newInstance("Theodore", "Roosevelt"));
helloWorlds.add(newInstance("Hideki", "Yukawa"));
helloWorlds.add(newInstance("Harold", "Urey"));
helloWorlds.add(newInstance("Barbara", "McClintock"));
helloWorlds.add(newInstance("Hermann", "Hesse"));
helloWorlds.add(newInstance("Mikhail", "Gorbachev"));
helloWorlds.add(newInstance("Amartya", "Sen"));
helloWorlds.add(newInstance("Albert", "Gore"));
helloWorlds.add(newInstance("Amnesty", "International"));
helloWorlds.add(newInstance("Daniel", "Bovet"));
helloWorlds.add(newInstance("William", "Faulkner"));
helloWorlds.add(newInstance("Otto", "Diels"));
helloWorlds.add(newInstance("Marie", "Curie"));
}

public Set<HelloWorld> findAll()
{
return helloWorlds;
}

private HelloWorld newInstance(String firstName, String lastName)
{
HelloWorld hw = new HelloWorld();
hw.setPk(nextId++);
hw.setFirstName(firstName);
hw.setLastName(lastName);
return hw;
}
}


That's that. Now we're ready to focus on JMesa.

Legacy
Article Resources: 
Published at DZone with permission of its author, David Sills.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Nicolas Frankel replied on Wed, 2008/06/18 - 10:19am

Hello,

Don't get me wrong, but displaying tabular data in HTML is done since a loooooong time with the DisplayTaglib. There's a short article on my blog if you're interested. They use taglibs but I see it as an advantage.

For more informations, see their site or their live demos which are really bluffing when you see the tiny amount of config needed on the JSP.

Cheers.

Nicolas

 

 

Benoit Guerout replied on Wed, 2008/06/18 - 10:53am

I've a very bad recollection of the last time I've tried to create a table JMesa (old but wonderfull displaytag solved easly the problem).

But, may be, this tutorial will help me to succeed the next time i'll try JMesa.

Jeff Johnston replied on Wed, 2008/06/18 - 7:19pm

What a great article...I was very excited to read this today :)! It was very well thought out and complete. You really tapped into just how customizable JMesa is. By design, just about every aspect of JMesa can be tweaked and modified with very little code. I will for sure link to this article from the home page of JMesa and reference it in the tutorials!

I am going to see about implementing your extended attributes notion. I think that is a nice improvement! I also hope to make some adapters for Spring so that those that choose to use the Spring framework can tie into Spring's notion of messages and preferences. It wouldn't be hard to do and would be a completely optional runtime dependency so non-Spring developers would not be effected.

Nicolas, there is a complete tag library with JMesa. The tag library is just a thin wrapper around the API. In addition JMesa has first class Groovy support and, in the next release, will even have Grails support with GSP Tags. The latter is currently being built by a member of the JMesa community and I am very excited to see that work as well. I have seen other work by this developer and it is always top notch. Also, as the article mentions, JMesa can also be put in an editable mode and will track your changes automatically.

bguerout, sorry to hear your first go around wasn't so great. How long ago was that? Based on how few questions I get nowadays I can say with confidence that your next experience should be really good. It is a very solid API! If you have any problems either post on the groups or email me directly. I try to get back ASAP as I know how frustrating it is to wait for replies when there are questions.

I wanted to mention that JMesa was designed to be an API first and foremost. It also embraces the Model 2 environment. Both of these give it the advantage of being able to use JMesa with just about any framework and regardless of the view technology being used.

David, if you don't mind, I also wanted to mention a few subtle improvements to your example that may make things easier:

  • You can actually turn off filtering at the row level by setting filterable to false. This will cause the filter row to not be rendered and the filter toolbar items to not display.
  • You might want to consider extending AbstractCellEditor as that will give you access to the Column, as well as the CoreContext and WebContext.
  • You do not need to inject your CellEditor with the CoreContext or WebContext. The support interfaces are there so the API can do that automatically for you when you set the editor on the renderer.
  • You can also define bogus column names instead of null for the column properties that do not map to a bean attribute. That enables you to reference the columns by name instead of position. It seems I usually have columns like "chkbox" myself that do not actually map to bean properties.

Once again, congratulations on a great article!

-Jeff Johnston

 

David Sills replied on Sun, 2008/06/22 - 1:59am in response to: Nicolas Frankel

Nicolas:

Thanks for your comment and thanks for reading.

It was, in fact, using Display Taglib for a while that got me to looking around for something easier to customize and with a few more features. I agree completely that if it meets your needs, it's a terrific library. It simply didn't meet mine.

That said, chacun à son goût, as the French say. The beauty of the Java world today is that we have enough open-source code around that everyone can use whatever they feel comfortable with.

Cheers,

David Sills

David Sills replied on Sun, 2008/06/22 - 2:01am in response to: Jeff Johnston

Jeff:

Thanks to you for authoring JMesa! Without it, of course, the article would have been, shall we say, less interesting?

I have incorporated some of your comments into the code and resources. I would be pleased if you wanted to link to the article.

All the best! 

David Sills

Neil Juan replied on Fri, 2008/08/22 - 9:07pm

I guess were on same track, I'm using JMesa for quite a while, in my swf application. If I do have problems, could I ask for help?

David Sills replied on Sat, 2008/08/23 - 1:23pm in response to: Neil Juan

Sure, but your best bet is the Google JMesa group: http://groups.google.com/group/jmesa/topics. Jeff Johnston (the creator of JMesa) moderates, and is extremely friendly and helpful.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.