Added support for publishing arguments, exception, or return value from the MessagePublishingInterceptor and the @Publisher-aware version (INT-175).

This commit is contained in:
Mark Fisher
2008-08-18 15:53:42 +00:00
parent 2977f4f61b
commit 0fcf546ad0
4 changed files with 140 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.integration.aop.MessagePublishingInterceptor;
/**
* Indicates that the method's return value should be published to the specified
* channel. The value will only be published if non-null.
@@ -37,4 +39,7 @@ public @interface Publisher {
String channel();
MessagePublishingInterceptor.PayloadType payloadType()
default MessagePublishingInterceptor.PayloadType.RETURN_VALUE;
}

View File

@@ -70,4 +70,18 @@ public class AnnotationAwareMessagePublishingInterceptor extends MessagePublishi
return super.resolveChannel(invocation);
}
@Override
protected PayloadType determinePayloadType(MethodInvocation invocation) {
Class<?> targetClass = AopUtils.getTargetClass(invocation.getThis());
Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
Annotation annotation = AnnotationUtils.getAnnotation(method, this.publisherAnnotationType);
if (annotation != null) {
PayloadType payloadType = (PayloadType) AnnotationUtils.getValue(annotation, "payloadType");
if (payloadType != null) {
return payloadType;
}
}
return super.determinePayloadType(invocation);
}
}

View File

@@ -26,6 +26,7 @@ import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;
import org.springframework.util.Assert;
/**
* Interceptor that publishes a target method's return value to a channel.
@@ -34,17 +35,27 @@ import org.springframework.integration.message.MessageCreator;
*/
public class MessagePublishingInterceptor implements MethodInterceptor {
public static enum PayloadType { RETURN_VALUE, ARGUMENTS, EXCEPTION };
protected final Log logger = LogFactory.getLog(getClass());
private volatile MessageCreator messageCreator;
private volatile MessageChannel defaultChannel;
private volatile PayloadType payloadType = PayloadType.RETURN_VALUE;
public void setDefaultChannel(MessageChannel defaultChannel) {
this.defaultChannel = defaultChannel;
}
public void setPayloadType(PayloadType payloadType) {
Assert.notNull(payloadType, "'payloadType' must not be null");
this.payloadType = payloadType;
}
/**
* Specify the {@link MessageCreator} to use when creating a message from the
* return value Object.
@@ -59,8 +70,32 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
* Invoke the target method and publish its return value.
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
Object retval = invocation.proceed();
if (retval != null) {
PayloadType payloadType = this.determinePayloadType(invocation);
if (payloadType.equals(PayloadType.ARGUMENTS)) {
this.sendMessage(invocation.getArguments(), invocation);
}
Object retval = null;
Throwable throwable = null;
try {
retval = invocation.proceed();
return retval;
}
catch (Throwable t) {
throwable = t;
throw t;
}
finally {
if (payloadType.equals(PayloadType.RETURN_VALUE)) {
this.sendMessage(retval, invocation);
}
else if (payloadType.equals(PayloadType.EXCEPTION)) {
this.sendMessage(throwable, invocation);
}
}
}
private void sendMessage(Object payload, MethodInvocation invocation) {
if (payload != null) {
MessageChannel channel = this.resolveChannel(invocation);
if (channel == null) {
if (logger.isWarnEnabled()) {
@@ -69,11 +104,11 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
}
}
else {
Message<?> message = (this.messageCreator != null) ? this.messageCreator.createMessage(retval) : new GenericMessage<Object>(retval);
Message<?> message = (this.messageCreator != null) ?
this.messageCreator.createMessage(payload) : new GenericMessage<Object>(payload);
channel.send(message);
}
}
return retval;
}
/**
@@ -83,4 +118,8 @@ public class MessagePublishingInterceptor implements MethodInterceptor {
return this.defaultChannel;
}
protected PayloadType determinePayloadType(MethodInvocation invocation) {
return this.payloadType;
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.aop;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -61,6 +62,61 @@ public class PublisherAnnotationAdvisorTests {
assertNull(message);
}
@Test
public void testPublishArguments() {
final QueueChannel channel = new QueueChannel();
channel.setBeanName("testChannel");
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel(channel);
PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor(channelRegistry);
TestService proxy = (TestService) this.createProxy(new TestServiceImpl("hello world"), advisor);
proxy.publishArguments("foo", 99);
Message<?> message = channel.receive(0);
assertNotNull(message);
assertTrue(message.getPayload() instanceof Object[]);
Object[] args = (Object[]) message.getPayload();
assertEquals(2, args.length);
assertEquals("foo", args[0]);
assertEquals(99, args[1]);
}
@Test
public void testPublishException() {
final QueueChannel channel = new QueueChannel();
channel.setBeanName("testChannel");
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel(channel);
PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor(channelRegistry);
TestService proxy = (TestService) this.createProxy(new TestServiceImpl("hello world"), advisor);
RuntimeException caughtException = null;
try {
proxy.publishException();
}
catch (RuntimeException e) {
caughtException = e;
}
assertNotNull(caughtException);
Message<?> message = channel.receive(0);
assertNotNull(message);
assertTrue(message.getPayload() instanceof RuntimeException);
RuntimeException publishedException = (RuntimeException) message.getPayload();
assertEquals(caughtException, publishedException);
}
@Test
public void testPublishReturnValue() {
final QueueChannel channel = new QueueChannel();
channel.setBeanName("testChannel");
ChannelRegistry channelRegistry = new DefaultChannelRegistry();
channelRegistry.registerChannel(channel);
PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor(channelRegistry);
TestService proxy = (TestService) this.createProxy(new TestServiceImpl("hello world"), advisor);
Integer actualReturnValue = proxy.publishReturnValue();
Message<?> message = channel.receive(0);
assertNotNull(message);
assertEquals(actualReturnValue, message.getPayload());
}
private Object createProxy(Object target, PublisherAnnotationAdvisor advisor) {
ProxyFactory factory = new ProxyFactory(target);
@@ -74,6 +130,13 @@ public class PublisherAnnotationAdvisorTests {
String publisherTest();
String noPublisherTest();
void publishArguments(String s, Integer n);
Integer publishReturnValue();
void publishException();
}
@@ -94,6 +157,20 @@ public class PublisherAnnotationAdvisorTests {
return this.message;
}
@Publisher(channel="testChannel", payloadType=MessagePublishingInterceptor.PayloadType.ARGUMENTS)
public void publishArguments(String s, Integer n) {
}
@Publisher(channel="testChannel", payloadType=MessagePublishingInterceptor.PayloadType.EXCEPTION)
public void publishException() {
throw new RuntimeException("test failure");
}
@Publisher(channel="testChannel", payloadType=MessagePublishingInterceptor.PayloadType.RETURN_VALUE)
public Integer publishReturnValue() {
return 123;
}
}
}