Wednesday, March 25, 2009

What's up with 0.0 not being mapped in Struts 2.1.6?

Recently converted to Struts 2.1.6, and I found a small problem. There were double values displaying in my JSP textfields as 0.0. When those values were submitted to my action which had a setQuantity (double quantity), I was receiving OGNL Exceptions saying that the method setQuantity([Ljava.lang.String;)] did not exist. Something similar to this:

[java.lang.NoSuchMethodException: setQuantity([Ljava.lang.String;)]  
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:823)
at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:964)
at
ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:75)
at
ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:131)
at
com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:28)


Well of course it did not exist, it was a double I was submitting. I wanted nothing to do with Strings on this field.

It turns out that this is a known issue with the xwork-2.1.2.jar file. So I was able to find the xwork-2.1.3.jar file from here:
http://jira.opensymphony.com/browse/XW-676

Once I added this to my project, the problem was solved and things are working nicely again. Enjoy!

Thursday, March 5, 2009

Formatting Numbers with Struts 2

I just wasted about 4 hours trying to figure out how you can format a number in a textfield with Struts 2. The only explanation was at http://struts.apache.org/2.0.14/docs/formatting-dates-and-numbers.html
I found was to make my <s:textfield> tag look like this:


<s:textfield key="orderItem.price"
value="%{getText('format.number',{'orderItem.price'})}" />

In this instance format.number refers to an entry in your package.properties file (NOTE: You actually should call this file package.properties. 'package' does not refer to the actual name of your package.) Inside this package.properties file you need an entry that looks similar to this

format.number= USD{0,number,##0.00}

which will output the number 1500.0 like: USD 1500.00

Anywho, there are several ways to define a formatting properties file, but for eases sake, just place the package.properties file inside the directory that your java action is. If I have an action org.james.actions.ViewPurchaseOrdersAction.java. Then my package.properties file would belong in org.james.actions. Now if you want your package.properties file to apply to all your actions, you can adjust the placement of the file, placing it higher in the package hierarchy. Basically Struts 2 will hunt down your package.properties file for you. The choices you make all depends on how tied to your actions your formatting should be.

Back on track. The key attribute of the above tag does something that I'm too lazy to look up. I didn't need it, we'll pass over. The shady thing though, is the value attribute. Using the above style for the value attribute, I was not able to get my formatted price to display.

After exhausting my patience trying all kinds of different things I started trying random things, and eventually got the following to work (Notice that the % and quotes are not inside the purchaseOrder.amount argument):

<s:textfield name="amount" theme="simple" value="%{getText('format.number',{orderItem.price})}" />

I'm not sure if this is because I'm on Struts 2.1, while the tutorial I took that snippet from is Struts 2.0, whether I just implemented something improperly, or whether that code snippet is just flat out wrong.

Either way I don't really care. My code works now, and I can move onto the next problem.
If the Struts 2 example from the official site isn't working for you, try mine.





Tuesday, March 3, 2009

Struts 2's Select Tag

Struts 2 provides a lot of useful tags that you can use in your jsp pages, to help simplify your html/java code.

One in particular that is fairly complex and requires explanation is the <select> tag.

Typical html select tags require you to specify the list of values one by one, creating potentially lengthy code. It's relatively inflexible and workarounds are usually abundant to get it to behave how you want.

The Struts 2 <s:select> tag however, provides nearly everything you could need to have fully functioning select dropdown functionality.

The attributes I use are headerKey, headerValue, list, listValue, and listKey.
One by one, headerValue allows you to tell your dropdown to initially display a message to your user. For example, if you want to tell your user, "Please select an employee", you can simply use that as the headerValue, and that will display as the very first option in your dropdown list.

The headerKey attribute assigns a value to the headerValue attribute. My headerKey is typically -1. Using this, when a page is submitted, I can easily ensure that a legitimate value has been selected, by ensuring the headerKey != -1.

list, tells the Struts tag what variable contains the list that you want to appear in the dropdown. The value you use for the list attribute must be iterable. In my Java action, I provide an ArrayList object that contains the values I want to be in my dropdown list. So if I have an Employee object, with getters and setters for employeeId and employeeName, and within my ArrayList called employeeList that has my Employee objects, I can specify that my list attribute is employeeList.

Next up is the listValue and listKey attributes. They work together. The listValue is what actually gets displayed in the dropdown list. Not the list that is iterated over, but the actual words themselves that appear. So using the employee example, I'd want the user to see the names of employees in my dropdown, so I'd specify my listValue="employeeName".

The listKey attribute indicates what request parameter value should be passed back to my action upon submission. For this example I'd make listKey="employeeId". But if you wanted to pass the name that was selected, you'd simply make listKey="employeeName".

Apart from the basic name and value attributes, which are self explanatory, you now have a fully functional dropdown list in your jsp, simply by using:

<s:select name="myEmployee" list="employeeList" headerKey="-1" headerValue="Please Select an Employee" listValue="employeeName" listKey="employeeId" />

And there you have it. The power of the Struts 2 <s:select> tag semi-de-mystified.