Removed the @MessageSource method-level annotation and added @Pollable as its replacement. Also added the @ChannelAdapter class-level annotation (refactoring to remove SourceEndpoint).
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Indicates that a class is capable of serving as a message channel.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Component
|
||||
public @interface ChannelAdapter {
|
||||
|
||||
String value();
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.springframework.integration.message.Message;
|
||||
* Indicates that a method is capable of producing messages. The method must
|
||||
* accept no parameters and return either a {@link Message} or an Object to
|
||||
* be passed as the message payload. The enclosing class may also be annotated
|
||||
* with {@link MessageEndpoint @MessageEndpoint}.
|
||||
* with {@link ChannelAdapter @ChannelAdapter}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@@ -36,6 +36,6 @@ import org.springframework.integration.message.Message;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface MessageSource {
|
||||
public @interface Pollable {
|
||||
|
||||
}
|
||||
@@ -47,4 +47,6 @@ public @interface Polled {
|
||||
|
||||
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
||||
|
||||
int maxMessagesPerPoll() default 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,12 +27,17 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.ConfigurationException;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.Polled;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
import org.springframework.integration.channel.ChannelRegistryAware;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.channel.PollableChannel;
|
||||
import org.springframework.integration.dispatcher.PollingDispatcher;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.message.MessageSource;
|
||||
import org.springframework.integration.message.MessageTarget;
|
||||
import org.springframework.integration.scheduling.PollingSchedule;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -66,7 +71,7 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Init
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
this.postProcessors.put(MessageHandler.class, new HandlerAnnotationPostProcessor(this.messageBus, this.beanClassLoader));
|
||||
this.postProcessors.put(MessageSource.class, new SourceAnnotationPostProcessor(this.messageBus, this.beanClassLoader));
|
||||
this.postProcessors.put(MessageSource.class, new PollableAnnotationPostProcessor(this.messageBus, this.beanClassLoader));
|
||||
this.postProcessors.put(MessageTarget.class, new TargetAnnotationPostProcessor(this.messageBus, this.beanClassLoader));
|
||||
}
|
||||
|
||||
@@ -86,6 +91,29 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Init
|
||||
postProcessor.createEndpoint(bean, beanName, beanClass, endpointAnnotation);
|
||||
if (endpoint != null) {
|
||||
endpoint.setName(beanName + "." + entry.getKey().getSimpleName() + ".endpoint");
|
||||
Polled polledAnnotation = AnnotationUtils.findAnnotation(beanClass, Polled.class);
|
||||
if (polledAnnotation != null) {
|
||||
PollingSchedule schedule = new PollingSchedule(polledAnnotation.period());
|
||||
schedule.setInitialDelay(polledAnnotation.initialDelay());
|
||||
schedule.setFixedRate(polledAnnotation.fixedRate());
|
||||
schedule.setTimeUnit(polledAnnotation.timeUnit());
|
||||
String inputChannelName = endpointAnnotation.input();
|
||||
MessageChannel inputChannel = this.messageBus.lookupChannel(inputChannelName);
|
||||
if (inputChannel != null) {
|
||||
if (inputChannel instanceof PollableChannel) {
|
||||
PollingDispatcher poller = new PollingDispatcher((PollableChannel) inputChannel, schedule);
|
||||
poller.setMaxMessagesPerPoll(polledAnnotation.maxMessagesPerPoll());
|
||||
endpoint.setSource(poller);
|
||||
}
|
||||
else {
|
||||
endpoint.setSource(inputChannel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
endpoint.setInputChannelName(inputChannelName);
|
||||
}
|
||||
endpoint.setSchedule(schedule);
|
||||
}
|
||||
this.messageBus.registerEndpoint(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,26 +22,23 @@ import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.ConfigurationException;
|
||||
import org.springframework.integration.annotation.Polled;
|
||||
import org.springframework.integration.annotation.ChannelAdapter;
|
||||
import org.springframework.integration.annotation.Pollable;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.dispatcher.DirectChannel;
|
||||
import org.springframework.integration.channel.PollableChannelAdapter;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.endpoint.SourceEndpoint;
|
||||
import org.springframework.integration.message.MethodInvokingSource;
|
||||
import org.springframework.integration.message.MessageSource;
|
||||
import org.springframework.integration.scheduling.PollingSchedule;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.integration.message.MethodInvokingSource;
|
||||
|
||||
/**
|
||||
* Post-processor for classes annotated with {@link MessageSource @MessageSource}.
|
||||
* Post-processor for methods annotated with {@link Pollable @Pollable}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class SourceAnnotationPostProcessor extends AbstractAnnotationMethodPostProcessor<MessageSource<?>> {
|
||||
public class PollableAnnotationPostProcessor extends AbstractAnnotationMethodPostProcessor<MessageSource<?>> {
|
||||
|
||||
public SourceAnnotationPostProcessor(MessageBus messageBus, ClassLoader beanClassLoader) {
|
||||
super(org.springframework.integration.annotation.MessageSource.class, messageBus, beanClassLoader);
|
||||
public PollableAnnotationPostProcessor(MessageBus messageBus, ClassLoader beanClassLoader) {
|
||||
super(Pollable.class, messageBus, beanClassLoader);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,37 +46,25 @@ public class SourceAnnotationPostProcessor extends AbstractAnnotationMethodPostP
|
||||
MethodInvokingSource source = new MethodInvokingSource();
|
||||
source.setObject(bean);
|
||||
source.setMethodName(method.getName());
|
||||
ChannelAdapter channelAdapterAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), ChannelAdapter.class);
|
||||
if (channelAdapterAnnotation != null) {
|
||||
String channelName = channelAdapterAnnotation.value();
|
||||
PollableChannelAdapter adapter = new PollableChannelAdapter(channelName, source, null);
|
||||
this.getMessageBus().registerChannel(channelName, adapter);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
protected MessageSource<?> processResults(List<MessageSource<?>> results) {
|
||||
if (results.size() > 1) {
|
||||
throw new ConfigurationException("At most one @MessageSource annotation is allowed per class.");
|
||||
throw new ConfigurationException("At most one @Pollable annotation is allowed per class.");
|
||||
}
|
||||
return (results.size() == 1) ? results.get(0) : null;
|
||||
}
|
||||
|
||||
public AbstractEndpoint createEndpoint(Object bean, String beanName, Class<?> originalBeanClass,
|
||||
org.springframework.integration.annotation.MessageEndpoint endpointAnnotation) {
|
||||
SourceEndpoint endpoint = new SourceEndpoint((MessageSource<?>) bean);
|
||||
Polled polledAnnotation = AnnotationUtils.findAnnotation(originalBeanClass, Polled.class);
|
||||
int period = polledAnnotation.period();
|
||||
long initialDelay = polledAnnotation.initialDelay();
|
||||
boolean fixedRate = polledAnnotation.fixedRate();
|
||||
PollingSchedule schedule = new PollingSchedule(period);
|
||||
schedule.setInitialDelay(initialDelay);
|
||||
schedule.setFixedRate(fixedRate);
|
||||
endpoint.setSchedule(schedule);
|
||||
String outputChannelName = endpointAnnotation.output();
|
||||
if (!StringUtils.hasText(outputChannelName)) {
|
||||
MessageChannel outputChannel = new DirectChannel();
|
||||
this.getMessageBus().registerChannel(beanName + ".output", outputChannel);
|
||||
endpoint.setTarget(outputChannel);
|
||||
}
|
||||
else {
|
||||
endpoint.setOutputChannelName(outputChannelName);
|
||||
}
|
||||
return endpoint;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,11 +39,12 @@ import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.integration.ConfigurationException;
|
||||
import org.springframework.integration.annotation.ChannelAdapter;
|
||||
import org.springframework.integration.annotation.Concurrency;
|
||||
import org.springframework.integration.annotation.Handler;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.MessageSource;
|
||||
import org.springframework.integration.annotation.MessageTarget;
|
||||
import org.springframework.integration.annotation.Pollable;
|
||||
import org.springframework.integration.annotation.Polled;
|
||||
import org.springframework.integration.annotation.Splitter;
|
||||
import org.springframework.integration.annotation.Transformer;
|
||||
@@ -373,15 +374,14 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageSourceAnnotation() {
|
||||
public void testChannelAdapterAnnotation() {
|
||||
MessageBus messageBus = new DefaultMessageBus();
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
messageBus.registerChannel("testChannel", testChannel);
|
||||
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor(messageBus);
|
||||
postProcessor.afterPropertiesSet();
|
||||
MessageSourceAnnotationTestBean testBean = new MessageSourceAnnotationTestBean();
|
||||
ChannelAdapterAnnotationTestBean testBean = new ChannelAdapterAnnotationTestBean();
|
||||
postProcessor.postProcessAfterInitialization(testBean, "testBean");
|
||||
messageBus.start();
|
||||
PollableChannel testChannel = (PollableChannel) messageBus.lookupChannel("testChannel");
|
||||
Message<?> message = testChannel.receive(1000);
|
||||
assertEquals("test", message.getPayload());
|
||||
messageBus.stop();
|
||||
@@ -526,11 +526,10 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
@MessageEndpoint(output="testChannel")
|
||||
@Polled(period=100)
|
||||
private static class MessageSourceAnnotationTestBean {
|
||||
@ChannelAdapter("testChannel")
|
||||
private static class ChannelAdapterAnnotationTestBean {
|
||||
|
||||
@MessageSource
|
||||
@Pollable
|
||||
public String test() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.endpoint.annotation;
|
||||
|
||||
import org.springframework.integration.annotation.Handler;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.Polled;
|
||||
import org.springframework.integration.annotation.MessageSource;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@MessageEndpoint(output="outputChannel")
|
||||
@Polled(period=100)
|
||||
public class InboundChannelAdapterTestBean {
|
||||
|
||||
@MessageSource
|
||||
public String getName() {
|
||||
return "world";
|
||||
}
|
||||
|
||||
@Handler
|
||||
public String sayHello(String name) {
|
||||
return "hello " + name;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user