advertisement
javaboutique
Search Tips
Articles  |   Tutorials  |   Reviews  |   Tools  |   by Category  |   by Date  |   by Name  |   Submit  |   Source  |   Forums  |  
javaboutique
Browse DevX


Partners & Affiliates











advertisement

Tutorials : Add Object Caching Using Spring, AOP, and Ehcache :

 

The Problem

The first thing you need to do is retrieve all your ATM data from an external system through a network. This sounds simple and vague at the same time. To complicate matters, add that your application needs access to this data frequently throughout any given day. You might be saying: "That's not a problem." Which it wouldn't be in cases where the network traffic is low but, when traffic increases it could take anywhere from 10 to 30 seconds to retrieve this data. Requiring end-users to wait 10 or more seconds for a page or dialog to load is simply unacceptable and will eventually result in a poor perception of the application. User perception is everything, right? Tasks that appear to be doing something by showing progress indicators or animations are more likely to be perceived by the end-user as quicker during long-running tasks. Leaving users in the dark regarding what is going on with the application is simply asking for trouble. If a user has to assume that the application is doing something, nine times out of 10, they'll try to re-invoke the same operation thus, causing an even longer wait not only for themselves and for other users. You'll need to account for this while designing the ATM locator system; making calls to the external system is the most critical function to address.

Addressing this problem, the example application uses a data caching approach. This works in most cases—however, like anything in software development, you should gain a full understanding of the data your application will read and/or write. It's important that you know what questions to ask when dealing with another business' data. When considering whether or not you can cache data, first ask: how much data is there and how often does it get updated? Obviously this is an incomplete list of questions to ask. But for the ATM locator service it is just enough information to move forward with development.

There's a popular saying in the XP community: "Build just enough and not much more." This means that when you're developing a service, you build the core first and then implement solutions when problems arise. This is the strategy employed here.

Take a look at the domain model in Figure 1. This shows the service's data requirements.


Figure 1. Domain Model

The core of this service is the AtmDao interface, shown below in its entirety:

package jbriscoe.article.spring.caching.dao;
import java.util.Set;
import jbriscoe.article.spring.caching.model.Atm;

public interface AtmDao {
	public Set<Atm> getAllAtms() throws Exception;
}
Designing to an interface allows you to scale the application to different areas of need in the future with minimal code change. In this example, the AtmDao interface is implemented with a static spring managed class, shown in Listing 1.

Pretty simple, huh? The real code for accessing an external system is outside the scope of this article. What is important is that you have a long-running method. In this case, the method is always going to run at least 10000 milliseconds, or 10 seconds, caused by the Thread.sleep(..) static method call. The ATM set is injected into the class by the Spring Framework at application context startup. The following is a snippet from the amtlocator-atms-beans.xml file (see Listing 2).

Click here to see the entire atmlocator-atms-beans.xml file.

Once you have your static data beans defined in Spring, the next step is to add an instance of the AtmDao implementation. The atmlocator-core-beans.xml file contains all core service beans, but, at this point, you only need to add the atmDao bean:

<bean id="atmDao"
 class="jbriscoe.article.spring.caching.dao.impl.StaticAtmDaoImpl">
  <property name="atms" ref="atms" />
</bean>
For those of you new to Spring, the ref attribute in the atms property simply means "Find a bean named atms in any xml context file." Now that you've got some actual code, it's time to run a test. The Spring framework makes it very easy to unit test your beans. And testing them within Spring allows you to verify that they are integrated properly and perform as expected.

I prefer to build an abstract base class named AbstractSpringTest for Spring test cases. This class will typically extend the Spring-provided org.springframework.test.AbstractDependencyInjectionSpringContextTests class. By extending this class, you can allow your test cases to participate in dependency injection. The new AbstractSpringTest class should look like this:

package jbriscoe.article.spring.caching;
import jbriscoe.article.spring.caching.dao.AtmDao;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

public abstract class AbstractSpringTest extends
		AbstractDependencyInjectionSpringContextTests {

  protected AtmDao atmDao;

  public AbstractSpringTest() {
    setPopulateProtectedVariables(true);
  }
  @Override
  protected String[] getConfigLocations() {
   return new String[] {
"classpath:jbriscoe/article/spring/caching/atmlocator-core-beans.xml",
"classpath:jbriscoe/article/spring/caching/atmlocator-atms-beans.xml"   };
  }
}
Notice that the atmDao field is protected in the AbstractSpringTest class. Also, a call has been added to setPopulateProtectedVariables(true) within the constructor. This removes the need for getters and setters within this class. This method could be substituted by a private atmDao with a matching setter within this class. That would have worked in just the same way. The getConfigLocations() method simply tells the Spring test class what beans files are to be included within your application context.

The next step is to create an actual test case that extends from the class you just built making a call to the AtmDao implementation. The implementation of the test case for getting all of the ATM objects is relatively simple and should look like Listing 3.

For those of you that noticed, Listing 3 calls the getAllAtms method twice in the larger method. This will come in handy later, when you want to test the performance of the method on subsequent calls (as will be made clearer in a moment). Once you have your unit test built, go ahead and run the test. Your test results, barring any compile errors, should pass successfully and look similar to the following test output:

