Monday, 22 April 2013

Spring AOP Tutorial

Introduction
Application logic can be broken into 2 distinct areas, core business logic and cross cutting concerns. Business logic is code written to satisfy a functional requirement, while a cross cutting concern is 'utility' logic that is agnostic to any specific business process and required by many parts of the application. Examples include logging, transaction management, performance monitoring and security. While none of these address a functional requirement, they remain fundamental parts of the application runtime.

Cross cutting concerns present 2 main challenges.
  1. They tend to be 'scattered' across the application which can lead to considerable duplicate code. Logging or performance monitoring is a good example. 
  2. They become tangled with application business logic and result in code that is difficult to maintain because there is no clear Separation of Concerns.  
Aspect Oriented Programming (AOP) aims to address these challenges by providing a means of modularising application logic, so that each module addresses a distinct concern. Take performance monitoring as an example - rather than have performance monitoring logic littered across the application, AOP provides a means of modularising this logic, and applying it to various parts of the application at runtime. This provides a clear Separation of Concerns as performance monitoring logic is no longer tangled with business logic throughout the application.

Key Terms
The detailed inner workings of AOP is well beyond the scope of this post. However, I've provided a brief definition of key terms that are referred to throughout this tutorial.

Aspect - A self contained module that attempts to address a specific cross cutting concern. In this tutorial  the Aspect will contain performance monitoring functionality.
Advice - Logic that is invoked at a specific point in a programs execution.
Join Point - A specific point in a programs execution where advice is applied. Note that advice can be applied before and after a Join Point.
Pointcut - An expression that identifies Join Points matching certain criteria. For example we can define a Pointcut that identifies all public methods in a package. These specific points in program execution (JoinPoints) have advice applied to them at runtime.    

How does it work?
If Advice (performance monitoring logic in this case) is completely separate from the business logic, how is it actually called? AOP takes care of this at runtime by wrapping the target object inside a proxy. The proxy intercepts incoming requests to the target object and calls the performance monitor 'utility' logic before it calls the target object. The proxy can also invoke utility logic after the target object has been called. Figure 1.0 below shows the steps involved.

Figure 1.0 - AOP Proxy
Sample Code
This sample code described in this tutorial will demonstrate some of Springs AOP capabilities by showing you how to build a simple performance monitor. Springs AOP support can be set up with either XML configuration or annotations. The XML approach is typically used in older applications running Spring 2.5, whereas newer applications running Spring 3.X typically use annotations. For completeness this tutorial will cover both approaches.

Project Structure
I've create 2 separate projects, one using XML configuration and one using annotations. The project structure is identical for both - the only difference is the configuration. To keep things simple both applications will be kicked off via a main method and call a simple Service. We'll then use AOP to apply performance monitoring to the service call. The structure of both projects is shown below.
Figure 2.0 - Project Structure

I'll start off by explaining the components that are identical in both the XML and annotation driven approaches. Then I'll move on to explaining the configuration specific to each approach. Full source code for both projects will be available to download at the bottom of this post.    

Service Interface
CalculationService.java is an interface that defines the simple service method shown below. Note that programming to interfaces is regarded as good practice, but has even more significance when using Springs AOP support. In order for Spring to use the dynamic proxy approach described earlier (see figure 1.0), it is expected that the target object (CalculationServiceImpl in this case) implements an interface. Its also possible to use AOP on a class that doesn't implement an interface. In this case CGLIB is used to proxy the target object.
1:  package com.blog.samples.aop;  
2:    
3:  /**  
4:   * Dummy service interface  
5:   *  
6:   */  
7:  public interface CalculationService  
8:  {  
9:       /**  
10:        * A dummy method  
11:        *  
12:        * @param employee_p  
13:        * @return  
14:        */  
15:       public void dummyServiceMethod();  
16:  }  

Service Implementation
CalculationServiceImpl.java implements the service interface defined above. The dummyServiceMethod simply logs a message and calls the randomSleep method to sleep the current thread for a random period of time. This allows us to simulate varying response times from the service method which will useful for testing our performance monitor later.
1:  package com.blog.samples.aop;  
2:    
3:  import org.apache.log4j.Logger;  
4:    
5:  /**  
6:   * Dummy service calculates implementation implements dummyServiceMethod.  
7:   *  
8:   */  
9:  public class CalculationServiceImpl implements CalculationService  
10:  {  
11:       private static final Logger logger_c = Logger.getLogger(CalculationServiceImpl.class);  
12:    
13:       /**  
14:        * dummyServiceMethod simply logs a message and calls randomSleep to  
15:        * sleep the current thread for a random period of time. This allows us  
16:        * to simulate varying response times from the service method which is  
17:        * useful for testing our performance monitor  
18:        *  
19:        * @param employee_p  
20:        * @return  
21:        */  
22:       public void dummyServiceMethod()  
23:       {  
24:            logger_c.debug("Doing some service stuff here...");  
25:    
26:            /* Sleep thread for random period so as to vary service execution time */  
27:            randomSleep();  
28:       }  
29:    
30:       /**  
31:        * Sleep thread for random period  
32:        */  
33:       private void randomSleep()  
34:       {  
35:            try  
36:            {  
37:                 Thread.sleep((long)(Math.random() * 1000));  
38:            }  
39:            catch (InterruptedException ie_p)  
40:            {  
41:                 logger_c.error("Error occurred sleeping thread", ie_p);  
42:            }  
43:       }  
44:  }  

Test Harness
RunTest.java uses a main method to load the Spring configuration and invokes the test service 50 times. We call the service 50 times as it helps demonstrate some of the statistics that can be gathered by the performance monitor defined later.
1:  package com.blog.samples.aop;  
2:    
3:  import org.apache.log4j.Logger;  
4:  import org.springframework.context.support.ClassPathXmlApplicationContext;  
5:    
6:  public class RunTest  
7:  {  
8:       private static final Logger logger_c = Logger.getLogger(RunTest.class);  
9:    
10:       public static void main (String [] args)  
11:       {  
12:            logger_c.debug("loading spring application context");  
13:            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");  
14:    
15:            /* get been from application context */  
16:            CalculationService calculationService = (CalculationService)applicationContext.getBean("calculationService");  
17:    
18:            /* call service 50 times so that we can see aggregated performance statistics for service call */  
19:            for(int i=0; i<50; i++)  
20:            {  
21:                 /* invoke dummy service */  
22:                 calculationService.dummyServiceMethod();  
23:            }  
24:    
25:            /* close down spring application context */  
26:            applicationContext.stop();  
27:       }  
28:  }  
Line 13 - load Spring configuration from src/main/resources/spring-config.xml
Line 16 - load calculation service from bean factory
Lines 19 to 23 - invoke calculation service 50 times so that we can gather a variety of metrics using the performance monitor (defined later).

