Tuesday, November 10, 2009

jQuery autocompleter

How can it be that well working (out of the box) autocompleters are so hard to come by? Well, this time I wanted one for jQuery, since I didn't want to introduce yet another javascript framework for this little thingy.
I found two different autocompleters under the jQuery project.

The first one didn't really work as ajaxy as I wanted. I couldn't get it to update the selection base while entering data. Instead it could only load a dataset when bound to the input then do some filtering itself.

The second looked much better but despite all the configuration options I couldn't get it to read simple JSON responses. Instead it seemed only to work with the default newline-separated-"formatted" datasets.

So. Should I fix one of them or continue looking? Well, the second had some eyecandy going so I jumped in to it. Didn't take long. Alot of cutting (since json becomes simpler than "my own fluffy format") and fiddling with the requests and voila, an exellent, simpler ajax autocompleter for jQuery. Source code GPL (beware, it's hacked for my needs!):

Wednesday, October 28, 2009

Painful unit testing in struts 2

If you plan on doing unit testing and truly decoupled action classes in struts 2 I must recommend you not to use the abstract (but helpful) ActionSupport class in your class hierarchy. Why? Many reasons, here's one.

The ActionSupport class contains some hard coupling which makes unit testing outside of a struts 2 "ActionContext" impossible. Of course, you can set up an ActionContext in the tests setUp() method and you're home free, but it's a heavy and unnecessary fixture. Inheriting the ActionSupport class binds you to this solution in some cases. Amongs others, this field

private final transient TextProvider textProvider =
new TextProviderFactory().createInstance(getClass(), this);

is a pain.
If the ActionContext is not setup, any call to getText(...) will cause a null-pointer exception at this line

ValueStack valueStack = ActionContext.getContext().getValueStack();

for obvious reasons.

This leaves you with three options. either you build up that awful fixture and build fragile tests which all fails in groups and tests much more logic than they should. Or you avoid testing code which touches this stuff. Or you copy the ActionSupport class (watch out for the license!) and set the field to default visibility instead of private final and replace it with a mock in the unit test.

Sunday, October 11, 2009

Workaround for buggy struts 2 portlet plugin

The Struts portlet plugin makes portlet development almost as smooth as web development with struts. Except that there is no server environment like tomcat in eclipse the portlet plugin makes portlet behave just as applications.

In my setups I create maven profiles for building the portlet and developing in eclipse. By adding a webapp profile with sitemesh and setting up a basic sitemesh decorator for the portlet styling can be done without deploying to the container all the time.

Now, there are a few issues with the portlet plugin. One of them turned out to risk becoming a show-stopper for struts usage in my latest project. I've been spending some free time on digging into this and here's what I have come up with.

When form urls are rendered with the portlet plugin, the plugin adds a parameters containing the namespace and action (path) that should be executed when the form is submitted. This path is constructed from a number of parameters, the portlet namespace, current portlet mode namespace and the namespace declaration on the s:form tag. Normally, a simple test form would look like

<s:form>
<s:textfield name="value"/>
<s:submit method="submit" />
</s:form>

which is simple and clean and what I like about struts 2! Now let's say the action is executing in namespace /test/view as declared in the viewNamespace parameter from portlet.xml. Then the portlet url will become portlet namespace + mode namespace + tag namespace which results in "/test/view" + "" + "/test/view" since the third part is by default the namespace of the current action. Of course, this will not work.

Loosing some of the clean and simple and reusability the form can be fixed to work properly by manually setting the namespace to "nothing" and thus using only the mode namespace. This form can of course never be reused for other actions, but that might be a minor problem.

<s:form namespace="/">
<s:textfield name="value"/>
<s:submit method="submit" />
</s:form>

If you are also using a portlet namespace, then it probably gets worse and I won't even try to go there.

Saturday, October 10, 2009

Number and date formatting in struts 2

Struts 2 has excellent capabilities built-in to handle internationalization. Not only in the sense of messages printed but also in formatting values and handling conversion of the submitted string to corresponding types, and adding field errors when they cannot be converted. All based on the user locale. Hit is a feature widely used, which became very apparent when release 2.1.3 (or maybe 2.1.4) broke the conversion error handling.

I have been fiddling for a while to get this parts working right in my forms. In those cases it is not automatic. There is no way for struts to know that the double I have in my model is actually a currency value and should be formatted accordingly. The struts documentation contains a section on what I need but it never worked, and turned out (perhaps) erroneous. It has been corrected in the most recent version but I'm putting up this post since google is not your friend always, you keep hitting wrong version in the docs now and then.

My issue is I have a date and currency value in my model, of the types Calendar and Double. I need the to be displayed in local format, and properly converted when submitted. First off is the format configuration, which goes in the resource boundle, in my case messages.properties.

format.money={0,number,#0.00}
format.date={0,date,yyyy-MM-dd}

This is actually swedish formats. The dot in the money format comes out correctly as a comma (how, I have no idea). This configuration is enough to make form post conversion work as expected.

Next step is getting output to work. This is easy if printing a number with s:property like this.

<s:text name="format.money">
<s:param name="value" value="model.price"/>
</s:text>

And there is the s:date tag for formatting dates. This can however not be used as easily in the s:input tags where they should go. To get those formats into the form.

<s:textfield name="model.observed" label="date"
value="%{getText('format.date',{model.observed.time})}" />
<s:textfield key="model.price" label="price"
value="%{getText('format.money',{model.price})}" />

Do not the time addition to the model.observed Calendar value, it makes sure the Date value is exposed, since the formatting does not work with Calendar type.

Friday, September 25, 2009

Installing internet explorer 7


Doing some website style testing, I need Internet Explorer since we have obviously promised the customers that everything will run fine with it. I however just got this message trying to install IE7. *Arrgh* what now!?

Saturday, September 12, 2009

Decoupling struts actions

Searching Google for struts unit test techniques you find a lot of discussions and blogs on the subject. The only ones I've found are either discussing the StrutsTestCase or how in some other way (manual) setup the entire struts machinery to run unit tests. I have however not found anything about how to test action classes alone.

Testing struts actions with the StrutsTestCase tests much more than just the logic in the action class itself, which is normally what you want to do in a well isolated and simple unit test. I am not interested in whether urls are correctly mapped or request parameters are set on my models by struts. This is something the struts developers do themselves, I assume, and for me it is actually more of an integration test.

So, to my issue. Trying to unit test my actions I ran into a new issue the other day testing an action using the getText(..) method. This particular method, in the end, locates package resources in it's own directory (from the action class) and parent packages until a resource is perhaps finally found. This requires the environment to know about which action class is executing. I've been trying to mock this condition away with combinations of easyMock and the struts bundled mock classes. To no avail.

The problem here is a classic one when you try to unit test. It is because I have extended the bundled ActionSupport (for convenience) and it contains:
private final transient TextProvider textProvider = 
new TextProviderFactory().createInstance(getClass(), this);
private final ValidationAwareSupport validationAware =
new ValidationAwareSupport();

The ValidationAwareSupport is just a datastructure to decrease code size of the validation aware class and has no external dependencies, which makes it a non-issue.
The TextProviderFactory however, is a big issue. Skipping a few details, digging into it, it depends on just about everthing. There are utility methods accessing action context and the valuestack and so forth. Wanting to avoid the execution context, in this case the action context (and possibly more), this should of course be decoupled.

I have already, since long back written my own ActionSupport since I didn't want it to be serializable. And, now decoupling the TextProvider is not very hard. I just add an interceptor that injects the TextProvider into the action during struts invocation. After this I'm free to provide a truly decoupled mock TextProvider in my unit test.

@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof TransientActionSupport) {
if (logger.isDebugEnabled()) {
logger.debug("Setting text provider on action");
}
((TransientActionSupport)action).setTextProvider(
new TextProviderFactory().createInstance(
action.getClass(), (LocaleProvider)action));
}
return invocation.invoke();
}

The next step is just to add the interceptor to your default interceptor stack, and you have the same functionality in your webapp as before.

Tuesday, September 8, 2009

In Redmod, they know how to prevent good programming

I'm not only working on Java... The worst thing with working with microsoft stuff is probably getting used to it, considering .Net fairly "ok", rediscovering the wonderful Java practices and tools and now going back and forth between Java and the disgusting .Net.

Today, I'm doing some Analysis Services coding. Trying to maintain a piece of web application visualizing data from the OLAP. It has once been written by a DBA, which means most logic was once in the database. Databases are like Excel, they can do to many things and are therefore used for things they weren't supposed to.

However, I tried writing a unit for a constructor implemented enourmous method that I'm trying to split up and test. However, it turns out, it's impossible. ADO MD (OLAP client) is written to be impossible to test, by sealing all its data classes. Trying to find out how the use those classes, I found this page, check the community comment!

It's clear. At microsoft, they detest modern practices so much they go to lengths to prevent them!