Setting up Valuelist with Struts or other frameworks

Setting up Valuelist with Struts or other frameworks

A few months ago, Jeff Genender told me about a tool that was displaytag like but better, ValueList. Then a while back Matt Raible notifies us of another new tag, DataGrid. I’ve used DisplayTag in the past on a few projects and it was a wonderful tool but it has its issues.

ValueList is a Spring induced tool, meaning that it has a dependency on Spring to make it work (or that it what it appears to me). It uses Spring to handle getting the results from the database and that is where it is vastly different from DisplayTag and DataGrid. In DisplaTag or DataGrid I believe you pass it a collection and it handles pagination from there, but what if your collection had 5,000 items in it? ValueList queries only what you need to see on the page at one time so large datasets are no problem! ValuesList takes the data tier into consideration making the tag span both tiers in a fairly decoupled way.

The downside to ValueList, very limited documentation (typical). So let me share with you the pains that I had because this is a good tool. The example I show uses their jdbcAdaptor but there are other adaptors like Hibernate or you can write your own too.

The pieces
applicationContext.xml
view.jsp
CustomAdaptor
Struts Action

STEP 1
You need a applicationContext.xml file from Spring and
add a valuelist entry like this

<bean id="valueListHandler" singleton="true" class="net.mlw.vlh.DefaultValueListHandlerImpl">
<property name="config.adapters">
<map>

<entry key="jobListByJobKey">
<bean class="com.xcel.flipper.console.dao.adapters.JobHistoryAdapter">
<property name="dataSource"><ref bean="flipperDataSource"/></property>
<property name="useName"><value>false</value></property>
<property name="defaultNumberPerPage"><value>8</value></property>
<property name="defaultSortColumn"><value>startdate</value></property>
<property name="defaultSortDirection"><value>asc</value></property>

<property name="sql">
<value>

select el.JOB_KEY as jobKey,
el.START_DATE_TIME as startdate,
el.END_DATE_TIME as enddate,
job.job_name as jobname,
jobstatus.job_execution_status_descr as status
From JOB_EXECUTION_LOG el,
JOB job,
JOB_EXECUTION_STATUS jobstatus
where el.job_key = job.job_key
and jobstatus.job_execution_status_code = el.job_execution_status_code
/~jobId: and el.job_key = {jobId}~/
/~sortColumn: ORDER BY [sortColumn] [sortDirection]~/
</value>
</property>
</bean>
</entry>

Key items here are how parameters get passed in

						   /~jobId: and el.job_key = {jobId}~/
						   /~sortColumn: ORDER BY [sortColumn] [sortDirection]~/

This says that in the request there will be a parameter called jobId, most likely got there from a form query posting. There is also a sortColumn and sortDirection, those you don’t manually put in the request but valuelist does it for you because they are passed in when the user wants to sort the result set in the view. Notice near the top that there is a default sort column and direction. You can see the sort arrows in the demo snapshot. Those columns are links to sorting the column.

STEP 2

Setup your Custom Adaptor

public class JobHistoryAdapter extends AbstractJdbcAdapter {

public List processResultSet(String name, ResultSet result, int numberPerPage) throws SQLException
{
List list = new ArrayList();

for ( int rowIndex = 0; result.next() && rowIndex < numberPerPage; rowIndex++)
{
JobHistoryDisplayBean historyBean = new JobHistoryDisplayBean();

historyBean.jobLog.setJobInstanceKey(result.getString("jobKey"));
historyBean.jobLog.setStartDateTime(result.getDate("startdate"));
historyBean.jobLog.setEndDateTime(result.getDate("enddate"));
historyBean.job.setJobName(result.getString("jobname"));
historyBean.status.setJobExecutionStatusDescr(result.getString("status"));
list.add(historyBean);
}

return list;
}
}


Notice I extract the values from the result set via a name which was defined in the sql command in the application.xml file. This class is referenced in the application.xml near the top.

STEP 3

Setup your Action class In your pre view action (or sometimes called dispay or load action) class (or if you are lucky enough to be using Webwork, in an Custom Interceptor) place this piece of code

ValueList valueList = getValueListHandler().getValueList("jobListByJobKey", ValueListRequestUtil.buildValueListInfo(request));
request.setAttribute("list", valueList);


This will call that particular entry in the application context and put this list in the request. This appears very much like display tag in that you put a collection in the request for the tag to interate over however one major difference here is the size of the list you a stuffing into the request. In Valuelist the collection size is the number of items you will show on one page, so in my example here it is 8 (see Spring reference above for defaultNumberPerPage) er

If you want to run a different query then call a different entry by name in the code above.


STEP 4 Setup the view



<vlh:root value="list" url="?" includeParameters="*">


<table width="450">
<!-- pagination section -->
<tr>
<td align="left" nowrap="true">
<c:out value="${list.valueListInfo.totalNumberOfEntries}"/> Total
- Page (<c:out value="${list.valueListInfo.pagingPage}"/> of <c:out value="${list.valueListInfo.totalNumberOfPages}"/>)
 
</td>
<td align="right">
<vlh:paging />
</td>
</tr>
<!-- end of Pagination -->
<tr>
<td colspan="2">
<table width="650" class="classicLook" cellspacing="0" cellpadding="0">
<vlh:row bean="job">
<vlh:attribute name="onclick">document.location='viewJobDetails.do?jobInstanceId=<c:out value="${job.jobInstanceKey}"/>';</vlh:attribute>
<vlh:attribute name="onmouseover">this.className='selected';</vlh:attribute>
<vlh:attribute name="onmouseout">this.className='zebra0';</vlh:attribute>

