Fat Spring Clients

If you were expecting something about obesity and pogo sticks you’ve come to the wrong place. Try google for that kind of stuff. 🙂

If you want to hear about my experience building a Java Swing GUI application with Spring then please carry on…

I’ve been using Spring for a few months now and have grown to love it and the I.O.C.model. However up until a few days ago my experience with it had only been in the context of building a web application.

Recently our team has been developing a fat client (Swing) application that connects to a remote server, authenticates and downloads reports from time to time. The application is going to used around the world by possibly thousands of clients and needs to be totally localisable. Our initial implementation started out with a mainline class which created all the JFrames, JButtons, JWhatevers and wired them all up with listeners yada, yada, yada. Then we got to thinking, “Why not use Spring here?”. It required a bit of a paradigm shift in our thinking but after going through the exercise I’m really happy with the results. Essentially the mainline class does nothing but set up the Spring container, lookup the main GUI class and run it. Here’s the main class:

public class MainLine {
  public static void main(String[] args) {
    ApplicationContext springContext = new ClassPathXmlApplicationContext("classpath*:applicationContext-fatClient.xml");
    Gui gui = ((Gui) springContext.getBean("Gui"));
    gui.run();
  }
}

The fat client consists of a main window (actually a system tray icon), a configuration dialog, a menu and a number of web service clients that communicate back the server. By using Spring we were able to inject the various components into the main Gui class rather than have it instantiate the various components. Here’s what the spring configuration looks like:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	     xmlns:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

	<bean id="MessageSource"
			class="org.springframework.context.support.ResourceBundleMessageSource">
	    <property name="basenames">
		  <list>
				<value>Gui</value>
				<value>Dialog</value>
		  </list>
		</property>
	</bean>

	<bean id="ConfigurationDialog" class="ca.intelliware.swing.ConfigurationDialog">
		<property name="messageSource" ref="MessageSource" />
	</bean>

	<bean id="Gui" class="ca.intelliware.swing.Gui">
		<property name="messageSource" ref="MessageSource" />
		<property name="configurationDialog" ref="ConfigurationDialog" />
		<property name="pingWebService" ref="PingWebService" />
		<property name="someOtherWebService" ref="SomeOtherWebService" />
	</bean>

	<!-- ========================= WebServiceClient DEFINITIONS ======================== -->
	<bean id="PingWebService" class="ca.intelliware.webservice.PingWebService">
	</bean>

	<bean id="SomeOtherWebService" class="ca.intelliware.webservice.SomeOtherWebService">
	</bean>

</beans>

The result of this was that we now have an application that we were able reap the benefits of dependency injection (easy testing, separation of concerns, loose coupling, encapsulation etc.) in a fat client. Being able to inject the MessageSource into beans as needed makes localisation a snap.

Also, I’ve always found that testing GUI code can be difficult at best but in this case it’s been much easier. At lease we’ve been able to test the webservice clients without having to worry about mocking out GUI components.

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply