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.
December 16, 2008 at 11:25 pm |
in method afterThrowing, you’ve got type of the service directly stated:
DomainRegistryService target
if you have multiple services processed by this Interceptor , you have to overload this method for each of the service like:
public void afterThrowing(Method method, Object[] args,
AnotherService target, Exception ex) throws Exception
you’d benefit if all your services had a common parent
December 16, 2008 at 11:44 pm |
I am punishing all my devs for not enclosing logger.debug() statements inside if (logger.isDebugEnabled())
)