Discussing the nuts and bolts of software development

Monday, April 21, 2008

 

Struts 2 doubleselect: A Detailed Example

Struts 2 provides a fantastic doubleselect tag, which allows you to specify two HTML select lists in such a way that the contents of the second list is dependent on the selection of the first (1). About a month ago, I came across a situation where this type of relationship was very advantageous, and set off towards the relevant Struts 2 documentation to learn how this mysterious tag worked. I found the list of attributes useful, but the examples at the bottom of the page left much to be desired (they're completely hard-coded). In fact, even after a good hour of searching, I couldn't find a solid example of the doubleselect tag that didn't hard-code both lists! Obviously it's much more useful to take advantage of the java back-end, and it took me two full hours of trial and error to finally figure out how to get my particular scenario working. What follows is a detailed example showing how to use the Struts 2 doubleselect tag to its fullest, for the next time I or anyone else wishes to make good use of it.

For our example, suppose you run some sort of automotive website, and would like to let the use specify the Make and Model of a car. The list of Makes should contain the car company, like Porsche, Ferrari or Lamborghini. The lists of Models should be the specific cars those companies make, like "911 Turbo" and "Boxster S" for the Porsche, "F430 Spyder" and "FXX" for Ferrari, etc. So when Porsche is selected in the first list, it's set of models will be shown in the second list. If we change the selection in the first list to Ferrari, the second list should update to contain only the Ferrari models. We also want to know what Make and Model the user has selected, and be able to set default selections in each list. This can actually be done with very little JSP syntax using the doubleselect tag:


<%@ taglib prefix="s" uri="/struts-tags"%>

<s:form action="selectCar" method="POST">
<s:doubleselect
name="makeId" doubleName="modelId"
list="allMakes" doubleList="models"
listKey="id" doubleListKey="id"
listValue="name" doubleListValue="name"
value="defaultItem" doubleValue="doubleDefaultItem" /
>
</s:form>


Of course, in addition to the jsp shown above, we need a struts.xml file, the struts action, a Make class and a Model class. It is assumed that you already know how to set up the struts.xml file and the basics of the struts action. Here's what we need in the other files:
When the page loads, here is how the doubleselect tag is interpreted:
When the form is submitted, the name and doubleName attributes will call setMakeId and setModelId in the action, and give them the values of listKey and doubleListKey respectively. So if Lamborghini is selected in the first list, and Murcielago in the second, the parameters passed in setMakeId and setModelId would be the id of the Make instance which has the name Lamborghini, and the id of the Model instance which has the name Murcielago.

So that's all there is to it! I hope this has been helpful, and saves a bit of time for the next person trying to implement a complex double-list system with back-end support.


(1) This functionality is provided using javascript which is automatically generated when Struts interprets the doubleselect tag. One downside to this approach is that it will clutter up your source quite a bit if you're using a large dataset, but this is unavoidable while using this tag.

Labels: ,


Comments:
I had a big problem with this tag.
My doubleSelectOnChange doesn't make call to my javascript function and I don't kwnow why.
When I saw source-code page, the call isn't exist in the page.
Anyone knows what's happen?
 
I did a bit of testing, and from what I can gather, the documentation is simply incorrect; it doesn't look like the doubleselect tag supports the onChange event (this could be because Struts uses this event on the first list to load the second list, though that doesn't explain why they would simply ignore it for the second list).

The onSelect event doesn't seem to be supported either, and although onBlur seems to fire, doubleOnBlur doesn't (this is also true for onFocus).

It looks like you might be out of luck for built-in event support. You may be able to extend the tag and manually add support for these events, or you could always just simulate the doubleselect behavior yourself using DHTML/AJAX.
 
Thanks, really i was suffering because i couldnt do work my example, noy is working accesing data from DB.

Regards
 
This was *very* helpful. Thanks!
 
This was very helpful.Thank you!
 
I have a problem implementing this tag. I get this in the trace:

Caused by:
freemarker.core.InvalidReferenceException: Expression parameters.formName is undefined on line 101, column 43 in template/simple/doubleselect.ftl.

 
@MichiIndian:

This is Struts' way of telling you that it is expecting a property called formName on the doubleselect tag. Looking at the tag's documentation, this is an inherited property, so the problem is probably on a parent tag, not the doubleselect tag itself.

Make sure that the doubleselect tag is inside a struts form tag, and if that still doesn't work, try specifying the formName property explicitly on the form/doubleselect tag.
 
This comment has been removed by the author.
 