<vlh:column title="Start Date" property="startDateTime" sortable="desc" />
<vlh:column title="End Date" property="endDateTime" sortable="desc" />
<vlh:column title="Job Name" property="jobName" sortable="desc" />
<vlh:column title="Job Status" property="status" sortable="desc" />

</vlh:row>
</table>
</td>
</tr>
</table>

</vlh:root>

Then the last item for the view to work is to add the tag to the web.xml file

<taglib>
    	<taglib-uri>valuelist.tld</taglib-uri>
    	<taglib-location>/WEB-INF/tlds/valuelist.tld</taglib-location>
    </taglib>

Summary

Valuelist does have more setup than DisplayTag does and maybe DataGrid but that is because Valuelist considers the datatier as part of the solution rather than leaving that up to you. If you collections will be small than there is little value gained from Valuelist but in most cases they probably won't be so take the time to use Valuelist. Also the main author of the project is VERY responsive on the forums so if you do get stuck he is there will to lend a hand. There is also a similar example that comes with the Valuelist download however it leaves out the part where you can integrate it with Struts.

Posted by kris at September 28, 2004 05:26 AM

Trackback Pings

TrackBack URL for this entry:
http://adigio.com/blogs/mt-tb.cgi/342

Comments

Nice blog:) Thanks for lending a hand in the documentation gap that I have.

Posted by: Matthew Wilson at November 1, 2004 06:43 AM

Thank you for your introduction using ValueList with Struts! Is it possible to provide some source code showing a working example? That would be great!

Posted by: Sebastian Beigel at November 9, 2004 08:54 AM

INFO] XmlBeanDefinitionReader - Loading XML bean definitions from resource [/WEB-INF/classes/standardJspApplicatio
Context.xml] of ServletContext
ERROR] ContextLoader - Context initialization failed java.lang.UnsupportedClassVersionError: net/mlw/v
h/web/tag/support/CsvDisplayProvider (Unsupported major.minor version 48.0)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:488)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:106)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1634)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:860)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1307)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1189)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:310)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.parseBeanDefinition(DefaultXmlBeanD
finitionParser.java:245)
at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.loadBeanDefinition(DefaultXmlBeanDe
initionParser.java:200)
at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.registerBeanDefinitions(DefaultXmlB
anDefinitionParser.java:152)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionR
ader.java:161)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReade
.java:127)
at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplica
ionContext.java:123)
at org.springframework.context.support.AbstractXmlApplicationContext.refreshBeanFactory(AbstractXmlApplicat
onContext.java:65)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:2
2)
at org.springframework.web.context.support.XmlWebApplicationContext.refresh(XmlWebApplicationContext.java:1
1)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:154)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:95)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:48)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4343)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595)
at org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:277)
at org.apache.catalina.core.StandardHost.install(StandardHost.java:832)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:701)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:432)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:983)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:349)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1091)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:789)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1083)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:478)
at org.apache.catalina.core.StandardService.start(StandardService.java:480)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:2313)
at org.apache.catalina.startup.Catalina.start(Catalina.java:556)
at java.lang.reflect.Method.invoke(Native Method)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:425)

ERROR] Context - Error listenerStart
ERROR] Context - Context startup failed due to previous errors
INFO] StandardHostDeployer - Installing web application at context path /webdav from URL file:E:\Tomcat\webapps\we
dav

Posted by: srikanth at November 22, 2004 01:49 AM

Please check some helpful info about loans loans http://www.fidelityfunding.net/ low interest credit cards low interest credit cards http://low-interest-credit-cards.web4u.gb.com/ casinos casinos http://casinos.web4u.gb.com/ weight loss weight loss http://weight-loss.web4u.gb.com/ forex forex http://forex.web4u.gb.com/ tax tax http://tax.web4u.gb.com/ taxes taxes http://taxes.web4u.gb.com/ turbo tax turbo tax http://turbo-tax.web4u.gb.com/ capital one credit card capital one credit card http://top-one-credit-card.web4u.gb.com/ mortgage loans mortgage loans http://mortgage-loans.web4u.gb.com/ blackjack blackjack http://blackjack.web4u.gb.com/ party poker party poker http://play-poker.web4u.gb.com/ texas holdem poker texas holdem poker http://texas-holdem-poker.web4u.gb.com/ poker online poker online http://poker-online.web4u.gb.com/ pacific poker pacific poker http://pacific-poker.web4u.gb.com/ weight loss pills weight loss pills http://weight-loss-pills.web4u.gb.com/ cheap phentermine cheap phentermine http://cheap-phentermine.web4u.gb.com/ buy phentermine buy phentermine http://buy-phentermine.web4u.gb.com/ buy viagra buy viagra http://buy-viagra.web4u.gb.com/ buy viagra online buy viagra online http://buy-viagra-online.web4u.gb.com/ ...

Posted by: casinos at January 3, 2005 04:22 PM

MT will always be king! http://www.hgh-express.com HGH

posted on 2005-01-10 23:49  笨笨  阅读(2598)  评论(0)    收藏  举报

导航