Overview

Using JDBC in many ways is tedious and error prone. There are many emerging alternatives to the brute force method of coding JDBC. JDO and similar projects such as Hibernate are a great alternative to the old approach of using JDBC. JDO and the like are great for loading pojos, but they are not ideal when it comes to querying the database for lists of data. Inline views and unions are difficult to implement in a JDO like implementation, some things are best done in a straight JDBC solution. This is one way the ValueListHandler fits into the picture.

Even in solutions where a List of pojos are retrieved from a service the ValueListHandler still encourages consistency across all services. In this case you would implement your own implemention of a ValueListAdapter, that simply calls your business method and converts the results to a ValueList.

Configuration

The property file mlavwilson.properties, is one of the configuration files for the ValueListHandler service tag libs. This property file contains some properties that customize the look and feel of the web components, and some properties that customize the behavior of the tags. I will come back to this later. Note: mlavwilson.properties are deprecated in nowaday. See configuration bean for more details.

Starting with release 0.1.1 I have let Spring manage and configure the ValueListService. This is a major change from pervious versions. See Beans and the ApplicationContext for details on how to use Spring in a web environment. Or take a look at the sample app: http://nighthawkds.homedns.org:8081/valuelist . Below is the config file from the sample war.

The above file configures the bean 'valueListHandler' which is the service. This bean has a map of adapters available to the ValueListHandler. Using Spring to manage the service allows the adapters to be configured in one place in a consistent manner. To see a config file for a real application see mlwfflm.

How to use the Service

In the previous section we outlined how to add adapters/queries to the ValueListHandler. From the sample file snippet, you see an adapter named "nbaTeams" with a query that selects from the team table. Using this query, we will step through the process involved in requesting the data that this query returns.

Get an instance of the service.

The ValueListHandler is an interface, so you need an implementation to work with. The easiest way to use the ValueListHandler in a web environment is to let Spring get it for you:

WebApplicationContext context 
    = WebApplicationContextUtils.getWebApplicationContext(pageContext.getServletContext());
ValueListHandler vlh 
    = (ValueListHandler) context.getBean("valueListHandler", ValueListHandler.class);
	      

Prepare to call the service.

Before the service can be called the ValueListInfo must be created. The ValueListInfo contains the following:

filtersA Map used to build and populate the query.
sortColumnsThe column(s) to sort the data by.
sortDirectionsThe direction(s) to sort the data.
pageNumberThe current page, set by the service if null.
totalNumberOfEntriesThis is set by the server after the call.
numberPerPageThe number of rows per page.
focusPropertyThe name of the property used for a focusing of the specified value.
focusValueThe value of the focusProperty. It search for a page and row, where is situated focus property with specified value.
//Create the info object, sort by the team column.
ValueListInfo info = new ValueListInfo("team", ValueListInfo.DESCENDING, parameters);
          

Request the ValueList from the sevice.

ValueList vList = vlh.getValueList("nbateams", info);

This method call returns a ValueList, which contains a list and the info that was passed into the service. The ValueList is also an Iterator! The ValueList is retrieved in the following way:

  1. Using the name (first argument) passed into the service, and adapter is located. This adapter was configured earlier in the xml snippet above.
  2. The adapter is used to retrieve the data from the database. To be an "adapter" in the ValueListHandler you must implement the ValueListAdapter interface.
  3. Now that the service has the data, the service has a chance to modify the ValueList. Using the method getAdapterType on the adapter, the service will sort, page and filter the data if needed. This allows the adapter to delegate the sorting, paging and/or filtering if desired.
  4. The service returns the ValueList.

Display the ValueList.

The ValueList can now be displayed. There are a few tags to assist in the web enviroment, they are discussed latter. There is also an implementation of JTable (coming soon) that displays the ValueList. But of course you are not limited to these two display implementations.

To display the ValueList in a jsp environment there are a few taglibs to assist you.

#NameSinceDescription
1vlh:root0.1.3 This tag is required as a parent element for all other vlh tags.
2vlh:retrieve0.1.1 This tag calls the ValueListHandler and requests the ValueList and gives it to the vlh:root tag.

NOTE: This tag should be used if you are not using the MVC push model.

5vlh:row0.1.0This is an iterate tag. It Iterates over the ValueList.
6-11vlh:column0.1.0This tag defines a column to display.
 1:  <vlh:root value="list" url="?" includeParameters="*" >
 2:   <vlh:retrieve name="nbaPlayers" />
 3:   
 4:   <table width="450" class="simple" cellspacing="0" cellpadding="0">
 5:     <vlh:row bean="player">
 6:       <vlh:column title="playerid"   property="playerid"   sortable="desc" />
 7:       <vlh:column title="teamname"   property="teamname"   sortable="desc" />
 8:       <vlh:column title="firstname"  property="firstname"  sortable="desc" />
 9:       <vlh:column title="lastname"   property="lastname"   sortable="desc" />
