Thursday, December 23, 2010

Spring MVC ModelAttribute and BindingResult

The Problem:

I am using Spring 3 MVC and I encountered the following error upon form submission:

org.springframework.validation.BindException type mismatch

In my controller I defined the following 2 model attributes:

        model.addAttribute("gene",gene);        
        model.addAttribute("renameAllele", ra);

Upon form submission, I wanted to bind the ModelAttribute to my method arguments as follows:

    @RequestMapping(value="/renameAllele/submit", method=RequestMethod.POST)
    public String submit(@ModelAttribute("renameAllele") @Valid final RenameAllele ra, BindingResult alleleBindingResult, 
            @ModelAttribute("gene") RenameGene gene, SessionStatus status ) {

This method signature didn't work because for every ModelAttribute added, we need to have a corresponding BindingResult argument as well. As you can see above, the ModelAttribute("gene") did not have a corresponding BindingResult.

Solution

To get it working, I changed the method signature as follows:

    @RequestMapping(value="/renameAllele/submit", method=RequestMethod.POST)
    public String submit(@ModelAttribute("renameAllele") @Valid final RenameAllele ra, BindingResult alleleBindingResult, 
            @ModelAttribute("gene") RenameGene gene, BindingResult geneBindingResult, 
            SessionStatus status ) {

I figured this out by reading the spring reference documentation. Here is a quote taken from their site:
"The Errors or BindingResult parameters have to follow the model object that is being bound immediately as the method signature might have more that one model object and Spring will create a separate BindingResult instance for each of them so the following sample won't work:"
Reference: http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html

Tuesday, December 21, 2010

styling tables made easy with DataTables jQuery plugin

In the past I've usually formatted results into a table using 'zebra' styling where each alternating row would be shaded with a different background color. Below is an example:




Typically the JSP would look as follows:


<table cellspacing="0" class="tracker-summaries">
    <tr>
        <th>Procedure</th>
        <th class="right-col">Version</th>
        <th class="right-col">Date added</th>
        <th class="right-col">Filename</th>
        <th class="right-col">&nbsp;</th>
    </tr>
    
    <c:set var="rownum" value="0" />    
<c:forEach items="${procedures}" var="procedure" >
                
        <c:set var="rownum" value="${rownum + 1}" />
        <tr <c:if test="${rownum mod 2 == 1 }">class="odd"</c:if>>
            
            <td>${procedure.type.value }</td>
            <td class="right-col">${procedure.version }</td>
            <td class="right-col">
                <c:if test="${not empty procedure.dateCreated}">
                    <fmt:formatDate pattern="dd/MM/yyyy" value="${procedure.dateCreated}" />
                </c:if>
            </td>    
            <td class="right-col">                
                ${ procedure.filename }
            </td>
            <td class="right-col">
                <a href='<c:url value="/inventory/inventoryDocDownload.html" />?<%= ParamNames.TYPE %>=<%=InventoryDocDownloadController.TYPE_PROCEDURE%>&id=${procedure.id}'>Download</a>
            </td>
        </tr>    
            </c:forEach>

</table>

As highlighted in red, I would manually assign each alternating row a different style to achieve the 'zebra' look and feel. This worked fine, but it became quite repetitive when you have multiple pages listing results in tables.

I recently, discovered a much better solution without having to customize each JSP that contained tabular results, using a jQuery plugin called DataTables

It's really quite simple. You create your tables without any styling attached. Then invoke a few lines of jQuery code to apply styling dynamically as follows:


    <script type="text/javascript">

        $(document).ready(function() {
            oTable = $('table.display').dataTable({
                "bJQueryUI": true,
                "bPaginate": false,
                "bLengthChange" : false,
                "bFilter" : false                            
            });

            $(".ui-toolbar:first").css('display','none');            
        } );        
    
    </script>

If you can apply this to every header to of your page, then all your pages will automatically have their tables properly formatted.

Furthermore, your tables will automatically have sorting, searching and pagination built-in.

Monday, December 20, 2010

SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

In Tomcat I had a stale version of context.xml under the following folder

/conf/Catalina

By deleting this cached folder the error was resolved

Spring 3 jndi-lookup and Tomcat

In your spring configuration you may have something like:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/>

Then in your webapp /META-INF/context.xml file you should have something similar too:

<?xml version='1.0' encoding='utf-8'?>

<!-- antiResourceLocking="true" -->
<Context path="/podd-apn"
         reloadable="true"
         cachingAllowed="false"
         antiResourceLocking="true"
         >


  <Resource name="jdbc/facs"              
            type="javax.sql.DataSource" username="${database.username}" password="${database.password}"
            driverClassName="org.postgresql.Driver" 
            url="${database.url}"
            maxActive="8" maxIdle="4"
            global="jdbc/facs" 
            />


</Context>


And in your web.xml you should something like:

  <!-- JNDI -->
  <resource-ref>
    <description>FACs Datasource</description>
    <res-ref-name>jdbc/facs</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>