Added support for publishing arguments, exception, or return value from the MessagePublishingInterceptor and the @Publisher-aware version (INT-175).
This commit is contained in:
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user