Search This Blog

Friday, October 30, 2009

Flex: How to create a different rollover color for the header in a datagrid component?

Update 01-02-2010: Monkey patching the Flex framework does not work when RSL's are used. This is because the code of the RSL is loaded in the first frame wether the monkey patched code is instantiated in the second frame and hence does not override the RSL classes. This can be solved by instantiating the monkey patched class in a custom preloader as described here. Depending on the size of the included classes, this can invalidate the choice to use RSL's in the first place, namely to reduce application size. To include the monkey patched class in a custom preloader depends solely on the patch itself and the increased download size. These two factors should be taken into account.


In my current project I have the following requirement for styling a DataGrid component:

The roll-over color of the header should be of a different color than the roll-over color of the datagrid rows. To make things even more interesting, the roll-over color must be a gradient instead of a solid color.

Unfortunately there is no easy way to accomplish this. We can set the default background color of the header with the headerColors style, but this color is overwritten when the mouse hovers over the header. We can also disable the rollover highlighting with the useRollOver property but this does not prevent from changing the rollover color of the header! Even if we could disable the header rollover color this way, it is not a solution because we want a different rollover color for the header and the rows containing the data.

After some digging in the Flex SDK source code, the solution I came up with is to provide a customized DataGridHeader class. Please note that I customized the Flex 3.2.0 SDK because I use the 3.2.0 SDK. If you use the Flex 3.4.0 SDK you should modify the DataGridHeader class of the 3.4.0 SDK instead. To customize the DataGridHeader class I did the following:
  1. Created a mx.controls.dataGridClasses package in my own source folder
  2. Copied the DataGridHeader.as file from the Flex 3.2.0 SDK to my own mx.controls.dataGridClasses package
  3. Located the mouseOver- and mouseDownHandlers and replaced the drawHeaderIndicator method with my own drawGradientBackGround method.
  4. Added two new style attributes to the DataGridHeader class, named: startColor and endColor which defines the start- and endcolor of the gradient fill. These attributes are queried in the drawGradientBackGround method. For simplicity I did not provide default values so the default color is black.
  5. Declared the startColor and endColor attributes in css and gave them a color value.
A full working example can be downloaded from http://code.google.com/p/jc-examples/ as a zip file or from the svn repository. The following picture is taken from the sample project which demonstrates the gradient header color when the mouse is over the header. The mouse is over the name column in this case. Please note that this example uses the Flex 3.2.0 SDK.


If there are more straightforward solutions to this problem please share them.

Resources

Saturday, October 3, 2009

To inject or not to inject

Last week I was a couple of days at a client to look at some strange behavior in the application. The application was a calculator used by clients of the company to calculate services the client offers. The application was written in Java6 and used Tapestry for the view and a Spring/Hibernate/AspectJ combination for the backend which talked against an Oracle database. Tomcat was used as the runtime container for the application.

The first problem that had to be tackled was that sometimes the dependency injection did not work properly. Sometimes dependencies were injected, and other times not. When I looked at the application I noticed that an aspect was responsible for injecting repositories into domain objects. As soon as a domain object is deserialized or instantiated, the AnnotationBeanConfigurerAspect injected the repository. At least that was the intention. But the injection did not always take place. I further discovered that load-time weaving was used to inject the aspect’s behavior. I looked at the configuration and did not see anything that was wrong. The proper class loader in Tomcat was used and the necessary Spring configuration was present. What was causing this awkward behavior? Because time was limited I decided to switch to compile-time weaving. We compiled the classes with the AspectJ compiler and redeployed the application. This time the dependency injection was working as expected. We did not further investigate why load-time weaving did not work properly. If you have any suggestions please mention them.

The second problem was that after a specific amount of inactivity at the application side, the application crashed when it was first accessed. The stack trace revealed that it was a problem with the underlying database connection. The message indicated that the connection was already closed. What was happening was that Oracle closes all idle connections after a specific amount of time, in our case 30 minutes. This is configured in the sqlnet.ora file with a parameter called sqlnet.expire. To overcome this, we added the following configuration to the Commons DBCP connection pool:

testOnBorrow=true

validationQuery=SELECT 1 FROM DUAL

The result of this configuration is that all connections returned from the pool are first tested with the specified validation query. If the test fails the connection is discarded from the pool and a new one is returned. This solved our problem. I must mention that this configuration can have a negative impact on performance because every returned connection is checked for validity. Because of this, the simplest Oracle query is used to test the connection. Since the application did not have many concurrent transactions, this setting was acceptable.

If performance is an issue, I would recommend using an eviction strategy where a specified eviction policy periodically checks all idle connections for validity. See the Commons DBCP configuration guide for an explanation to configure this.

I hope some of you may find these solutions helpful in your own projects.