INFO  AbstractSingleSpringContextTests - Loading context for:
classpath:jbriscoe/article/spring/caching/atmlocator-core-beans.xml,
classpath:jbriscoe/article/spring/caching/atmlocator-atms-beans.xml
INFO  StaticAtmDaoImpl - Actually performing all atms lookup.
INFO  StaticAtmDaoImpl - Actually performing all atms lookup.
This unit test is slow, but how slow? To find out, you'll build a spring AOP interceptor that will time the method call execution from start to finish. It's always good to reuse existing code, so the interceptor will use the commons-lang StopWatch class for all timing needs. Listing 4 is the implementation of the method execution timer interceptor.

The method interceptor works like this: you create a new instance of StopWatch, then start the timer. Next, execute the method that you're timing and log the results for analysis. Now that you've got an interceptor, you need to register it with Spring for use. Add the following beans in atmlocator-core-beans.xml:

<aop:config>
 <aop:pointcut id="getAllAtmsPointcut"
	expression="execution(* *..StaticAtmDaoImpl.getAllAtms())" />
 <aop:advisor id="methodTimingAdvisor"
  advice-ref="methodTimingAdvice" pointcut-ref="getAllAtmsPointcut" />
</aop:config>

<bean id="methodTimingAdvice"
class="jbriscoe.article.spring.caching.interceptor.MethodTimingInterceptor" />
Before you run the test, there are few new beans worth discussing:
  • methodTimingAdvice interceptor: This bean will simply be instantiated once and then you'll use the reference to apply with a given pointcut.
  • pointcut: This bean is a simple expression that communicates your desire to attach method timing to a class called StaticAtmDaoImpl with a method called getAllAtms—with no arguments.
  • advisor: This bean simply joins the pointcut and interceptor so they can be applied within the ATM locator service.
Go ahead and run the test case. You should receive the following log output:
INFO  AbstractSingleSpringContextTests - Loading context for:
classpath:jbriscoe/article/spring/caching/atmlocator-core-beans.xml,
classpath:jbriscoe/article/spring/caching/atmlocator-atms-beans.xml
INFO  StaticAtmDaoImpl - Actually performing all atms lookup.
INFO  MethodTimingInterceptor - Method Invocation
[jbriscoe.article.spring.caching.dao.impl.StaticAtmDaoImpl.getAllAtms] Total Time:
10(seconds) 10000(millis)
INFO  StaticAtmDaoImpl - Actually performing all atms lookup.
INFO  MethodTimingInterceptor - Method Invocation
[jbriscoe.article.spring.caching.dao.impl.StaticAtmDaoImpl.getAllAtms] Total Time:
10(seconds) 10000(millis)
No real surprises with the test results. The getAllAtms method takes 10 seconds each and every time. So it's clear: you need to improve this method's performance!

Keep in mind that this method has been deliberately slowed down—this could very well have been a real call to an external system that took 10 seconds to complete!

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.

 DevX Skillbuilding from IBM developerWorks
 RIA Run Contest: Build Next-Gen Apps in Microsoft Silverlight 2
 Avaya DevConnect Center
 Intel Go Parallel Portal
 Internet.com eBook Library
 Microsoft RIA Development Center
 Destination .NET
XML error: not well-formed (invalid token) at line 53
advertisement
Receive Articles via our XML/RSS feed
Receive Articles via our XML/RSS feed

JavaBytes
Internet Cyclone
This powerful, easy-to-use, internet optimizer is for Windows 95, 98, ME, NT, 2000 and XP. It's designed to automatically optimize your Windows settings, boosting your Internet connection up to 200%.

SaaS Tool Offers Custom Database Development
Microsoft’s Automated Agent: Can We Talk?
Borland Finally Sells CodeGear
Red Hat Heads For The JON 2.0
Out with the Old, in with the New at JavaOne
Trolltech Expands WebKit Footprint
Oracle: Eating its Own Open Source Food
Big Money and Open Source May Not Compute
Open Source Embrace Gives Sun New Fans
NetBeans, OpenSolaris Also in Spotlight at JavaOne

Taming Trees: Building Branching Structures
Clean Up Function Syntax Mess with decltype
Sutter Speaks: The Future of Concurrency
INTEL SCAVENGER HUNT, LENOVO X300 AND APPLE IPOD TOUCH GIVEAWAY (the "Giveaway")
Comparing Multi-Core Processors for Server Virtualization
Intel® Desktop Business Computing Solutions
Intel: What Downturn?
Managing the Evolving Data Center
Implement Drag and Drop in Your Windows Forms Applications
Processing Linked Web Data with XSLT

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map  |   Network Map  |   About



JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
Microsoft Article: HyperV-The Killer Feature in WinServer ‘08
Avaya Article: How to Feed Data into the Avaya Event Processor
Microsoft Article: Install What You Need with Win Server ‘08
HP eBook: Putting the Green into IT
Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
Avaya Article: Setting Up a SIP A/S Development Environment
IBM Article: How Cool Is Your Data Center?
Microsoft Article: Managing Virtual Machines with Microsoft System Center
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Intel Video: Are Multi-core Processors Here to Stay?
On-Demand Webcast: Five Virtualization Trends to Watch
HP Video: Page Cost Calculator
Intel Video: APIs for Parallel Programming
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Sun Download: Solaris 8 Migration Assistant
Sybase Download: SQL Anywhere Developer Edition
Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
Red Gate Download: SQL Compare Pro 6
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
IBM Article: Collaborating in the High-Performance Workplace
HP Demo: StorageWorks EVA4400
Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES