Archive for November, 2008

Exception interception

November 14, 2008

Sometimes you need to perform a specific action on some kind of Exception. For example, if you have multiple calls of domainRegistryService, and in case of unsuccessful registration it needs to write the reason to the database. For this task you can use Spring to create an interceptor.

This is the interceptor class. afterThrowing implements ThrowsAdvice and is called in case of Exception, afterReturning implements AfterReturningAdvice and is called in case when method is completed successfully. getOrder is needed if you have more than one interceptor

public class DomainRegistryInterceptor implements ThrowsAdvice,
		AfterReturningAdvice, Ordered {

	private static final long serialVersionUID = 1L;
	private static final Logger logger = Logger
			.getLogger(TransactionDescriptionInterceptor.class);

	public void afterThrowing(Method method, Object[] args,
			DomainRegistryService target, Exception ex) throws Exception {
		logger.debug("=== TransactionDescriptionInterceptor.afterThrowing ===");

		logger.debug("=== target === " + target.getClass().getName());
		logger.debug("=== method === " + method.getName());

		if (args != null && args.length > 0 && args[0] instanceof Domain
				&& ((Domain) args[0]).getTransactionId() != null)

			target.updateTransactionDescription(((Domain) args[0])
					.getTransactionId(), ex.getMessage());
		throw ex;
	}

	@Override
	public void afterReturning(Object arg0, Method method, Object[] args,
			Object target) throws Throwable {

		logger.debug("=== TransactionDescriptionInterceptor.afterReturning ===");

		logger.debug("=== target === " + target.getClass().getName());
		logger.debug("=== method === " + method.getName());

		if (target instanceof DomainRegistryService) {
			DomainRegistryService domainRegistryService = (DomainRegistryService) target;

			if (args != null && args.length > 0 && args[0] instanceof Domain
					&& ((Domain) args[0]).getTransactionId() != null)

				domainRegistryService.updateTransactionDescription(
						((Domain) args[0]).getTransactionId(),
						"Command completed successfully");
		}
	}

	@Override
	public int getOrder() {
		return 3;
	}

}

Then you have to bind this interceptor to your service (or services). Here’s a Spring configuration file:

	< !-- Service-->
	< bean id="service.domain.domainRegistryService"
		class="com.yourcompany.service.domain.impl.DomainRegistryServiceImpl">
	< /bean>

	< !-- INTERCEPTOR -->
	< bean id="domainRegistryInterceptor"
		class="com.yourcompany.spring.DomainRegistryInterceptor">
	< /bean>

	< !-- Auto-Proxy -->
	< bean id="domainRegistryProxyCreator"
		class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		< property name="beanNames">
			< list>
				< idref bean="service.domain.domainRegistryService" />
			< /list>
		< /property>
		< property name="interceptorNames">
			< list>
				< idref bean="txInterceptor" />
				< idref bean="methodCallAccessInterceptor" />
				< idref bean="domainRegistryInterceptor" />
			< /list>
		< /property>
		< property name="order" value="3" />
	< /bean>

The linking is performed in the Auto-proxy part. Service is listed under beanNames property, interceptor goes to interceptorNames property, order defines the order of this proxy among other proxies in the application.

Background of Spring auto-proxy is explained here.