Spring Roo: Customizing Web MVC UI Forms

There are many features that I like from Spring Roo:
  • The shell is very effective for constructing projects -with a helpful tab completion-
  • Round-trip is essential to keep the code in sync
  • Code generation without “unnecessary abstractions” is refreshing -although version 1.1.2 might bring some of them back- just to mention a few.
At the top of the list, I am placing, what I consider the jewel-of-the-crown: The Tagx library for JSP(x) views. The article assumes some familiarity with Spring Roo. For more information on Spring Roo visit its website at http://www.springsource.org/roo.

Tagx Library in a Nutshell

The tagx library is installed by the Web MVC add-on. Spring Roo scaffolds controllers and views from entities classes. Views are created with components from the tagx library. Please read reference document at http://static.springsource.org/spring-roo/reference/html/base-web.html for a complete description.

Without further ado. Straight to business.

This article refers to forms implemented in World Almanac by jD website. World Almanac is a member of a group of web apps created to experiment with Spring Roo development. The link of the showcases website is at https://pragmatikroo.org/showcases. The purpose is to implement typical web development requirements beyond the CRUD scope. This is the problem to work on: I need to customize a list.tagx component to render country flag images. Typically this component renders strings and numbers inside a grid. The form will be paginated for easy navigation, as shown in the image below. This functionality provides a World Almanac galleria view Additionally, I want to attach a click event for navigating to a country detail page. The form provides two select controls for enabling counties filtering. The form is paginated and navigated the same way a typical list.jspx form is. Typically Roo select buttons are associated with an action button. In this case, I remove them and the filtering action is triggered by a choice select. I didn’t have to start from scratch. I just tweaked Roo generated source code. Roo is great!.

Paginated Gallery Form

Below is the source code that renders the flag country gallery view. There is a lot of customization here. However you can still see the skeleton of the original scaffold form created by Roo. Paginated Gallery JSPx code
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <div xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:page="urn:jsptagdir:/WEB-INF/tags/form" xmlns:table="urn:jsptagdir:/WEB-INF/tags/form/fields" version="2.0" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:fn="http://java.sun.com/jsp/jstl/functions"> <script type="text/javascript"> <![CDATA[ function selectIt( aName ){ var selectContinentPage="/worldAlmanac/countrys"; document.body.innerHTML = '<form id="dynForm" action='+ selectContinentPage+ ' method="get">'+ '<input type="hidden" name="find" value="gallery" />'+ '<input type="hidden" name="\page" value="1" />'+ '<input type="hidden" name="\size" value="50" />'+ '<input type="hidden" name="'+aName.name+'" value="'+aName.value+'" />'+ '</form>'; document.getElementById("dynForm").submit(); } ]]> </script> <jsp:output omit-xml-declaration="yes" /> <div id="wrapperTop"> <input name="btnBack" title="Previous Page" onMouseOver="window.status='Previous Page'; return true" onMouseOut="window.status=''; return true" onclick="location.href = '/worldAlmanac'" type="button" value="Previous Page"/> </div> <page:list id="pl:org.josean.rooworld.domain.Country" items="${countrys}"> <div> <div style="float: left; width: 60%;"> <field:select disableFormBinding="true" id="f:org.josean.rooworld.domain.Country.continent" items="${continent}" field="continent" path="/countrys" onchange="selectIt(this);"/> </div> <div> <field:select disableFormBinding="true" id="f:org.josean.rooworld.domain.Country.region" items="${region}" field="region" path="/countrys" onchange="selectIt(this);" /> </div> </div> <table:gallery data="${countrys}" id="l:org.josean.rooworld.domain.Country" path="/countrys" title="Click on image to select country info" page="${page}" size="${size}" typeIdFieldName="code" pageid="page" sizeid="size" delete="false" update="false" create="false" select="false" show="false" anchorURL="/countrys?find=gallery"> <table:column id="c:org.josean.rooworld.domain.Country.code" type="img" >[/caption] <strong>Detailed Country JSPx code</strong> <!-- wp:code {"language": "html"} --><pre class="wp-block-code"><code></code></pre><!-- /wp:code --> <?xml version="1.0" encoding="UTF-8" standalone="no"?> <div xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:page="urn:jsptagdir:/WEB-INF/tags/form" version="2.0" xmlns:spring="http://www.springframework.org/tags" xmlns:c="http://java.sun.com/jsp/jstl/core"> <jsp:output omit-xml-declaration="yes" /> <spring:url value="http://maps.google.com/maps/api/js?sensor=false" var="google_map_url" /> <spring:url value="/static/js/googleMap.js" var="tmp_map_url" /> <c:set var="map_url" value="uri:/${tmp_map_url}" /> <script type="text/javascript" src="${google_map_url}"> </script> <script src="${tmp_map_url}" type="text/javascript"> </script> <page:show id="ps:org.josean.rooworld.domain.Country" object="${country}" z="3tU6/DN2doNWT+sTLgEAZR7U8hk="> <table width="100%;"> <tr> <td width="50%"> <field:display field="code" id="s:org.josean.rooworld.domain.Country.code" object="${country}" type="img" z="?" label="Flag" /> <field:display field="name" id="s:org.josean.rooworld.domain.Country.name" object="${country}" z="FAyyuD7aX42uNNgL4e7tS//taRI=" /> <field:display field="continent" id="s:org.josean.rooworld.domain.Country.continent" object="${country}" z="fSpvsKUctolI0akJTZzYHoOwueo=" /> <field:display field="region" id="s:org.josean.rooworld.domain.Country.region" object="${country}" z="z7xfg8bZs8LFPftHWVjP45HdpGI=" /> <field:display field="surfaceArea" id="s:org.josean.rooworld.domain.Country.surfaceArea" object="${country}" z="7C7ri5E3jCruBij5X5iEJqh4g1k=" /> <field:display field="indepYear" id="s:org.josean.rooworld.domain.Country.indepYear" object="${country}" z="EZL1ubZ/J9SiMbCUfokjr1OoDKA=" /> <field:display field="population" id="s:org.josean.rooworld.domain.Country.population" object="${country}" z="kqB3gvDWozV4lRD2m/S/6tpw2rE=" /> <field:display field="lifeExpectancy" id="s:org.josean.rooworld.domain.Country.lifeExpectancy" object="${country}" z="6Sj9b9rtuCZd1V5oNnz7gmAaQkI=" /> <field:display field="gnp" id="s:org.josean.rooworld.domain.Country.gnp" object="${country}" z="cQC9QwBNccJoYP9+xn4nAakFVVk=" /> <field:display field="gnpold" id="s:org.josean.rooworld.domain.Country.gnpold" object="${country}" z="AKqXyf8qWGWBU0HwUSIvnnLzZeE=" /> <field:display field="localName" id="s:org.josean.rooworld.domain.Country.localName" object="${country}" z="jYwa2XCaRe58W9ae45HLAaLlt7A=" /> <field:display field="govermentForm" id="s:org.josean.rooworld.domain.Country.govermentForm" object="${country}" z="N9WckigFkEM6lBgGaHR3QG13Lq4=" /> <field:display field="capital" id="s:org.josean.rooworld.domain.Country.capital" object="${country}" z="JRQSSvwHoOt1d2yff5JeK7NDn0k=" /> <field:display field="code2" id="s:org.josean.rooworld.domain.Country.code2" object="${country}" z="gIR7Z72tUJCdEBJHExd4FLG1ze0=" /> <field:display field="headofState" id="s:org.josean.rooworld.domain.Country.headofState" object="${country}" z="EmNqI9StH4djy7tAZsVKe3+VJ+A=" /> <field:display field="latitude" id="s:org.josean.rooworld.domain.Country.latitude" object="${country}" z="?" /> <field:display field="longitude" id="s:org.josean.rooworld.domain.Country.longitude" object="${country}" z="?" /> <page:find reportParam="${country.code}" path="/pdf/countryReport" id="c:report" buttonLabel="Pdf Report" /> </td> <td> <div id="map_canvas" style="width: 400px; height: 550px;"> <button onclick="initialize();">Show Map</button> </div> </td> </tr> </table> </page:show> </div>
Code language: HTML, XML (xml)
That is it!

Conclusion

This article has shown a customization example using code originally started from the scaffold one created by the Spring Roo Web MVC add-on. I found the Jspx notation very expressive and intuitive. The tagx library is ample and easily to extend if needed. Jspx are XML documents, consequently they are validated against wellness. I have to say that this annoyed me in the beginning but after a short time, I got used to and started to like it. Not to mention the benefits of having forms error checking. Spring Roo Web MVC views are simpler and less interactive their contra-parts based heavily in Javascript and Ajax. However, I believe they are very useful in a variety of Web Development projects and plenty of market for them. As the Reader can see, the look and feel of a Roo created app can totally be change to meet any UI/Web design requirement. This code example was create Spring Roo 1.1.0.M1.

View Comments

    • Sorry Majkel,

      What you mean? It works!. From the showcases front-end click on World Almanac.showcase.
      That's it. Next time I will be more explicit for telling the Reader where to click on.
      Thank you for bringing it to my attention.

      • Late response: I guess the load of the almanac was slow back then. This one works now. The first grids and charts link also work but initially it takes up to 10 seconds to display properly , 5 of which occur after page seems fully loaded. Dual 2.0 G5 with 8GB RAM in Firefox 8.
        Thanks for your examples!

        • Hello Majkel,

          If you can visit World Almanac by jD...
          I believe you will find it way-way faster. If interested I tell you what it did for it.

          Best results using Chrome. Firefox is ok too.

          Roogards
          jD

      • Hello Majkel,

        You are very welcome...

        My response time -form here-is < than a second on the charts, filtering using different Continents. Which by the way the chart is generated every time.

        I notice that sometimes the rendering makes a short pause about in the middle page- rendering the flags. I haven't done any optimization at all. This is just a prototype for understanding how to move the CRUD code generated by Roo and find what it takes to create complete web applications.

        I am running multiple applications using the same web container which also impact performance.

        Roogards
        jD

  • Viral,

    When you get time could you please post any examples on Spring Security with Database and Spring web-flow.

    Thanks,
    naveen

  • Nice tutorial,
    but how i'm beginner in java
    i need de source code to understand
    more.

    it's possible send me te source code?

    tanks,

    marcos

    sorry for bad english

  • Hello, I need to understand better your source code. Can you send it to me? I am trying to load google maps in my springroo project but it just load first level of script("http://maps.google.com/maps/api/js?sensor=false") I noticed that the function getScript (getScript("http://maps.gstatic.com/intl/pt_br/mapfiles/api-3/10/15a/main.js");), for example, doesnt work, seems that there is some conflicts with webmvc and this function. I tried to download it and it works but when the day change they(google) change the validation key and the script doesnt work anymore

  • Hi, I am getting the below error, what to do ?
    Please help me.

    No tag "gallery" defined in tag library associated with uri "urn:jsptagdir:/WEB-INF/tags/form/fields"

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

4 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

4 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

4 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

4 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

5 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

5 years ago