Author Archive for alex

A few experiments with HTML 5 applications

I’ve had a long-standing interest in taking client-side programming beyond display logic and input validation. The new HTML 5 technologies are making full-scale application development in the browser increasingly practical. Unfortunately, the needs of Carbon Five’s clients generally exceed the capabilities of purely client-side solutions, so I don’t get to spend as much time developing JavaScript as I’d like. Consequently, I challenged myself to solve as many of my day-to-day issues as possible by writing applications that require only a single HTML page and a modern browser to run. So far, this has resulted in five applications; they’re available — with some additional thoughts on this style of development — below the fold.

Continue reading ‘A few experiments with HTML 5 applications’

Screw.Unit JS Testing in Maven: javascript-test-maven-plugin

I’ve written a maven plugin to integrate Screw.Unit javascript tests into a maven build. The project is inspired by the Blue Ridge testing framework for Rails, but it’s a bit more light-weight by design.
Continue reading ‘Screw.Unit JS Testing in Maven: javascript-test-maven-plugin’

Secure Email with Spring’s JavaMailServer and Gmail

Both Carbon Five and my ISP have moved email management over to Gmail.  While this has been a net improvement for me as an end user, it’s made it a bit more difficult to configure my applications to send outgoing mail.  It isn’t hard to find examples online that explain how to configure Spring’s JavaMailSender to work with Gmail.  But none of the examples I’ve found provide a configuration that can be switched between Gmail and an open SMTP server with a few reasonable external properties (an important feature in an application that needs to be deployed in varied environments).  What’s worse, the configurations tend to differ with no rational provided for the necessary parameters.  So I spent some time with the source and a debugger and came up with a simplified solution:

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
  <property name="defaultEncoding" value="UTF-8"/>
  <property name="host" value="${mail.host}"/>
  <property name="port" value="${mail.port}"/>
  <property name="protocol" value="${mail.protocol}"/>
  <property name="username" value="${mail.username}"/>
  <property name="password" value="${mail.password}"/>
  <property name="javaMailProperties">
    <props>
      <prop key="mail.debug">${mail.debug}</prop>
      <prop key="mail.${mail.protocol}.auth">${mail.smtp-auth}</prop>
    </props>
  </property>
</bean>

The properties for an open server look something like this:

mail.host       = localhost
mail.port       = 25
mail.protocol   = smtp
mail.smtp-auth  = false
mail.username   =
mail.password   =
mail.debug      = false

And the properties for gmail look something like this:

mail.host       = smtp.gmail.com
mail.port       = 465
mail.protocol   = smtps
mail.smtp-auth  = true
mail.username   = my.email@address.com
mail.password   = mypassword
mail.debug      = true

The host, port, username, password and debug properties should be obvious.  The key is to change the protocol between ‘smtp’ and ‘smpts’.  The only real difference between smtp and smtps is that the later causes JavaMail’s SMTPTransport object to open an SSL socket to the server.  Gmail only accepts SSL connections on port 465.  After figuring this out, I was glad to see that Gmail was accepting my connections, but immediately frustrated to find that JavaMail was no longer attempting to authenticate before sending mail.  The trick is that JavaMail checks its transport related parameters under ‘mail.[protocol].[parameter]‘.  This appears to be an entirely undocumented feature of JavaMail.  Fortunately, we can substitute the protocol name into the parameter key as well, so our auth parameter still works with either ‘smtp’ or ‘smtps’.

Parameterized REST URLs with Spring MVC

At Carbon Five, we’ve been working REST-ful practices into our web applications for some time now. Providing simple URLs for application entities is a key principal of this style, but parsing parameters out of the request path has been klunky in Spring MVC. Spring’s WebFlow apparently supports REST-ful URLs, but I’ve never found anything in what I’ve read or heard to recommended that project (though I’ve heard nothing bad).

I finally got fed up with the situation and worked out a solution that lets developers specify path parameters in the dispatcher mappings, which will appear as request parameters in the controller and view. I’ve made the project available on our public SVN server. The solution requires only 4 classes, so you can download them instead. Read on for configuration information.

ParameterizedUrlHandlerMapping

The solution is to replace Spring MVC’s SimpleUrlHandlerMapping with ParameterizedUrlHandlerMapping. This class is responsible for routing requests to the appropriate handler (servlet, controller, or JSP), so it’s an ideal place to specify the parameters. Of course, at this point, it has no more access to the request than a controller, so the best it can do is add the path parameters to the request attributes. It adds them as a Map of String name/value pairs with the key “ParameterizedUrlHandlerMapping.path-parameters”.