Spring Configuration (XML Approach)
This section will detail the components required to enable AOP using traditional XML configuration. The Calculation Service bean, performance monitor bean and AOP configuration are defined in spring-configuration.xml below.
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <beans xmlns="http://www.springframework.org/schema/beans"  
3:                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4:                xmlns:context="http://www.springframework.org/schema/context"  
5:                xmlns:aop="http://www.springframework.org/schema/aop"  
6:                xsi:schemaLocation="http://www.springframework.org/schema/context  
7:                                    http://www.springframework.org/schema/context/spring-context-2.5.xsd  
8:                                    http://www.springframework.org/schema/beans  
9:                                    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
10:                                   http://www.springframework.org/schema/aop  
11:                                   http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
12:    
13:    
14:       <!-- Calculation Service bean definition - this is the bean that we want to monitor performance on -->  
15:       <bean id="calculationService" class="com.blog.samples.aop.CalculationServiceImpl" />  
16:    
17:    <!-- ================================================================== -->  
18:    <!--         A O P C O N F I G B E A N S                        -->  
19:    <!-- ================================================================== -->  
20:    
21:      <!-- Performance Monitor bean definition - this bean contains performance monitoring logic  
22:           like starting and stopping the monitoring, logging statistics etc -->  
23:      <bean id="performanceMonitor" class="com.blog.samples.aop.PerformanceMonitor" />  
24:    
25:      <!-- AOP configuration -->  
26:      <aop:config>  
27:    
28:        <!-- Name of the Aspect we're defining -->  
29:        <aop:aspect ref="performanceMonitor">  
30:    
31:          <!--  
32:            the Pointcut expression specifies where the advice (performance monitoring code) will  
33:            be applied. Pointcut expressions are very flexible and can be as specific or as generic  
34:            as you like. In this instance we configured the Pointcut expression so that it covers  
35:            all methods in the com.blog.samples.aop.CalculationService class. However, we could  
36:            have configured it so that advice is only applied to a single Service method, or even  
37:            opened it up to all classes within the com.blog.samples.aop package. Obviously this  
38:            level of flexibility isn't required for our trivial example, but is very useful in  
39:            large enterprise applications.  
40:           -->  
41:          <aop:pointcut  
42:               id="serviceMethod"  
43:               expression="execution(* com.blog.samples.aop.CalculationService.*(..))"/>  
44:    
45:          <!--  
46:               <aop:before ... /> is used to specify the advice that should be run before a Pointcut  
47:               method - invoke the startMonitor method to start timing method execution before the Pointcut  
48:               pointcut-ref - the point cut reference specifies the point of execution in the code where the  
49:                              advice should be run. In this case its before any public method in the  
50:                              Calculation Service.  
51:          -->  
52:          <aop:before  
53:               method="startMonitor"  
54:               pointcut-ref="serviceMethod"/>  
55:    
56:          <!--  
57:               <aop:after ... /> is used to specify the advice that should be run after a Pointcut  
58:               method - invoke the stopMonitor method to stop timing method execution after the Pointcut  
59:               pointcut-ref - the point cut reference specifies the point of execution in the code where the  
60:                              advice should be run. In this case its after any public method in the  
61:                              Calculation Service.  
62:          -->  
63:          <aop:after  
64:               method="stopMonitor"  
65:               pointcut-ref="serviceMethod"/>  
66:    
67:          <!--  
68:               method - invoke the log method to log method execution metrics after the Pointcut  
69:               pointcut-ref - the point cut reference specifies the point of execution in the code where the  
70:                              advice should be run. In this case its after any public method in the  
71:                              Calculation Service.  
72:          -->  
73:          <aop:after  
74:               method="log"  
75:               pointcut-ref="serviceMethod"/>  
76:    
77:          <!--  
78:               <aop:after-throwing ... /> is used to define the advice to be run after an exception is thrown at a Pointcut.  
79:               method - invoke the stopMonitor method to stop timing method execution after an exception is thrown at the Pointcut  
80:               pointcut-ref - the point cut reference specifies the point of execution in the code where the  
81:                              advice should be run. In this case its after any public method in the  
82:                              Calculation Service.  
83:          -->  
84:          <aop:after-throwing  
85:               method="stopMonitor"  
86:               pointcut-ref="serviceMethod"/>  
87:    
88:          <!--  
89:               method - invoke the log method to stop timing method execution after an exception is thrown at the Pointcut  
90:               pointcut-ref - the point cut reference specifies the point of execution in the code where the  
91:                              advice should be run. In this case its after any public method in the  
92:                              Calculation Service.  
93:          -->  
94:          <aop:after-throwing  
95:               method="log"  
96:               pointcut-ref="serviceMethod"/>  
97:    
98:        </aop:aspect>  
99:      </aop:config>  
100:    
101:    <!-- ***************************** -->  
102:    
103:  </beans>  

Performance Monitor (XML Configuration Approach)
The AOP configuration above uses a PerformanceMonitor class to apply advice at specified Pointcucts. The class is defined below and uses the JAMon API to provide basic performance monitoring functionality to captures and log performance metrics.
1:  package com.blog.samples.aop;  
2:    
3:  import java.util.Date;  
4:  import org.aspectj.lang.JoinPoint;  
5:  import org.apache.log4j.Logger;  
6:  import com.jamonapi.Monitor;  
7:  import com.jamonapi.MonitorFactory;  
8:    
9:  /**  
10:   * Performance monitor use the Jamon library to provide basic performance  
11:   * monitoring and logging functionality.  
12:   *  
13:   */  
14:  public class PerformanceMonitor  
15:  {  
16:       private static final Logger logger_c = Logger.getLogger(PerformanceMonitor.class);  
17:       private final String MONITOR = "PERFORMANCE_MONITOR";  
18:       private Monitor monitor_i;  
19:    
20:       /**  
21:        * Start monitor  
22:        */  
23:       public void startMonitor()  
24:       {  
25:            monitor_i = MonitorFactory.start(MONITOR);  
26:       }  
27:    
28:       /**  
29:        * Stop monitor  
30:        */  
31:       public void stopMonitor()  
32:       {  
33:            monitor_i.stop();  
34:       }  
35:    
36:       /**  
37:        * get last access  
38:        *  
39:        * @return Date  
40:        */  
41:       public Date getLastAccess()  
42:       {  
43:            return monitor_i.getLastAccess();  
44:       }  
45:    
46:       /**  
47:        * get call count  
48:        *  
49:        * @return int  
50:        */  
51:       public int getCallCount()  
52:       {  
53:            return (int) monitor_i.getHits();  
54:       }  
55:    
56:       /**  
57:        * get average call time  
58:        *  
59:        * @return double  
60:        */  
61:       public double getAverageCallTime()  
62:       {  
63:            return monitor_i.getAvg() / 1000;  
64:       }  
65:    
66:       /**  
67:        * get last call time  
68:        *  
69:        * @return double  
70:        */  
71:       public double getLastCallTime()  
72:       {  
73:            return monitor_i.getLastValue() / 1000;  
74:       }  
75:    
76:       /**  
77:        * get maximum call time  
78:        *  
79:        * @return double  
80:        */  
81:       public double getMaximumCallTime()  
82:       {  
83:            return monitor_i.getMax() / 1000;  
84:       }  
85:    
86:       /**  
87:        * get minimum call time  
88:        *  
89:        * @return double  
90:        */  
91:       public double getMinimumCallTime()  
92:       {  
93:            return monitor_i.getMin() / 1000;  
94:       }  
95:    
96:       /**  
97:        * get total call time  
98:        *  
99:        * @return double  
100:        */  
101:       public double getTotalCallTime()  
102:       {  
103:            return monitor_i.getTotal() / 1000;  
104:       }  
105:    
106:       /**  
107:        * log statistics  
108:        *  
109:        * @param joinPoint_p  
110:        */  
111:       public void log(JoinPoint joinPoint_p)  
112:       {  
113:            StringBuffer sb = new StringBuffer();  
114:    
115:            sb.append("\n");  
116:            sb.append("*======================================");  
117:            sb.append("\n");  
118:            sb.append("*    PERFORMANCE STATISTICS    *");  
119:            sb.append("\n");  
120:            sb.append("*======================================");  
121:            sb.append("\n");  
122:            sb.append("* Method Name: " + joinPoint_p.getSignature().getName());  
123:            sb.append("\n");  
124:            sb.append("* Execution Date: ").append(this.getLastAccess());  
125:            sb.append("\n");  
126:            sb.append("* Last Execution Time: ").append(this.getLastCallTime()).append(" sec");  
127:            sb.append("\n");  
128:            sb.append("* Service Calls: ").append(((this.getCallCount())));  
129:            sb.append("\n");  
130:            sb.append("* Avg Execution Time: ").append(this.getAverageCallTime()).append(" sec");  
131:            sb.append("\n");  
132:            sb.append("* Total Execution TIme: ").append(this.getTotalCallTime()).append(" sec");  
133:            sb.append("\n");  
134:            sb.append("* Min Execution Time: ").append(this.getMinimumCallTime()).append(" sec");  
135:            sb.append("\n");  
136:            sb.append("* Max Execution Time: ").append(this.getMaximumCallTime()).append(" sec");  
137:            sb.append("\n");  
138:            sb.append("*======================================");  
139:    
140:            logger_c.info(sb.toString());  
141:       }  
142:  }  

Line 23 - Method starts monitor. This is called before the service method is invoked.
Line 31 - Method stops monitor. This is called after the service method completes.
Line 41 to 101 - Series of utility methods gather various metrics from the Jamon monitor.
Line 111 - Method logs performance statistics gathered by monitor. The JoinPoint argument provides access to the target object - in this instance we use the JoinPoint to access the name of the target method being invoked.

Spring Configuration (Annotation Driven)
This section shows how AOP can be configured using annotations. You'll notice that this approach is less verbose than the XML approach described earlier. Note that Pointcuts are no longer defined using XML, instead Spring will look for beans annotated with @Aspect and register them as aspects.
1:  <beans xmlns="http://www.springframework.org/schema/beans"  
2:       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
3:       xmlns:aop="http://www.springframework.org/schema/aop"  
4:       xsi:schemaLocation="http://www.springframework.org/schema/beans  
5:                                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
6:                                http://www.springframework.org/schema/aop  
7:                                http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">  
8:    
9:       <!-- this registers beans annotated with @Aspect -->  
10:       <aop:aspectj-autoproxy />  
11:    
12:       <!-- Calculation Service bean definition - this is the bean that we want to monitor performance on -->  
13:       <bean id="calculationService" class="com.blog.samples.aop.CalculationServiceImpl" />  
14:    
15:       <!-- Performance Monitor bean definition - this bean contains performance monitoring logic  
16:            for starting and stopping the monitoring, logging statistics etc -->  
17:       <bean id="performanceMonitor" class="com.blog.samples.aop.PerformanceMonitor" />  
18:    
19:  </beans>  

