View Javadoc

1   package net.sf.appstatus.support.aop;
2   
3   import net.sf.appstatus.core.services.IService;
4   import net.sf.appstatus.core.services.IServiceManager;
5   import net.sf.appstatus.core.services.IServiceMonitor;
6   
7   import org.aopalliance.intercept.MethodInterceptor;
8   import org.aopalliance.intercept.MethodInvocation;
9   import org.slf4j.Logger;
10  import org.slf4j.LoggerFactory;
11  
12  /**
13   * AOP AppStatus interceptor for services. Allows to remove references to
14   * AppStatus in services calls (replaces
15   * getMonitor/beginCall/cacheHit/failure/endCall).
16   *
17   * <p>
18   * Supports failure and cacheHit (if useThreadLocal enabled).
19   * <p>
20   *
21   * <pre>
22   * &lt;bean id="appStatusInterceptor" class="net.sf.appstatus.support.aop.AppStatusServiceInterceptor" scope="singleton">
23   *         &lt;property name="serviceManager" ref="serviceManager" />
24   * 
25   *         &lt;!-- Optional property for dynamic activation -->
26   *         &lt;property name="activationCallback" ref="activationCallback" />
27   * 
28   *         &lt;!-- Optional property for logger selection -->
29   *         &lt;property name="logger" value="&lt;logger-name>" />
30   * 
31   *         &lt;!-- Optional property for monitor setup -->
32   *         &lt;property name="preServiceCallback" ref="preServiceCallback" />
33   * 
34   *         &lt;!-- Optional property for service result analysis -->
35   *         &lt;property name="postServiceCallback" ref="postServiceCallback" />
36   * 
37   * &lt;/bean>
38   * 
39   *  &lt;aop:config >
40   *         &lt;aop:advisor id="serviceCallAdvisor" advice-ref="appStatusInterceptor" pointcut="execution(public * your.package.ServiceClient*.*(..))" />
41   *     &lt;/aop:config>
42   * </pre>
43   *
44   * @author Nicolas Richeton
45   **/
46  public class AppStatusServiceInterceptor implements MethodInterceptor {
47  
48  	private IAppStatusActivationCallback activationCallback;
49  	private Logger logger = null;
50  
51  	private IPostServiceCallback postServiceCallback;
52  	private IPreServiceCallback preServiceCallback;
53  	private IServiceManager serviceManager;
54  
55  	public Object invoke(MethodInvocation invocation) throws Throwable {
56  
57  		// Ensure AppStatus is activated
58  		if (activationCallback != null && !activationCallback.isActive(invocation)) {
59  			return invocation.proceed();
60  		}
61  
62  		IServiceMonitor m = null;
63  
64  		// Get custom monitor
65  		if (preServiceCallback != null) {
66  			m = preServiceCallback.getMonitor(serviceManager, invocation);
67  		}
68  
69  		// Create default service monitor if necessary.
70  		if (m == null) {
71  			IService service = serviceManager.getService(invocation.getMethod().getName(), invocation.getThis()
72  					.getClass().getSimpleName());
73  			m = serviceManager.getMonitor(service);
74  		}
75  
76  		// Change default logger
77  		if (logger != null) {
78  			m.setLogger(logger);
79  		}
80  
81  		// Allow custom setup
82  		if (preServiceCallback != null) {
83  			preServiceCallback.setup(m, invocation);
84  		}
85  
86  		Object result = null;
87  		m.beginCall(invocation.getArguments());
88  		try {
89  			result = invocation.proceed();
90  
91  			// Allow custom result handling
92  			if (postServiceCallback != null) {
93  				postServiceCallback.handleResult(m, invocation, result);
94  			}
95  
96  		} catch (Exception e) {
97  			// Allow custom exception handling
98  			if (postServiceCallback != null) {
99  				postServiceCallback.handleException(m, invocation, e);
100 			} else {
101 				m.failure(e.getLocalizedMessage(), e);
102 			}
103 			throw e;
104 		} finally {
105 			m.endCall();
106 		}
107 		return result;
108 
109 	}
110 
111 	/**
112 	 * @param activationCallback
113 	 */
114 	public void setActivationCallback(IAppStatusActivationCallback activationCallback) {
115 		this.activationCallback = activationCallback;
116 	}
117 
118 	/**
119 	 * Set the logger to use with this interceptor.
120 	 *
121 	 * @param name
122 	 *            logger name
123 	 */
124 	public void setLogger(String name) {
125 		logger = LoggerFactory.getLogger(name);
126 	}
127 
128 	/**
129 	 * Adding a callback disables automatic failure management. It's up to the
130 	 * callback to set failure flag.
131 	 *
132 	 * @param postServiceCallback
133 	 */
134 	public void setPostServiceCallback(IPostServiceCallback postServiceCallback) {
135 		this.postServiceCallback = postServiceCallback;
136 	}
137 
138 	/**
139 	 * @param preServiceCallback
140 	 */
141 	public void setPreServiceCallback(IPreServiceCallback preServiceCallback) {
142 		this.preServiceCallback = preServiceCallback;
143 	}
144 
145 	/**
146 	 * Set the AppStatus service manager to use for this interceptor.
147 	 *
148 	 * @param serviceManager
149 	 */
150 	public void setServiceManager(IServiceManager serviceManager) {
151 		this.serviceManager = serviceManager;
152 	}
153 
154 }