To use ParameterizedUrlHandlerMapping, replace the SimpleUrlHandlerMapping bean in the dispatcher configuration file
with something that looks like this:

<bean class="carbonfive.spring.web.pathparameter.ParameterizedUrlHandlerMapping">
  <property name="alwaysUseFullPath" value="true"/>
  <property name="mappings">
    <props>
      <prop key="/view/noparameters">controller1</prop>
      <prop key="/view/(bar:foo)">controller2</prop>
      <prop key="/view/(*.html:html)">controller3</prop>
      <prop key="/view/(**&#47;*:view).view">controller4</prop>
      <prop key="/view/c/(*:controller)/(*:id)">controller5</prop>
    </props>
  </property>
</bean>

The ParameterizedUrlHandlerMapping supports all mappings that are valid using SimpleUrlHandlerMapping’s default AntPathMatcher. The special parenthetical sections of the patterns have the syntax:

'(' + [ant_style_path] + ':' + [parameter_name] + ')'

Any part of the path pattern can be within parenthesis. The above example will having the following effect:

path controller parameters
/view/noparameters controller1
/view/bar controller2 foo -> bar
/view/piglet.html controller3 html -> piglet.html
/view/this/that/the-other.view controller4 view -> this/that/the-other
/view/c/save/2342443 controller5 controller -> save
id -> 2342443

ParameterizedPathFilter

If accessing the parameters from request attributes is all you need, you can stop here. But to elevate your path parameters to first class citizen status in your web app, you need them to appear as request parameters. Once they are request parameters, Spring will bind them to your command or form objects, and your controllers can once again forget the details of request parsing and focus on business logic. To complete the solution, we need the ParameterizedPathFilter configured as a web filter. It proxies the request with a wrapper class that listens for ParameterizedUrlHandlerMapping’s request attribute. When it is set, the wrapper class adds the parameters to the request parameters for the remaining life of the request.

To configure the ParameterizedPathFitler, add the following to your web.xml:

<filter>
  <filter-name>PathParameterFilter</filter-name>
  <filter-class>carbonfive.spring.web.pathparameter.ParameterizedPathFilter</filter-class>
</filter>
 
<filter-mapping>
  <filter-name>PathParameterFilter</filter-name>
  <url-pattern>/path/to/dispatcher/servlet/*</url-pattern>
</filter-mapping>

You should have a filter mapping for each path pattern mapped to a Spring dispatcher servlet.

That’s all it takes to add this functionality to your webapp. We’ve been using it in our current project. It’s been problem free and the architectural improvements have been satisfying.

Using classpath*: vs. classpath: when loading Spring resources.

I recently resolved a build problem nestled deep within the esoterica of spring resource loading. The behavior of classpath: URLs is explained at length in the Spring documentation, but, sadly, this is probably the last place a developer of my disposition would look. The problem (which I describe in more detail beyond the fold) was that we were unable to load hibernate mapping files from our Spring configured integration tests even though they gave us no trouble in our web application. The solution was to replace the “classpath:” prefix of our mappingLocation URI with “classpath*:”.

In this project, we are storing our Hibernate mapping files as separate files located in the package of the class they map (i.e. “Foo.hbm.xml” stored in “src/main/java/com/example/”). We inherited the persisted classes and Hibernate and Spring configuration from another project. The sessionFactory configuration in spring specified the mappingLocations as “classpath:**/*.hbm.xml” which worked fine when we deployed the web application.

We soon ran into problems when we added integration tests to test new DAO functionality. The test configuration was not able to find any hibernate mappings even though we were using the same “classpath:**/*.hbm.xml” URI. After a few hours of hair-pulling and a deep tour of the Spring source, we realized that the problem was that our test Spring configuration was in a different classpath root from the Hibernate mappings, even though both directories were in the test’s classpath.

When you use ‘classpath:’ for an Ant style wildcard search, Spring uses a single classpath directory for the search. The documentation is vague, but it seems the directory returned will be the first one provided by ClassLoader.getResources(“”). In our case, it returned the ‘/target/test-classes’ directory that contains applicationTest.xml and our test classes, instead of ‘/target/classes’ which contains application.xml and all the *.hbm.xml files.

Using the ‘classpath*:’ prefix fixes the problem. It indicates that the resource loader should look in all directories on the classpath, so making this change solved our problem. Apparently Spring maintains both prefixes because limitations in the Classloader (at the specification level) make it difficult to search for resources in the classpath root when performing wildcard searches across all classpath directories. This suggest it might be good practice to always create a directory to contain resources you might otherwise want to put in the classpath root and always use the ‘claspath*:’ prefix.

Flash Remoting Mystery Time

remoting_performance_icon.gifIt seems that there are some strange performance problems when Flex loads lists of data. These problems are alluded to, but not explained in the first of Matt Chotin’s excellent articles on improving remoting performance for large lists. It appears that the time required to load a list increases non-linearly with time. This means that 1 request for a 1000 item list can take much longer than 25 requests for a 40 item list. This is why data paging is a must. I have done some analysis of this problem and have more info, some numbers, and test code below the fold.

One of the first things I noticed when I began investigating the performance of remoted lists is that the delay between the time the load starts and time the data becomes accessible can be broken in to two parts. The first is the time between the remote method call and the result handler of that call. During this time the mouse icon is a spinning clock, but the application is still responsive. Within the result handler all the data from the list seems to be available. The second part of the load happens after the result handler. During this time, the application becomes unresponsive. It is only after this time that any visual changes to the application caused by the new data will appear (though the delay exists even if there is no change to the display). It is this time that exhibits the strange behavior. Since I can’t explain what the application is doing during this time, I’ve dubbed it the mystery time.

My test case involves a simple remote object called TestRemote:

package test;
 
import java.io.*;
import java.util.*;
 
public class TestRemote implements Serializable
{
  public List getObjects(int number, int mapSize, int references)
  {
    List data = new ArrayList();
    Random rnd = new Random();
 
    TestParent parent = new TestParent(Integer.toString(rnd.nextInt()), rnd.nextInt(), "Test Object " + rnd.nextInt(), testMap(mapSize, rnd));
    TestParent parent2 = new TestParent(Integer.toString(rnd.nextInt()), rnd.nextInt(), "Test Object " + rnd.nextInt(), testMap(mapSize, rnd));
    for (int i = 0; i < number; i++)
      data.add(new TestRemotingObject(Integer.toString(rnd.nextInt()), rnd.nextInt(),
                                      "Test Object " + rnd.nextInt(), testMap(mapSize, rnd),
                                      (references > 0 ? parent : null), (references > 1 ? parent2 : null)));
    return data;
  }
 
  private Map testMap(int mapSize, Random rnd)
  {
    Map testData = new HashMap();
    for (int j = 0; j < mapSize; j++)
      testData.put("key" + rnd.nextInt(), "value" + rnd.nextInt());
    return testData;
  }
 
  public static class TestRemotingObject extends TestParent
  {
    public TestParent parent = null;
    public TestParent parent2 = null;
 
    public TestRemotingObject(String id, int number, String name, Map testData, TestParent parent, TestParent parent2)
    {
      super(id, number, name, testData);
      this.parent = parent;
      this.parent2 = parent2;
    }
  }
 
  public static class TestParent
  {
    public String id;
    public int number;
    public String name;
    public Map testData;
 
    public TestParent(String id, int number, String name, Map testData)
    {
      this.id = id;
      this.number = number;
      this.name = name;
      this.testData = testData;
    }
  }
}

and an MXML file with the loading timing and charting logic built in:

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns:tops="*" pageTitle="Test Peformance" backgroundColor="white">
  <mx:Script><![CDATA[
import mx.core.*;
import mx.utils.*;
 
var MAX_ITEM_COUNT = 1000;
var ITEM_COUNT_INCREMENT = 20;
var MAP_SIZE = 10;
var REFERENCES = 0;
 
var timesData : Array = [];
var loadStart : Date;
var loadMiddle : Date;
var itemCount : Number = 0;
 
public function loadData()
{
  if ( loadStart != null )
  {
    var timeNow = new Date();
    timesData.push( { items:itemCount, loadTime:(loadMiddle.getTime() - loadStart.getTime()), mysteryTime:(timeNow.getTime()-loadMiddle.getTime()), cumulativeTime:(timeNow.getTime()-loadStart.getTime()) } );
    timesChart.executeBindings();
  }
 
  itemCount += ITEM_COUNT_INCREMENT;
  if ( itemCount > MAX_ITEM_COUNT ) return;
 
  loadStart = new Date();
  var contentCall = remoteService.getObjects( itemCount, MAP_SIZE, REFERENCES );
  contentCall.resultHandler = Delegate.create(this,function( result )
  {
    trace(result[itemCount - 1].name);
    loadMiddle = new Date();
    doLater(this, "loadData");
  });
}
]]></mx:Script>
  <mx:RemoteObject id="remoteService" named="TestRemote" showBusyCursor="true" concurrency="multiple" result="event.call.resultHandler( event.result );"/>
  <mx:Button label="load" click="loadData();"/>
  <mx:LineChart id="timesChart" marginLeft="5" height="100%" width="100%"
                marginRight="5" dataProvider="{timesData}" showDataTips="true">
    <mx:horizontalAxis><mx:CategoryAxis dataProvider="{timesData}" categoryField="items"/></mx:horizontalAxis>
    <mx:series>
      <mx:Array>
        <mx:LineSeries yField="loadTime" form="curve" name="Load Time"/>
        <mx:LineSeries yField="mysteryTime" form="curve" name="Mystery Time"/>
        <mx:LineSeries yField="cumulativeTime" form="curve" name="Cumulative Time"/>
      </mx:Array>
    </mx:series>
  </mx:LineChart>
  <mx:Legend dataProvider="timesChart" direction="horizontal"/>
</mx:Application>

The loadData() function of this MXML file is a little strange. The mystery time only occurs after the remote call’s result handler has completed execution, so we need to time between the end of the method and then next time we can execute code. It turns out that Flash’s doLater() method makes this easy. It executes the given method during the next frame of the flash movie, and the mystery time must complete before the next frame is drawn/executed. So the loadData() function records the time since the last call started, increments the item count (and stops if its reached the limit), calls the remote method, and assingns a result handler that will restart the loop by calling loadData() in a doLater() function.

remoting_performance_2_10.gifArmed with this code, we can begin analysing the mystery time. I ran many tests with different item counts, map sizes, and object references, but this graph seems to say most everything that I can say with any confidence about the problem. The load time is the time between the remote call and the result handler. It increases linearly with list size as we’d expect (bigger list size = bigger download = increased time). Remember that the result of the remote call is fully available at the end of the load time, so this curve represents the request to the server, the server call itself, the serialization to a remoting response, the streaming of that response, and (it appears) the deserialization of that response into Actionscript objects.

The mystery time is the time between the call to the result handler and the display refresh (measured as the time between the result handler and the next frame). It’s a little difficult to see, but there’s a slight increase in slope at around 15 to 30 items. You can also see that after around 60 items, the mystery time provides the majority of the delay between the the remote request and the response to the user.

In this graph, the mystery time has a spike at around 188 items. That’s common, the peaks sometimes appear in the load time as well. It could be many things, including garbage collection in the flash player, garbage collection in the app server (since I’m running it on the same machine), or an entirely separate process. At any rate, I’m ignoring the spikes.

The most interesting curve is the time per 100 items. If the cumumlative time were linear, this curve would be a horizontal line. As you can see, it starts high and quickly decreases to a minimum. This accounts for the overhead involved in making many many small requests as opposed to a single larger one. The minimum of this curve it the ideal (or at least fastest) paging size. Unfortunately, it isn’t consistent across tests, even with the same parameters. It ranges from about 20 to 60, but is usually on the low side. Between 50 and 100 items, the curve rises quickly, meaning the performance for the high side of 100 items is much worse than on the low side. It’s not so easy to see in this graph, but the curve continues to rise gradually after 100, but slope seems to diminish as the item count continues to rise.

remoting_performance_map.gifA curiosity of the mystery time, is that it seems to be nearly invariant over the size of the objects in the list. In this test, the item count was kept constant at 100 as the size of the map in each object was incremented. The load time increases linearly as we’d expect, but the mystery time increases only slightly between 0 and 25 map entries, and then remains constant. I’ve observed this for different types of objects as well.

While the mystery time does not depend on the size of the objects, it does seem to depend on the structure of the object graph. Specifically, references to parent objects (i.e. each object in the list referencing a single instance of a container object) seems to increase the mystery time well out of proportion to the actual number of items (N+1) when the item count is high (>> 100). Since we’ve already established that the page size needs to be < 100, I'm not going to elaborate on this oddity.

The conclusions are: 1) the mystery time takes a significant if not dominant proportion of the total request time, 2) The mystery time increases non-linearly with respect to list size and remains constant with respect to object instance size, and 3) optimum paging size seems to be between 20 and 50. I’m at a loss to explain what the mystery time is. It’s doesn’t seem to be deserialization because the content is available before the mystery time starts. It may be garbage collection, but it seems far to predictable for any garbage collection scheme I know of. At any rate, I’d love to hear some theories about what’s going on here.