Performance Monitor (Annotation Driven)
There are a number of significant differences between the Performance monitor defined below, and the one we defined earlier (using the XML approach). Here AOP is configured using class level meta data in the form of annotations.The @Aspect annotation tells Spring that this class contains advice and should be applied to specified Pointcuts at runtime. The Pointcuts are defined using method level annotations and have the same format as the ones defined earlier.
1:  package com.blog.samples.aop;  
2:    
3:  import java.util.Date;  
4:    
5:  import org.aspectj.lang.JoinPoint;  
6:  import org.aspectj.lang.annotation.After;  
7:  import org.aspectj.lang.annotation.Aspect;  
8:  import org.aspectj.lang.annotation.Before;  
9:  import org.apache.log4j.Logger;  
10:    
11:  import com.jamonapi.Monitor;  
12:  import com.jamonapi.MonitorFactory;  
13:    
14:  /*  
15:   * @Aspect tells the Spring framework that this class contains advice that should  
16:   * be applied to one or more specified Pointcuts at runtime  
17:   */  
18:  @Aspect  
19:  public class PerformanceMonitor  
20:  {  
21:       private static final Logger logger_c = Logger.getLogger(PerformanceMonitor.class);  
22:       private final String MONITOR = "PERFORMANCE_MONITOR";  
23:       private Monitor monitor_i;  
24:    
25:       /*  
26:        * @Before tells the Spring framework that this method should be invoked before the specified Pointcut.  
27:        * The Pointcut expression here is identical to the one we used in the XML configuration example  
28:        */  
29:       @Before("execution(* com.blog.samples.aop.CalculationService.dummyServiceMethod())")  
30:       public void startMonitor()  
31:       {  
32:            monitor_i = MonitorFactory.start(MONITOR);  
33:       }  
34:    
35:       /*  
36:        * @After tells the Spring framework that this method should be invoked after the specified Pointcut.  
37:        * The Pointcut expression here is identical to the one we used in the XML configuration example  
38:        */  
39:       @After("execution(* com.blog.samples.aop.CalculationService.dummyServiceMethod())")  
40:       public void stopMonitor()  
41:       {  
42:            monitor_i.stop();  
43:       }  
44:    
45:       /**  
46:        * get last access  
47:        *  
48:        * @return Date  
49:        */  
50:       public Date getLastAccess()  
51:       {  
52:            return monitor_i.getLastAccess();  
53:       }  
54:    
55:       /**  
56:        * get call count  
57:        *  
58:        * @return int  
59:        */  
60:       public int getCallCount()  
61:       {  
62:            return (int) monitor_i.getHits();  
63:       }  
64:    
65:       /**  
66:        * get average call time  
67:        *  
68:        * @return double  
69:        */  
70:       public double getAverageCallTime()  
71:       {  
72:            return monitor_i.getAvg() / 1000;  
73:       }  
74:    
75:       /**  
76:        * get last call time  
77:        *  
78:        * @return double  
79:        */  
80:       public double getLastCallTime()  
81:       {  
82:            return monitor_i.getLastValue() / 1000;  
83:       }  
84:    
85:       /**  
86:        * get maximum call time  
87:        *  
88:        * @return double  
89:        */  
90:       public double getMaximumCallTime()  
91:       {  
92:            return monitor_i.getMax() / 1000;  
93:       }  
94:    
95:       /**  
96:        * get minimum call time  
97:        *  
98:        * @return double  
99:        */  
100:       public double getMinimumCallTime()  
101:       {  
102:            return monitor_i.getMin() / 1000;  
103:       }  
104:    
105:       /**  
106:        * get total call time  
107:        *  
108:        * @return double  
109:        */  
110:       public double getTotalCallTime()  
111:       {  
112:            return monitor_i.getTotal() / 1000;  
113:       }  
114:    
115:       /*  
116:        * @After tells the Spring framework that this method should be invoked after the specified Pointcut.  
117:        * The Pointcut expression here is identical to the one we used in the XML configuration example  
118:        */  
119:       @After("execution(* com.blog.samples.aop.CalculationService.dummyServiceMethod())")  
120:       public void log(JoinPoint joinPoint_p)  
121:       {  
122:            StringBuffer sb = new StringBuffer();  
123:    
124:            sb.append("\n");  
125:            sb.append("*======================================");  
126:            sb.append("\n");  
127:            sb.append("*    PERFORMANCE STATISTICS    *");  
128:            sb.append("\n");  
129:            sb.append("*======================================");  
130:            sb.append("\n");  
131:            sb.append("* Method Name: " + joinPoint_p.getSignature().getName());  
132:            sb.append("\n");  
133:            sb.append("* Execution Date: ").append(this.getLastAccess());  
134:            sb.append("\n");  
135:            sb.append("* Last Execution Time: ").append(this.getLastCallTime()).append(" sec");  
136:            sb.append("\n");  
137:            sb.append("* Service Calls: ").append(((this.getCallCount())));  
138:            sb.append("\n");  
139:            sb.append("* Avg Execution Time: ").append(this.getAverageCallTime()).append(" sec");  
140:            sb.append("\n");  
141:            sb.append("* Total Execution TIme: ").append(this.getTotalCallTime()).append(" sec");  
142:            sb.append("\n");  
143:            sb.append("* Min Execution Time: ").append(this.getMinimumCallTime()).append(" sec");  
144:            sb.append("\n");  
145:            sb.append("* Max Execution Time: ").append(this.getMaximumCallTime()).append(" sec");  
146:            sb.append("\n");  
147:            sb.append("*======================================");  
148:    
149:            logger_c.info(sb.toString());  
150:       }  
151:  }  

Running the Test Harness
At this point I've covered all the various components and explained how AOP can be configured using both XML and annotations. Its time to run the test harness and see the performance monitor at work. Simply kick off the main method in RunTest.java and you should see the Calculation Service invoked 50 times, with performance metrics logged for each call. For brevity the extract below shows the end of the log.
1:  DEBUG: [Apr-16 18:37:12,945] samples.aop.CalculationServiceImpl - Doing some service stuff here...  
2:  INFO : [Apr-16 18:37:13,493] samples.aop.PerformanceMonitor -   
3:  *======================================  
4:  *    PERFORMANCE STATISTICS    *  
5:  *======================================  
6:  * Method Name: dummyServiceMethod  
7:  * Execution Date: Tue Apr 16 18:37:12 BST 2013  
8:  * Last Execution Time: 0.063 sec  
9:  * Service Calls: 49  
10:  * Avg Execution Time: 0.5139387755102041 sec  
11:  * Total Execution TIme: 25.183 sec  
12:  * Min Execution Time: 0.024 sec  
13:  * Max Execution Time: 0.988 sec  
14:  *======================================  
15:  DEBUG: [Apr-16 18:37:13,493] samples.aop.CalculationServiceImpl - Doing some service stuff here...  
16:  INFO : [Apr-16 18:37:14,176] samples.aop.PerformanceMonitor -   
17:  *======================================  
18:  *    PERFORMANCE STATISTICS    *  
19:  *======================================  
20:  * Method Name: dummyServiceMethod  
21:  * Execution Date: Tue Apr 16 18:37:13 BST 2013  
22:  * Last Execution Time: 0.548 sec  
23:  * Service Calls: 50  
24:  * Avg Execution Time: 0.51462 sec  
25:  * Total Execution TIme: 25.731 sec  
26:  * Min Execution Time: 0.024 sec  
27:  * Max Execution Time: 0.988 sec  
Various performance statistics have been logged, including minimum, maximum and average execution times. These metrics were logged every time the service method was invoked, and without adding cross cutting monitoring logic to the Calculation Service.

Summary
This tutorial has demonstrated how AOP can be used to encapsulate a cross cutting concern, apply it to business logic at runtime, and ensure a clear separation of concerns. Although the performance monitor example is trivial, it demonstrates a realistic use case for AOP and could form the basis for a more complete performance monitoring utility. Full source code is available here for the XML and annotation driven approaches, so feel free to download and play around with it. As always, comments or questions are welcome below.

Tuesday, 9 April 2013

jQuery Tables

Introduction
This post will show you how to create rich data grids using the DataTables plugin for jQuery. DataTables is a flexible framework that allows you to create grids using a variety of data sources. This tutorial will show you how DataTables can be used with DOM and JavaScript data sources.

DOM Data Source
The simplest way to use DataTables is with a DOM data source. This approach simply 'decorates' an existing HTML table and is ideal for enhancing plain HTML tables created using template languages like JSP or Velocity.

Make Model Body Shape Engine Size (Cubic Capacity) Horse Power
BMW 320d Saloon 2000 181
BMW 330d Coupe 3000 231
BMW 335d Estate 3000 286
BMW 335i Saloon 3000 306
BMW M3 Coupe 4000 415
BMW 520d Saloon 2000 181
BMW 530d Saloon 3000 231
BMW 535d Estate 3000 286
BMW 535i Saloon 4000 306
BMW M5 Saloon 5000 508

To turn this rather dull looking HTML table into a rich data grid we simply decorate the table on document load.
1:  <script type="text/javascript">  
2:         $(document).ready(function() {  
3:                 $('#sampleGrid').dataTable({        
4:                       "bJQueryUI": true,        
5:                       "iDisplayLength": 4,  
6:                       "sPaginationType": "full_numbers"  
7:                 });            
8:         } );  
9:   </script>  
10:  <table id="sampleGrid">  
11:       <thead>  
12:            <tr>  
13:                 <th>Make</th>  
14:                 <th>Model</th>  
15:                 <th>Body Shape</th>  
16:                 <th>Engine Size (Cubic Capacity)</th>  
17:                 <th>Horse Power</th>  
18:            </tr>  
19:       </thead>  
20:       <tbody>  
21:            <tr>  
22:                 <th>BMW</th>  
23:                 <th>320d</th>  
24:                 <th>Saloon</th>  
25:                 <th>2000</th>  
26:                 <th>181</th>  
27:            </tr>  
28:            <tr>  
29:                 <th>BMW</th>  
30:                 <th>330d</th>  
31:                 <th>Coupe</th>  
32:                 <th>3000</th>  
33:                 <th>231</th>  
34:            </tr>  
35:            <tr>  
36:                 <th>BMW</th>  
37:                 <th>335d</th>  
38:                 <th>Estate</th>  
39:                 <th>3000</th>  
40:                 <th>286</th>  
41:            </tr>  
42:            <tr>  
43:                 <th>BMW</th>  
44:                 <th>335i</th>  
45:                 <th>Saloon</th>  
46:                 <th>3000</th>  
47:                 <th>306</th>  
48:            </tr>  
49:            <tr>  
50:                 <th>BMW</th>  
51:                 <th>M3</th>  
52:                 <th>Coupe</th>  
53:                 <th>4000</th>  
54:                 <th>415</th>  
55:            </tr>  
56:            <tr>  
57:                 <th>BMW</th>  
58:                 <th>520d</th>  
59:                 <th>Saloon</th>  
60:                 <th>2000</th>  
61:                 <th>181</th>  
62:            </tr>  
63:            <tr>  
64:                 <th>BMW</th>  
65:                 <th>530d</th>  
66:                 <th>Saloon</th>  
67:                 <th>3000</th>  
68:                 <th>231</th>  
69:            </tr>  
70:            <tr>  
71:                 <th>BMW</th>  
72:                 <th>535d</th>  
73:                 <th>Estate</th>  
74:                 <th>3000</th>  
75:                 <th>286</th>  
76:            </tr>  
77:            <tr>  
78:                 <th>BMW</th>  
79:                 <th>535i</th>  
80:                 <th>Saloon</th>  
81:                 <th>4000</th>  
82:                 <th>306</th>  
83:            </tr>  
84:            <tr>  
85:                 <th>BMW</th>  
86:                 <th>M5</th>  
87:                 <th>Saloon</th>  
88:                 <th>5000</th>  
89:                 <th>415</th>  
90:            </tr>  
91:       </tbody>  
92:  </table>  
Line 3 - reference the HTML table by id (#sampleGrid) and invoke the DataTables plugin.
Line 4 - apply jQueryUI theme to the grid
Line 5 - set the default number of rows for display.
Line 6 -  set up the pagination control in the footer.
Line 10 to 92 - table definition that we're decorating. Note that the id must be set so that it can be referenced by the plugin on document load)

As you can see below, the resulting data grid is a vast improvement over the plain HTML table and provides some really cool functionality out of the box.

Make Model Body Shape Engine Size (Cubic Capacity) Horse Power
BMW 320d Saloon 2000 181
BMW 330d Coupe 3000 231
BMW 335d Estate 3000 286
BMW 335i Saloon 3000 306
BMW M3 Coupe 4000 415
BMW 520d Saloon 2000 181
BMW 530d Saloon 3000 231
BMW 535d Estate 3000 286
BMW 535i Saloon 4000 306
BMW M5 Saloon 5000 415

JavaScript Array Data Source
DataTables can also be used to create grids declaratively by passing the data as a JavaScript array. This is pretty flexible as it allows you to take data from any source, convert it to a JavaScript array and populate the grid. For example, you might take data keyed by the user or from the server side  and convert it to a JavaScript array, before passing it to the grid. In the sample code below I've hard coded an array of values.
1:  <table id="sampleGridJavaScriptDataSource">  
2:  </table>  
3:  <script type="text/javascript">  
4:         $(document).ready(function() {  
5:                 var someData = [                           
6:                                  [ "Colm", "Toale", "12/04/1981", "Male", "Engineer" ],  
7:                                  [ "Gary", "Gallagher", "12/04/1981", "Male", "Project Manager" ],  
8:                                  [ "Gary", "Jonston", "18/01/1979", "Male", "Doctor" ],  
9:                                  [ "Riain", "McAtamney", "02/07/1985", "Male", "Managing Consultant" ],  
10:                                 [ "Gareth", "Burnside", "07/01/1979", "Male", "Lorry Driver" ],  
11:                                 [ "Connor", "Smyth", "11/03/1986", "Male", "Bank Manager" ],  
12:                                 [ "John", "Flemming", "19/07/1976", "Male", "Accountant" ],  
13:                                 [ "Claire", "Jones", "21/11/1980", "Male", "HR Manager" ],  
14:                                 [ "Sarah", "Nolan", "10/08/1972", "Female", "Receptionist" ],  
15:                                 [ "Steve", "Scott", "27/08/1984", "Male", "Taxi Driver" ]  
16:                               ]  
17:                 $('#sampleGridJavaScriptDataSource').dataTable( {  
18:                      "bJQueryUI": true,        
19:                      "iDisplayLength": 4,  
20:                      "sPaginationType": "full_numbers",  
21:                      "aaData": someData,  
22:                      "aoColumns": [  
23:                           { "sTitle": "Forename" },  
24:                           { "sTitle": "Surname" },  
25:                           { "sTitle": "Date Of Birth" },  
26:                           { "sTitle": "Gender" },  
27:                           { "sTitle": "Occupation" }                           
28:                      ]  
29:                 } );       
30:            } );  
31:  </script>  
Line 1 - Simple HTML table definition with id attribute set
Line 5 to 16 - Hard coded array of values used to populate the grid. In a real application this data would come from another source (user interface, server side etc.)
Line 17 - Define the grid by applying the DataTables plugin to the table skeleton we defined on line 1
Line 18 to 20 - This is the same basic configuration that we applied to our first grid. See DOM data source above.
Line 21 - Pass JavaScript array as data source. In our case this data is hard coded but in a real application it could come from any source.
Line 22 to 27 - Column definitions for the grid. Note that these were not required in the earlier example because we were using an existing HTML table as our data source

Friday, 29 March 2013

jQuery Performance Tips

Introduction
I've been working with jQuery for a while now and I have to say I'm very impressed. It really does live up to the headline, 'write less do more' and allows developers to become productive very quickly. This kind of immediate productivity is great but there is the potential for inexperienced jQuery developers to write code that performs poorly.
This was recently brought to my attention while working on a project where we were targeting IE8. Running on Chrome our application was perfectly responsive, but this was not the case when we switched to IE8. It’s well known that the JavaScript engine used by IE8 is considerably slower than that of the latest generation browsers, but I was still surprised by the difference in performance. The application was noticeably slower and the decreased performance had a significant impact on user experience.
After performing a few code reviews I put together some guidelines to help improve the efficiency of the jQuery we were writing. The changes applied were minimal, but the results were significant and we saw a considerable performance improvement. As a result the application was much more responsive and the user experience improved dramatically. There's nothing ground breaking here, just a few simple guidelines that may help others who are experiencing similar problems with older browsers

Choose the right Selector
jQuery selectors offer a convenient way to get a handle on any DOM element or group of elements. It should be noted though that not all selectors are equal,and choosing the right selector can have a significant impact on performance.

Select By Id
If possible select elements by Id, for example $("#name"). This is efficient because it uses the native DOM function getElementById. An Id is unique on the page and as a result the search ends as soon as the DOM element is found. This is not the case when searching by non unique attributes like class name.

Narrow your Searches
It's not always possible to search by Id and sometimes we need to search by some other type of DOM attribute. A common example is searching by class name as shown below.

var element = $('.myClass');

This is potentially quite expensive, especially in older browsers like IE8 that don't implement the native getElementsByClassName function, and require a full DOM search. For this kind of scenario it makes sense to narrow the search to a subset of the DOM by telling jQuery where to start searching. This improves performance by reducing the amount of DOM that is processed for a given search.
One way of narrowing the search is by specifying a context parameter with our selector - we could update our previous search to specify a starting element as follows.

var element = $('.myClass', someDomElement);

An alternative to context parameters is to use the find() function as shown below

var element = someDomElement.find('.myClass')

Both approaches are equivalent so choosing one is really a matter of personal preference. The important point is, the smaller the specified DOM element the faster the resulting search. Its therefore important to be as specific as possible when using with the Context parameter or find() function.

Cache Selectors
As mentioned above, it’s important to be aware of the overhead associated with using different types of selectors. Even selecting by Id has an associated overhead, so we should minimise where possible. You'll often see code like this

$('#someGrid').dataTable().fnClearTable();
$('#someGrid').dataTable().fnAddData(someData);
$('#someGrid').doSoemthingElse();

Here we've called the same selector 3 times. It would be more efficient to hold a reference to the selected element and work with that reference.

var dataGrid = $('#someGrid');
dataGrid.dataTable().fnClearTable();
dataGrid.dataTable().fnAddData(someData);
dataGrid.doSoemthingElse();


The performance gain using a cached selector in this instance isn't significant because we’re selecting by Id. However, if we had a similar scenario that selected by class name, then the use of a cached selector would see a significant performance improvement. As a general rule of thumb it’s a good idea to use cached selectors wherever you can. Here we can see a performance comparison between cached and non cached selectors.

Method Chaining
Almost all jQuery methods return an object allowing you to conveniently chain method calls. This makes for cleaner more concise code as seen in the examples below.

Rather than writing this...
$('#surname').addClass(".someClass");
$('#surname').css("right","-130px");
$('#surname').css("top","-15px");

We can chain the method calls like this...

$('#surname').addClass(".someClass").css("right","-130px").css("top","-15px");

As well as being cleaner and more concise, method chaining also offers a small performance benefit over individual function calls, especially when combined with cached selectors. Here you can see that method chaining is marginally faster in most cases.

Hopefully the points above will be useful to others experiencing jQuery performance issues. Please feel free to leave a comment below.

Monday, 28 January 2013

Axis2 Web Service Client Tutorial

Introduction
Axis2 is a Java framework that provides comprehensive support for exposing and consuming web services. This short post will look at its SOAP client support and how it can be used to get a simple web service client up and running.
For convenience I'm going to be calling a web service that I recently built as part of another blog post.  If you don't already have a web service to call you can grab the full source code for my sample service from github. Simply run a Maven build and deploy the WAR to your Servlet container.

What is a Web Service Client
This post doesn't attempt to explain the detailed inner workings of a web service client, but its still pretty useful to have an idea of what's going on under the hood. Most web service clients provide the following
  • A client side proxy for the remote service we want to call, that allows our application to invoke a SOAP service using a simple method call. The proxy insulates our application from the intricacies of sending and receiving SOAP messages.
  • Marshalling of Java objects to XML so that application data can be converted to SOAP payloads for posting to the service endpoint.
  • Un-marshalling of XML back into Java objects so that SOAP payloads returned from the remote service can be interpreted by our application.
  • Establishing and pooling HTTP connections between client and and web service.
WSDL2Java
Axis2 provides WSDL2Java tooling that parses a WSDL to generate the client side proxies required to invoke a remote service. WSDL2Java can be run on the command line but I prefer to use a Maven plugin so that I have a fresh set of proxies generated as part of every build.

Maven Configuration
The Maven POM configuration below shows how the axis2-wsdl2code-maven-plugin can be configured to generate the required client side stubs.
1:  <?xml version="1.0"?>  
2:  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  
3:                                      http://maven.apache.org/maven-v4_0_0.xsd">  
4:       <artifactId>axis2-webservice-client-sample</artifactId>  
5:       <modelVersion>4.0.0</modelVersion>  
6:       <inceptionYear>2011</inceptionYear>  
7:       <packaging>jar</packaging>  
8:       <groupId>com.blog.webservices.client</groupId>  
9:       <version>1.0</version>  
10:       <properties>  
11:            <axis2.version>1.6.2</axis2.version>  
12:            <log4j.version>1.2.16</log4j.version>  
13:       </properties>  
14:       <build>  
15:            <resources>  
16:                 <resource>  
17:                      <directory>src/main/resources</directory>  
18:                      <filtering>true</filtering>  
19:                 </resource>  
20:            </resources>  
21:            <plugins>  
22:                 <plugin>  
23:                      <groupId>org.apache.axis2</groupId>  
24:                      <artifactId>axis2-wsdl2code-maven-plugin</artifactId>  
25:                      <version>1.6.2</version>  
26:                      <executions>  
27:                           <execution>  
28:                                <goals>  
29:                                     <goal>wsdl2code</goal>  
30:                                </goals>  
31:                                <configuration>  
32:                                     <wsdlFile>src/main/resources/wsdl/AccountDetailsService.wsdl</wsdlFile>  
33:                                     <databindingName>adb</databindingName>  
34:                                     <packageName>com.blog.webservices.client</packageName>  
35:                                     <outputDirectory>src/main/java</outputDirectory>  
36:                                     <flattenFiles>true</flattenFiles>  
37:                                </configuration>  
38:                           </execution>  
39:                      </executions>  
40:                 </plugin>  
41:                 <plugin>  
42:                      <groupId>org.apache.maven.plugins</groupId>  
43:                      <artifactId>maven-compiler-plugin</artifactId>  
44:                 </plugin>  
45:            </plugins>  
46:       </build>  
47:       <dependencies>  
48:            <dependency>  
49:                 <groupId>org.apache.axis2</groupId>  
50:                 <artifactId>axis2-kernel</artifactId>  
51:                 <version>${axis2.version}</version>  
52:            </dependency>  
53:            <dependency>  
54:                 <groupId>org.apache.axis2</groupId>  
55:                 <artifactId>axis2-adb</artifactId>  
56:                 <version>${axis2.version}</version>  
57:            </dependency>  
58:            <dependency>  
59:                 <groupId>org.apache.axis2</groupId>  
60:                 <artifactId>axis2-transport-http</artifactId>  
61:                 <version>${axis2.version}</version>  
62:            </dependency>  
63:            <dependency>  
64:                 <groupId>org.apache.axis2</groupId>  
65:                 <artifactId>axis2-transport-local</artifactId>  
66:                 <version>${axis2.version}</version>  
67:            </dependency>  
68:            <dependency>  
69:                 <groupId>org.apache.axis2</groupId>  
70:                 <artifactId>axis2-xmlbeans</artifactId>  
71:                 <version>${axis2.version}</version>  
72:            </dependency>  
73:            <dependency>  
74:                 <groupId>log4j</groupId>  
75:                 <artifactId>log4j</artifactId>  
76:                 <version>${log4j.version}</version>  
77:            </dependency>  
78:       </dependencies>  
79:  </project>  
The POM configuration shown here is pretty simple. The interesting bit is the WSDL2Code configuration plugin between lines 22 and 40. The plugin is configured with the following information

Line 32- Location of WSDL we're going to use for code generation.
Line 33 - Data binding framework we're going to use for code generation. In this example I've used the standard ADB (Axis Data Binding) framework but we could easily plugin an equivalent framework like JAXB or XMLBeans.
Line 34 - Package name for the generated classes.
Line 35 - Output directory for generated classes.

Code Generation
Now that we have the POM configured the next step is to run a build and generate our classes. When we run 'mvn clean install' the WSDL2Code plugin will read the WSDL and invoke the Axis code generator to build a client side proxy for our service. When the build is complete our project structure should look similar to figure 1.0. You'll notice that 2 classes were generated, both of which are explained below.
Figure 1.0 Project Structure

AccountDetailsServiceCallBackHandler
This is an abstract class that can be extend to implement a non blocking web service client. A non blocking client invokes the remote service on a separate thread and returns immediately, so as not to 'block' the client application while Axis waits on a response. The AccountDetailsServiceCallbackHandler abstract class should be extended to provide implementations for 2 callback methods, that are invoked by Axis once it has received a response from the service.
This non blocking approach is very useful in certain circumstances, for example, when a client application needs to call a number of different services at the same time. Rather than call each service sequentially, the client application can call multiple services simultaneously (on different threads) and handle the response from each service as it arrives, using appropriate callback implementations.

AccountDetailsServiceStub
This class acts as a client side proxy for the remote service and provides a means of building requests, invoking the service and processing responses.

Calling the Service Synchronously
The code sample below shows how we can use the generated classes to call our service synchronously. Note that the main thread will block while it waits on a response from the service.
1:  package com.blog.samples.webservices.client;  
2:  import java.rmi.RemoteException;  
3:  import com.blog.webservices.client.AccountDetailsServicesStub;  
4:  import com.blog.webservices.client.AccountDetailsServicesStub.AccountDetailsRequest;  
5:  import com.blog.webservices.client.AccountDetailsServicesStub.AccountDetailsResponse;  
6:  public class SynchronousWebServiceClientTest  
7:  {  
8:       public static void main (String [] args) throws RemoteException  
9:       {  
10:            AccountDetailsServicesStub servicesStub = new AccountDetailsServicesStub(WebServiceCientUtils.SERVICE_ENDPOINT);  
11:            AccountDetailsRequest accountDetailsRequest = new AccountDetailsRequest();  
12:            accountDetailsRequest.setAccountNumber("12345");  
13:            AccountDetailsResponse accountDetailsResponse = servicesStub.accountDetails(accountDetailsRequest);  
14:            WebServiceCientUtils.logAccountDetails(accountDetailsResponse.getAccountDetails());  
15:       }  
16:  }  
Calling the Service Asynchronously
The code sample below shows how we can call our service asynchronously. Invoking 'startService' on the service stub kicks off a web service request on a new thread and returns immediately so that execution of the client application is not blocked. We pass in a new instance of our callback handler to handle the web service response.
1:  package com.blog.samples.webservices.client;  
2:  import java.rmi.RemoteException;  
3:  import com.blog.webservices.client.AccountDetailsServicesStub;  
4:  import com.blog.webservices.client.AccountDetailsServicesStub.AccountDetailsRequest;  
5:  public class AsynchronousWebServiceClientTest  
6:  {  
7:       public static void main (String [] args) throws RemoteException, InterruptedException  
8:       {  
9:             AccountDetailsServicesStub servicesStub = new AccountDetailsServicesStub(WebServiceCientUtils.SERVICE_ENDPOINT);  
10:            AccountDetailsRequest accountDetailsRequest = new AccountDetailsRequest();  
11:            accountDetailsRequest.setAccountNumber("12345");  
12:            WebServiceCientCallBackHandler callBackHandler = new WebServiceCientCallBackHandler();  
13:            servicesStub.startaccountDetails(accountDetailsRequest, callBackHandler);  
14:            Thread.sleep(5000);  
15:       }  
16:  }  
A sample callback handler implementation is shown below. Note that we implement the receiveResultAccountDetails method to handle successful responses and receiveErrorAccountDetails to handle errors. Axis2 will invoke the appropriate method depending on whether or not the web service call was successful.
1:  package com.blog.samples.webservices.client;  
2:  import org.apache.log4j.Logger;  
3:  import com.blog.webservices.client.AccountDetailsServicesCallbackHandler;  
4:  import com.blog.webservices.client.AccountDetailsServicesStub.AccountDetailsResponse;  
5:  public class WebServiceCientCallBackHandler extends AccountDetailsServicesCallbackHandler  
6:  {  
7:            private static final Logger logger_c = Logger.getLogger(WebServiceCientCallBackHandler.class);  
8:            @Override  
9:            public Object getClientData()  
10:            {  
11:                 return super.getClientData();  
12:            }  
13:            @Override  
14:            public void receiveResultaccountDetails(AccountDetailsResponse result_p)  
15:            {  
16:                 super.receiveResultaccountDetails(result_p);  
17:                 WebServiceCientUtils.logAccountDetails(result_p.getAccountDetails());  
18:            }  
19:            @Override  
20:            public void receiveErroraccountDetails(Exception ex_p)  
21:            {  
22:                 super.receiveErroraccountDetails(ex_p);  
23:                 logger_c.error("An error occurred calling AccountDetails Service", ex_p);  
24:            }  
25:  }  
Source Code
You can download the full source code for this tutorial here. I'm having an issue with my GitHub account at the minute but as soon as I get that sorted I'll push the code up and add a link.
If you liked the post or have questions about any of the material covered, feel free to leave a comment below.

Monday, 14 January 2013

Spring Web Services Tutorial

Introduction
Modern enterprise applications are rarely stand alone and often rely on data and services provided by external systems. In order for different types of systems to communicate there must be a  communication protocol of some sort, a standard way of sending and receiving messages in a format that is recognised and supported by all major platforms. SOAP (Simple Object Application Protocol) is such a protocol, and allows applications to communicate by exchanging messages in a standard XML format.
SOAP Web Services provide a platform agnostic integration mechanism that allows disparate systems to exchange data regardless of the platform they are running on. For example, SOAP web services are commonly used to integrate .NET applications with applications running on the Java platform. Almost all modern platforms and frameworks (Java, .Net, Ruby, PHP, etc) provide comprehensive libraries and tooling that allow developers to quickly and easily expose and consume SOAP services.
This post will look at Spring Web Services and take you through a step by step tutorial for building, deploying and testing a simple contract first SOAP service for retrieving simple bank account details.

Technology Stack
The technology stack used in this tutorial will include Spring 3.1 for Web Services Support, Maven for  dependency resolution & build, Tomcat for our test server and SoapUI to build sample SOAP messages for testing our service.

Creating the Project
The project structure is similar to that used in a some of my other tutorials and is typical of most modern Spring web applications. We'll start off by creating a simple Spring web project like the one shown in figure 1.0 below.
Figure 1.0 Project Structure
Contract Last vs Contract First
There are two fundamental approaches to building web services, Contract Last and Contract First.
The Contract Last approach involves taking existing code and generating a service contract directly from that code in order to expose it as a SOAP interface. There are a variety of Java frameworks out there (Axis2, XFire etc) that provide this Java2WSDL tooling, to quickly generate the server side proxies, marshallers and Servlet classes required to expose a SOAP service.
The Contract First approach involves defining the Service contract before implementing the service. This means describing the service parameters and return types using XSD's (XML Schema Definitions), then using those XSD's to construct a WSDL (web service definition language) to provides a public facing contract or description of the service. Only after the service contract has been clearly defined, is the service implementation actually written.
This post will describe a Contract First service, as this is the preferred approach for various reasons, some of which are explained in this article.

Service Contract Definition
Given that we're building a service to retrieve simple bank account details we'll start off by defining our core business entity, an Account. We'll define our account entity in src/main/webapp/schemas/AccountDetails.xsd.
 <?xml version="1.0" encoding="UTF-8"?>  
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://webservices.samples.blog.com" targetNamespace="http://webservices.samples.blog.com" elementFormDefault="qualified" attributeFormDefault="unqualified">  
      <xs:element name="Account" type="Account"/>  
      <xs:complexType name="Account">  
           <xs:sequence>  
                <xs:element name="AccountNumber" type="xs:string"/>  
                <xs:element name="AccountName" type="xs:string"/>  
                <xs:element name="AccountBalance" type="xs:double"/>  
                <xs:element name="AccountStatus" type="EnumAccountStatus"/>  
           </xs:sequence>  
      </xs:complexType>  
      <xs:simpleType name="EnumAccountStatus">  
           <xs:restriction base="xs:string">  
                <xs:enumeration value="Active"/>  
                <xs:enumeration value="Inactive"/>  
           </xs:restriction>  
      </xs:simpleType>  
 </xs:schema>  
I use XMLSpy for working with XML as it provides a useful graphical representation of the XML types being defined. This can be useful when working on large applications with complex data models. A visual representation of the above XSD is shown below.
Figure 2.0 Account Entity
Next we'll define the service request and response types in src/main/webapp/schemas/AccountDetailsServiceOperations.xsd.
 <?xml version="1.0" encoding="UTF-8"?>  
 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://com/blog/samples/webservices/accountservice" xmlns:account="http://webservices.samples.blog.com" targetNamespace="http://com/blog/samples/webservices/accountservice" elementFormDefault="qualified">  
      <xsd:import namespace="http://webservices.samples.blog.com" schemaLocation="AccountDetails.xsd"/>  
      <xsd:element name="AccountDetailsRequest">  
           <xsd:complexType>  
                <xsd:sequence>  
                     <xsd:element name="accountNumber" type="xsd:string"/>  
                </xsd:sequence>  
           </xsd:complexType>  
      </xsd:element>  
      <xsd:element name="AccountDetailsResponse">  
           <xsd:complexType>  
                <xsd:sequence>  
                     <xsd:element name="AccountDetails" type="account:Account"/>  
                </xsd:sequence>  
           </xsd:complexType>  
      </xsd:element>  
 </xsd:schema>  
A visual representation of these types is shown below.
Figure 3.0 AccountDetailsRequiest Entity
Figure 4.0 AccountDetailsResponse Entity
Object to XML Mapping
A fundamental part of web services is the conversion of SOAP messages from XML to Java objects and vice versa. This is a non trivial task if you were to set out to do it yourself so we'll make use of the JAXB framework to take car of this for us. I've been working with JAXB for a few years now and find it to be a powerful and flexible framework, and a huge improvement on older OXM frameworks like Castor.
In order to use our XSD defined types in the application we need to generate Java classes from those types. We do this as part of the Maven build process by using the jaxb-maven-plugin in our POM. The plugin is configured to parse a set of XSD's and run JAXB's class generator to create Java classes for each of the defined types. For brevity only part of the Maven POM definition is shown below. The entire  POM definition can be found with the source code that accompanies this tutorial.
 <?xml version="1.0"?>  
 <project xmlns="http://maven.apache.org/POM/4.0.0"  
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  
                                     http://maven.apache.org/maven-v4_0_0.xsd">  
      <artifactId>spring-webservices-sample</artifactId>  
      <modelVersion>4.0.0</modelVersion>  
      <inceptionYear>2013</inceptionYear>  
      <packaging>war</packaging>  
      <groupId>com.blog.webservices</groupId>  
      <version>1.0</version>  
      <properties>  
           <spring.version>3.1.1.RELEASE</spring.version>  
           <spring.ws.version>2.0.0.RELEASE</spring.ws.version>  
           <log4j.version>1.2.16</log4j.version>  
           <context.path>spring-webservices-sample</context.path>  
      </properties>  
      <build>  
           <plugins>  
                <plugin>  
                     <groupId>org.codehaus.mojo</groupId>  
                     <artifactId>jaxb2-maven-plugin</artifactId>  
                     <version>1.4</version>  
                     <executions>  
                          <execution>  
                               <goals>  
                                    <goal>xjc</goal>  
                               </goals>  
                               <phase>generate-sources</phase>  
                          </execution>  
                     </executions>  
                     <configuration>  
                          <clearOutputDir>false</clearOutputDir>  
                          <outputDirectory>src/main/java</outputDirectory>  
                          <schemaDirectory>src/main/webapp/schemas</schemaDirectory>  
                          <includeSchema>**/*.xsd</includeSchema>                        
                          <enableIntrospection>false</enableIntrospection>  
                     </configuration>  
                </plugin>  
                <plugin>  
                     <groupId>org.apache.maven.plugins</groupId>  
                     <artifactId>maven-war-plugin</artifactId>  
                     <configuration>  
                          <warName>${context.path}</warName>  
                     </configuration>  
                </plugin>  
           </plugins>  
      </build>  
      <dependencies>  
     ...  
     ...  
Running a Maven build will create Java classes for each of the defined schema types. The screenshot below shows what the generated classes should look like in your project after you run a Maven build. Note that JAXB has used the the namespaces in the XSD's to derive package names for the generated classes.
Figure 5.0 JAXB Generated Classes
Defining the Service
The next step is to define the Service interface using the types we generated above. The Service interface is defined below and is very simple indeed.
 package com.blog.samples.services;  
 import com.blog.samples.webservices.Account;  
 /**  
  * The Interface AccountService.  
  */  
 public interface AccountService  
 {  
      /**  
       * Gets the account details.  
       *  
       * @param accountNumber the account number  
       * @return the account details  
       */  
      public Account getAccountDetails(String accountNumber);  
 }  
Now we'll provide a really simple implementation of this interface. As you can see our service implementation returns some hard coded values. Obviously a real service implementation would do something more meaningful.
 package com.blog.samples.services;  
 import org.springframework.stereotype.Service;  
 import com.blog.samples.webservices.Account;  
 import com.blog.samples.webservices.EnumAccountStatus;  
 /**  
  * The Class AccountService.  
  */  
 @Service  
 public class AccountServiceImpl implements AccountService  
 {  
      /**  
       * Gets the account details.  
       *  
       * @param accountNumber the account number  
       * @return the account details  
       */  
      public Account getAccountDetails(String accountNumber)  
      {  
           /* hard coded account data - in reality this data would be retrieved  
            * from a database or back end system of some sort */  
           Account account = new Account();  
           account.setAccountNumber("12345");  
           account.setAccountStatus(EnumAccountStatus.ACTIVE);  
           account.setAccountName("Joe Bloggs");  
           account.setAccountBalance(3400);  
           return account;  
      }  
 }  
Creating the Service Endpoint
A service endpoint is the component that deals with processing web service requests and responses. In the background a Spring Servlet intercepts incoming SOAP requests for a defined URL and routes them to an endpoint for processing. Below we're going to define that endpoint.
1:  package com.blog.samples.services.endpoints;  
2:  import org.springframework.beans.factory.annotation.Autowired;  
3:  import org.springframework.ws.server.endpoint.annotation.Endpoint;  
4:  import org.springframework.ws.server.endpoint.annotation.PayloadRoot;  
5:  import org.springframework.ws.server.endpoint.annotation.RequestPayload;  
6:  import org.springframework.ws.server.endpoint.annotation.ResponsePayload;  
7:  import com.blog.samples.services.AccountService;  
8:  import com.blog.samples.webservices.Account;  
9:  import com.blog.samples.webservices.accountservice.AccountDetailsRequest;  
10:  import com.blog.samples.webservices.accountservice.AccountDetailsResponse;  
11:  /**  
12:   * The Class AccountService.  
13:   */  
14:  @Endpoint  
15:  public class AccountServiceEndpoint  
16:  {  
17:       private static final String TARGET_NAMESPACE = "http://com/blog/samples/webservices/accountservice";  
18:       @Autowired  
19:       private AccountService accountService_i;  
20:       /**  
21:        * Gets the account details.  
22:        *  
23:        * @param accountNumber the account number  
24:        * @return the account details  
25:        */  
26:       @PayloadRoot(localPart = "AccountDetailsRequest", namespace = TARGET_NAMESPACE)  
27:       public @ResponsePayload AccountDetailsResponse getAccountDetails(@RequestPayload AccountDetailsRequest request)  
28:       {  
29:            AccountDetailsResponse response = new AccountDetailsResponse();  
30:            /* call Spring injected service implementation to retrieve account data */  
31:            Account account = accountService_i.getAccountDetails(request.getAccountNumber());  
32:            response.setAccountDetails(account);  
33:            return response;  
34:       }  
35:       public void setAccountService(AccountService accountService_p)  
36:       {  
37:            this.accountService_i = accountService_p;  
38:       }  
39:  }  
Our sample application makes sue of  Springs Web Services annotation support. The above class uses a number of these annotations, each of which is explained below.

Line 14 - @Enpoint is a specialised version of the standard Spring @Component annotation and allows this class to get picked up and registered by Springs component scanning.
Lines 18 & 19 - Our simple service implementation is Spring injected so that it can be used by our web service endpoint.
Line 17 - this is the namespace we defined in our XSD type definitions earlier. We use this in the endpoint class for mapping request to specific methods for processing.
Line 26 - @PayloadRoot indicates that this method will process service requests with the XML root element matching that defined by the localPart attribute. In the example above our method will process incoming requests of type AccountDetailsRequest with namespace http://com/blog/samples/webservices/accountservice. Remember that we defined this XSD type and namespace earlier.
Line 27 - @ResponsePayload indicates the type to be returned in the SOAP response. In this example the AccountDetailsResponse object will be converted to XML and returned to the client application as a SOAP response. @RequestPayload AccountDetails tells Spring to convert incoming requests of type AccountDetails, from XML to Java and the pass that object as a parameter to this endpoint method.

Spring Configuration
Next we'll write our Spring configuration to bring everything together. The Spring configuration is defined as follows.
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <beans xmlns="http://www.springframework.org/schema/beans"  
3:            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4:            xmlns:context="http://www.springframework.org/schema/context"  
5:            xmlns:sws="http://www.springframework.org/schema/web-services"  
6:            xsi:schemaLocation="http://www.springframework.org/schema/beans  
7:                                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
8:                                     http://www.springframework.org/schema/web-services  
9:                                     http://www.springframework.org/schema/web-services/web-services-2.0.xsd  
10:                                     http://www.springframework.org/schema/context  
11:                                     http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
12:       <context:component-scan base-package="com.blog.samples.services" />  
13:       <sws:annotation-driven />  
14:       <!--  
15:            Our test service bean  
16:       -->  
17:       <bean id="AccountDetailsService" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition" lazy-init="true">  
18:      <property name="schemaCollection">  
19:        <bean class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">  
20:          <property name="inline" value="true" />  
21:          <property name="xsds">  
22:            <list>  
23:              <value>schemas/AccountDetailsServiceOperations.xsd</value>  
24:            </list>  
25:          </property>  
26:        </bean>  
27:      </property>  
28:      <property name="portTypeName" value="AccountDetailsService"/>  
29:      <property name="serviceName" value="AccountDetailsServices" />  
30:      <property name="locationUri" value="/endpoints"/>  
31:    </bean>  
32:  </beans>  
Line 12 - Component scanning scans the defined package (com.blog.sample.services) for Spring managed components to load into the bean factory.
Line 13 - Enables Spring Web Services annotation support so that annotations like @PayloadRoot can be used to configure the service endpoint.
Line 17 to 31 - Use of DefaultWsdl11Definition enables automated WSDL generation. Spring uses the schema definitions listed in the schemaCollection property, as well as the portType, serviceName and locationUri to generate a WSDL file the first time it is requested. Although this is a powerful feature it should be used with caution in production as the WSDL generation process can be quite slow. An approach I've used in the past is to copy the generated WSDL from your browser to your project and expose it using Springs static WSDL support with <static-wsdl>.

Web.xml
Now for the final bit of configuration before we test out our service. Web.xml is defined as follows.
1:  <?xml version="1.0" encoding="UTF-8"?>  
2:  <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
3:             xmlns="http://java.sun.com/xml/ns/javaee"  
4:             xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
5:             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
6:             id="WebApp_ID"  
7:             version="2.5">  
8:       <context-param>  
9:            <param-name>contextConfigLocation</param-name>  
10:            <param-value>  
11:                 /WEB-INF/config/spring-config.xml  
12:            </param-value>  
13:       </context-param>  
14:       <listener>  
15:            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
16:       </listener>  
17:       <servlet>  
18:            <servlet-name>webservices</servlet-name>  
19:            <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>  
20:            <init-param>  
21:                 <param-name>transformWsdlLocations</param-name>  
22:                 <param-value>true</param-value>  
23:            </init-param>  
24:            <init-param>  
25:                 <param-name>contextConfigLocation</param-name>  
26:                 <param-value></param-value>  
27:            </init-param>  
28:            <load-on-startup>1</load-on-startup>  
29:       </servlet>  
30:       <servlet-mapping>  
31:            <servlet-name>webservices</servlet-name>  
32:            <url-pattern>*.wsdl</url-pattern>  
33:       </servlet-mapping>  
34:       <servlet-mapping>  
35:            <servlet-name>webservices</servlet-name>  
36:            <url-pattern>/endpoints/*</url-pattern>  
37:       </servlet-mapping>  
38:  </web-app>  
Line 8 to 13 - Path for Spring configuration to be loaded on application start-up.
Line 14 to 16 - Loads the Spring application context using the configuration file defined above
Line 18 to 19 - Spring Web Service Servlet that intercepts incoming HTTP requests.
Line 21 to 22 - Ensures WSDL is context aware. Transforms SOAP address so that it isn't hard coded to localhost:8080.Address updates depending on the application context and port that the application is deployed at.
Line 25 to 26 - ContextConfigLocation set with an empty parameter means that Spring won't try to load the default webservices-servlet.xml configuration.
Line 47 to 55 - Configures the URLs that our newly configured Web Services Servlet will handle.

Deploying the Service
We're now ready to deploy our application - I use Tomcat but feel free to use any Servlet container. Once the application is deployed, just browse to http://localhost:8080/spring-webservices-sample/endpoints/AccountDetailsService.wsdl and the application should generate and display the following WSDL.
1:  <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch0="http://com/blog/samples/webservices/accountservice" xmlns:sch1="http://webservices.samples.blog.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://com/blog/samples/webservices/accountservice" targetNamespace="http://com/blog/samples/webservices/accountservice">  
2:       <wsdl:types>  
3:            <xsd:schema xmlns="http://com/blog/samples/webservices/accountservice" xmlns:account="http://webservices.samples.blog.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://com/blog/samples/webservices/accountservice">  
4:                 <xsd:import namespace="http://webservices.samples.blog.com"/>  
5:                 <xsd:element name="AccountDetailsRequest">  
6:                      <xsd:complexType>  
7:                           <xsd:sequence>  
8:                                <xsd:element name="accountNumber" type="xsd:string"/>  
9:                           </xsd:sequence>  
10:                      </xsd:complexType>  
11:                 </xsd:element>  
12:                 <xsd:element name="AccountDetailsResponse">  
13:                      <xsd:complexType>  
14:                           <xsd:sequence>  
15:                                <xsd:element name="AccountDetails" type="account:Account"/>  
16:                           </xsd:sequence>  
17:                      </xsd:complexType>  
18:                 </xsd:element>  
19:            </xsd:schema>  
20:            <xs:schema xmlns="http://webservices.samples.blog.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://webservices.samples.blog.com">  
21:                 <xs:element name="Account" type="Account"/>  
22:                 <xs:complexType name="Account">  
23:                      <xs:sequence>  
24:                           <xs:element name="AccountNumber" type="xs:string"/>  
25:                           <xs:element name="AccountName" type="xs:string"/>  
26:                           <xs:element name="AccountBalance" type="xs:double"/>  
27:                           <xs:element name="AccountStatus" type="EnumAccountStatus"/>  
28:                      </xs:sequence>  
29:                 </xs:complexType>  
30:                 <xs:simpleType name="EnumAccountStatus">  
31:                      <xs:restriction base="xs:string">  
32:                           <xs:enumeration value="Active"/>  
33:                           <xs:enumeration value="Inactive"/>  
34:                      </xs:restriction>  
35:                 </xs:simpleType>  
36:            </xs:schema>  
37:       </wsdl:types>  
38:       <wsdl:message name="AccountDetailsResponse">  
39:            <wsdl:part element="tns:AccountDetailsResponse" name="AccountDetailsResponse"/>  
40:       </wsdl:message>  
41:       <wsdl:message name="AccountDetailsRequest">  
42:            <wsdl:part element="tns:AccountDetailsRequest" name="AccountDetailsRequest"/>  
43:       </wsdl:message>  
44:       <wsdl:portType name="AccountDetailsService">  
45:            <wsdl:operation name="AccountDetails">  
46:                 <wsdl:input message="tns:AccountDetailsRequest" name="AccountDetailsRequest"/>  
47:                 <wsdl:output message="tns:AccountDetailsResponse" name="AccountDetailsResponse"/>  
48:            </wsdl:operation>  
49:       </wsdl:portType>  
50:       <wsdl:binding name="AccountDetailsServiceSoap11" type="tns:AccountDetailsService">  
51:            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>  
52:            <wsdl:operation name="AccountDetails">  
53:                 <soap:operation soapAction=""/>  
54:                 <wsdl:input name="AccountDetailsRequest">  
55:                      <soap:body use="literal"/>  
56:                 </wsdl:input>  
57:                 <wsdl:output name="AccountDetailsResponse">  
58:                      <soap:body use="literal"/>  
59:                 </wsdl:output>  
60:            </wsdl:operation>  
61:       </wsdl:binding>  
62:       <wsdl:service name="AccountDetailsServices">  
63:            <wsdl:port binding="tns:AccountDetailsServiceSoap11" name="AccountDetailsServiceSoap11">  
64:                 <soap:address location="http://localhost:8080/spring-webservices-sample/endpoints"/>  
65:            </wsdl:port>  
66:       </wsdl:service>  
67:  </wsdl:definitions>  
Testing the Service
The simplest way to test a SOAP service is using SoapUI. For anyone who hasn't used it before, SoapUI is an open source functional testing tool for testing SOAP web services. It saves us having to write a web service client and means that in just a few clicks we can have a test harness in place to test our service.

To test our serviced using SoapUI follow the steps below.
Figure 6.0 SoapUI Test Project
  • SoapUI will parse the exposed WSDL (make sure your application is deployed and the WSDL is exposed!) and use it to build a sample SOAP request.
  • When the new project opens click AccountServiceTest -> AccountDetails -> request and you'll see a SOAP request for the AccountDetails service in the left hand pane. Set the account number and press the green arrow in the top left hand corner to call the service.
  • If the request is successful you should see a SOAP response containing the requested account data in the right hand pane. See figure 7.0 below  
Figure 7.0 SoapUI AccountDetaills Service Test
Summary
The sample code in this post took you through the steps required to build, deploy and test a contract first web service using the Spring framework. Don't forget that you can download the full source code for this tutorial and play around with it. If you found this tutorial useful then feel free to share it with others or leave a comment below. The full source code can be found on GitHub at https://github.com/briansjavablog/spring-webservices-tutorial.