10:        <vlh:column title="status"     property="status"     sortable="desc" />
11:        <vlh:column title="pos"        property="pos"        sortable="desc" />
12:      </vlh:row>
13:    </table>
14:    
15:  </vlh:root>

For more details on displaying a ValueList in a web environment see valuelist.war.

Included Adapters

DefaultDynaBeanAdapter This ValueListAdapter returns a ValueList of DynaBean(s). This is useful for simple applications or demos. I would not recommend using this adapter for a real solution.
DefaultDynclassAdapter This ValueListAdapter returns a ValueList of Dynclass(s). This is useful for simple applications or demos. I would not recommend using this adapter for a real solution.
DefaultWrapperAdapter This ValueListAdapter returns a ValueList of wrapped records from ResultSet. Using wrappers is recommended in cases, when your hibernate hql is too complex, and you cannot controll all composite joins for example.
FileSystemAdapter This ValueListAdapter returns a ValueList of FileInfo(s). This is useful for browsing a file system on the web.
Hibernate20Adapter This ValueListAdapter returns a ValueList of pojos delegating the data access to Hibernate. As well, Hibernate20Adapter can focus (look up a row of specified property using specified value). See valuelist.war examples.

Almoust all adpaters (except FileSystemAdapter) are able to use so called validators of rows. See Hibernate20Adapter where you can find simple usage.

How to use the ValueList in a MVC framework

Main aim of this section is to give a solution for so called "refresh button problem".

Ussually, when you work with an web application, sometimes you need redirect to 'view' and not to lose all information about sorting, focusing, paging on so on. Considere example: You like to delete a row of the table. If you do it with just a forwarding parameters via request, it is possible that after deleting row you will be forwarded back to the view jsp. But when an user press refresh button, it will be called delete method again due to fact, that all request parameters are still the same!

Basicly therefore was writen this service helper class that allow you to back up your actual state of viewed table to the session and retrieve it back when is it necesserally.

Get an instance of the service's helper.

The ValueListHandlerHelper is a class, that require before any use to set any ValueListHandler implemntation. The easiest way to use the ValueListHandlerHelper in a web environment is to let Spring bean factory create it for you:

  
			
<bean id="valueListHelper" singleton="true" class="net.mlw.vlh.web.mvc.ValueListHandlerHelper">
	<property name="valueListHandler">
		<ref bean="valueListHandler"/>
	</property>
</bean>
 
<bean id="valueListHandler" singleton="true" class="net.mlw.vlh.DefaultValueListHandlerImpl">    
    <property name="config.adapters">
		  <map> ... and so on.
		  </map>
    </property>
</bean>					 
		

The next is to set up your controller to know that you would like to use a service's helper class instance.

 
class MyController ....
{
	public void setValueListHelper(ValueListHandlerHelper valueListHandlerHelper) { 
		this.valueListHelper = valueListHandlerHelper; 
	} 
	..
}

The refresh button problem solution

Now we will focus more on detail, how to backup information about the table. Considere an example: We have one table in jsp with the id="MyTable". A strut's controller for this table could look like this:

public ActionForward doDelete(ActionMapping mappings, ActionForm form,
	   HttpServletRequest request, HttpServletResponse response) throws Exception
{
	ValueListInfo info = valueListHelper.getValueListInfo(request, "MyTable");
	
	//modification of paging page after delete first row that is also last row in last page.
	info.setPagingPage(valueListHelper.getLastPageAfterDelete(info));
	
	valueListHelper.backupInfoFor(request, info, "MyTable");
	
	//redirect true
	return mappings.findForward("view");
}
	  
		 
At first, we must get information about actual valuelist's info. After that, we can modify it, and finally, we should it backup into the session.

If the request parameters doesn't containt any information for the table with id 'MyTable', it try to get an information from previously saved backup of the state (ValueListInfo) of the table from http's session. Therefore is necessity after every action to backup valuelist's info. As a unique key is used table's id 'MyTable'.

For more information how to use this class see

Use case

To see a good example of how the ValueList is used, take a look at the spring-config file for the Fantasy Sports Components. This config file has a query named playerRank. This query has left joins, inline views and a large amount of group bys. This solution is using the DefaultDynaBeanAdapter right out of the box.