can you give me the layout of strut.xml file for this example ?
 
what if i have four select boxes and on selection of an item in first select will populate second select box, and on selection of an item in second select, third and so on till fourth select box gets populated ? How to do this?
 
@ D: There wasn't anything special about the struts.xml file, and it wouldn't make sense without the back-end Java anyways. There are many great resources for learning struts online, try the official docs: http://cwiki.apache.org/WW/home.html
 
@ kiran: By design, the doubleselect tag will only make two paired select boxes. If you want four, you're going to have to do it yourself. The best way to do this would probably be to extend the doubleselect tag and implement your own quadrupleselect tag or something similar. Here is a decent post to get you started about extending tags: http://bodez.wordpress.com/2009/03/13/customising-struts2-jsp-tags/

If you do this, I'm sure it would make a great blog post and I'd love to read it — so be sure to send me a link!
 
Great article. Helped me a lot!
 
Unlike official documentation this article is so helpful! Even two years after publishing :)
 
It's still not working from me:
The stack trace says:


java.lang.ArrayIndexOutOfBoundsException: -1
at com.opensymphony.module.sitemesh.html.HTMLProcessor$1.currentBuffer(HTMLProcessor.java:74)
at com.opensymphony.module.sitemesh.html.State.handleText(State.java:64)
at com.opensymphony.module.sitemesh.html.HTMLProcessor$2.text(HTMLProcessor.java:103)
at com.opensymphony.module.sitemesh.html.tokenizer.Parser.parsedText(Parser.java:295)
at com.opensymphony.module.sitemesh.html.tokenizer.Parser.parseTag(Parser.java:160)
at com.opensymphony.module.sitemesh.html.tokenizer.Parser.start(Parser.java:112)
at com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer.start(TagTokenizer.java:33)
at com.opensymphony.module.sitemesh.html.HTMLProcessor.process(HTMLProcessor.java:90)
at com.opensymphony.module.sitemesh.parser.HTMLPageParser.parse(HTMLPageParser.java:52)
at com.opensymphony.module.sitemesh.filter.Buffer.parse(Buffer.java:49)
at com.opensymphony.module.sitemesh.filter.PageResponseWrapper.getPage(PageResponseWrapper.java:165)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:124)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:738)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.struts2.dispatcher.ActionContextCleanUp.doFilter(ActionContextCleanUp.java:99)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
But if I insert sysout statements after double select they work..... wierd...
 
Hi, although you make me understand the code very nicely. 80% understood. But please-please-please could you paste the code of those three classes i.e. ActionClass, MakeClass & ModelClass. I'll be deeply thankful to you. I need those codes very badly. NO other site has yet make the doubleSelect tag dynamic..
 
Hi, although you make me understand the code very nicely. 80% understood. But please-please-please could you paste the code of those three classes i.e. ActionClass, MakeClass & ModelClass. I'll be deeply thankful to you. I need those codes very badly. NO other site has yet make the doubleSelect tag dynamic..
 
Thanks a lot ..your example is awesome :)

Sreenath
 
Struts is the most popular framework which is used for developing the java based applications. Struts framework is based on the model view controller architecture.
struts training in chennai | struts training
 
I have read your article. It is really useful for me. Start to learn Java programming because there is a massive demand for Java developers in IT sectors. It has a great scope in future.
JAVA Training in Chennai | JAVA course in Chennai

 

The strategy you have posted on this technology helped me to get into the next level and had lot of information in it. The python programming language is very popular and most widely used.
Python Training in Chennai | Python Course in Chennai
 
Thanks of sharing this post…Java is the fastest growing language that helps to get your dream job in a best way, so if you wants to become a expertise in Java get some training on that language.
Regards,
Core JAVA Training in Chennai | JAVA Training in Chennai

 
Java Online Training Java Online Training Java Online Training Java Online Training Java Online Training Java Online Training

Hibernate Online Training Hibernate Online Training Spring Online Training Spring Online Training Spring Batch Training Online Spring Batch Training Online
 
I have read your blog its very attractive and impressive. I like it your blog.
Java Training institute in velachery
 
Excellent post!!! Java is most popular and efficient programming language available in the market today. It helps developers to create stunning desktop/web applications loaded with stunning functionalities. Java Course in Chennai | Best JAVA Training in Chennai
 
Try Articles Pool. One of the top rated do follow article submission sites with extreme SEO value and quick approval.
 
Are you looking for best website to download eBook torrents for free? Then Ebook Share will be the right place. ebookshare | kovalanj
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?