Search in sources :

Example 81 with Message

use of org.springframework.messaging.Message in project spring-integration by spring-projects.

the class MessagingMethodInvokerHelper method findHandlerMethodsForTarget.

private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(final Object targetObject, final Class<? extends Annotation> annotationType, final String methodName, final boolean requiresReply) {
    Map<String, Map<Class<?>, HandlerMethod>> handlerMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> candidateMessageMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMessageMethods = new HashMap<>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<>();
    final AtomicReference<Class<?>> ambiguousFallbackMessageGenericType = new AtomicReference<>();
    final Class<?> targetClass = getTargetClass(targetObject);
    MethodFilter methodFilter = new UniqueMethodFilter(targetClass);
    ReflectionUtils.doWithMethods(targetClass, method1 -> {
        boolean matchesAnnotation = false;
        if (method1.isBridge()) {
            return;
        }
        if (isMethodDefinedOnObjectClass(method1)) {
            return;
        }
        if (method1.getDeclaringClass().equals(Proxy.class)) {
            return;
        }
        if (annotationType != null && AnnotationUtils.findAnnotation(method1, annotationType) != null) {
            matchesAnnotation = true;
        } else if (!Modifier.isPublic(method1.getModifiers())) {
            return;
        }
        if (requiresReply && void.class.equals(method1.getReturnType())) {
            return;
        }
        if (methodName != null && !methodName.equals(method1.getName())) {
            return;
        }
        if (methodName == null && ObjectUtils.containsElement(new String[] { "start", "stop", "isRunning" }, method1.getName())) {
            return;
        }
        HandlerMethod handlerMethod1;
        try {
            method1 = AopUtils.selectInvocableMethod(method1, org.springframework.util.ClassUtils.getUserClass(targetObject));
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method1);
            handlerMethod1 = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method1, handlerMethod1);
        } catch (IneligibleMethodException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling " + e.getMessage() + ".");
            }
            return;
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling.", e);
            }
            return;
        }
        if (AnnotationUtils.getAnnotation(method1, Default.class) != null) {
            Assert.state(this.defaultHandlerMethod == null, () -> "Only one method can be @Default, but there are more for: " + targetObject);
            this.defaultHandlerMethod = handlerMethod1;
        }
        Class<?> targetParameterType = handlerMethod1.getTargetParameterType();
        if (matchesAnnotation || annotationType == null) {
            if (handlerMethod1.isMessageMethod()) {
                if (candidateMessageMethods.containsKey(targetParameterType)) {
                    throw new IllegalArgumentException("Found more than one method match for type " + "[Message<" + targetParameterType + ">]");
                }
                candidateMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (candidateMethods.containsKey(targetParameterType)) {
                    String exceptionMessage = "Found more than one method match for ";
                    if (Void.class.equals(targetParameterType)) {
                        exceptionMessage += "empty parameter for 'payload'";
                    } else {
                        exceptionMessage += "type [" + targetParameterType + "]";
                    }
                    throw new IllegalArgumentException(exceptionMessage);
                }
                candidateMethods.put(targetParameterType, handlerMethod1);
            }
        } else {
            if (handlerMethod1.isMessageMethod()) {
                if (fallbackMessageMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackMessageGenericType.compareAndSet(null, targetParameterType);
                }
                fallbackMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod1);
            }
        }
    }, methodFilter);
    if (candidateMethods.isEmpty() && candidateMessageMethods.isEmpty() && fallbackMethods.isEmpty() && fallbackMessageMethods.isEmpty()) {
        findSingleSpecifMethodOnInterfacesIfProxy(targetObject, methodName, candidateMessageMethods, candidateMethods);
    }
    if (!candidateMethods.isEmpty() || !candidateMessageMethods.isEmpty()) {
        handlerMethods.put(CANDIDATE_METHODS, candidateMethods);
        handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
        return handlerMethods;
    }
    if ((ambiguousFallbackType.get() != null || ambiguousFallbackMessageGenericType.get() != null) && ServiceActivator.class.equals(annotationType)) {
        /*
			 * When there are ambiguous fallback methods,
			 * a Service Activator can finally fallback to RequestReplyExchanger.exchange(m).
			 * Ambiguous means > 1 method that takes the same payload type, or > 1 method
			 * that takes a Message with the same generic type.
			 */
        List<Method> frameworkMethods = new ArrayList<>();
        Class<?>[] allInterfaces = org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
        for (Class<?> iface : allInterfaces) {
            try {
                if ("org.springframework.integration.gateway.RequestReplyExchanger".equals(iface.getName())) {
                    frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
                    if (logger.isDebugEnabled()) {
                        logger.debug(targetObject.getClass() + ": Ambiguous fallback methods; using RequestReplyExchanger.exchange()");
                    }
                }
            } catch (Exception e) {
            // should never happen (but would fall through to errors below)
            }
        }
        if (frameworkMethods.size() == 1) {
            Method method = org.springframework.util.ClassUtils.getMostSpecificMethod(frameworkMethods.get(0), targetObject.getClass());
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method);
            HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method, handlerMethod);
            handlerMethods.put(CANDIDATE_METHODS, Collections.singletonMap(Object.class, handlerMethod));
            handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
            return handlerMethods;
        }
    }
    Assert.state(!fallbackMethods.isEmpty() || !fallbackMessageMethods.isEmpty(), "Target object of type [" + this.targetObject.getClass() + "] has no eligible methods for handling Messages.");
    Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType + "] for method match: " + fallbackMethods.values());
    Assert.isNull(ambiguousFallbackMessageGenericType.get(), "Found ambiguous parameter type [" + ambiguousFallbackMessageGenericType + "] for method match: " + fallbackMethods.values());
    handlerMethods.put(CANDIDATE_METHODS, fallbackMethods);
    handlerMethods.put(CANDIDATE_MESSAGE_METHODS, fallbackMessageMethods);
    return handlerMethods;
}
Also used : MutableMessage(org.springframework.integration.support.MutableMessage) Message(org.springframework.messaging.Message) HashMap(java.util.HashMap) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) ArrayList(java.util.ArrayList) MethodFilter(org.springframework.util.ReflectionUtils.MethodFilter) AnnotatedMethodFilter(org.springframework.integration.util.AnnotatedMethodFilter) FixedMethodFilter(org.springframework.integration.util.FixedMethodFilter) UniqueMethodFilter(org.springframework.integration.util.UniqueMethodFilter) AtomicReference(java.util.concurrent.atomic.AtomicReference) Method(java.lang.reflect.Method) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) UniqueMethodFilter(org.springframework.integration.util.UniqueMethodFilter) Default(org.springframework.integration.annotation.Default) ServiceActivator(org.springframework.integration.annotation.ServiceActivator) InvocableHandlerMethod(org.springframework.messaging.handler.invocation.InvocableHandlerMethod) ConversionFailedException(org.springframework.core.convert.ConversionFailedException) MessageHandlingException(org.springframework.messaging.MessageHandlingException) EvaluationException(org.springframework.expression.EvaluationException) ConverterNotFoundException(org.springframework.core.convert.ConverterNotFoundException) MessageConversionException(org.springframework.messaging.converter.MessageConversionException) MethodArgumentResolutionException(org.springframework.messaging.handler.invocation.MethodArgumentResolutionException) NoSuchBeanDefinitionException(org.springframework.beans.factory.NoSuchBeanDefinitionException) Map(java.util.Map) HashMap(java.util.HashMap)

Example 82 with Message

use of org.springframework.messaging.Message in project spring-integration by spring-projects.

the class AbstractRequestHandlerAdvice method invoke.

@Override
public final Object invoke(final MethodInvocation invocation) throws Throwable {
    Method method = invocation.getMethod();
    Object[] arguments = invocation.getArguments();
    boolean isMessageMethod = (method.getName().equals("handleRequestMessage") || method.getName().equals("handleMessage")) && (arguments.length == 1 && arguments[0] instanceof Message);
    Object invocationThis = invocation.getThis();
    if (!isMessageMethod) {
        boolean isMessageHandler = invocationThis != null && MessageHandler.class.isAssignableFrom(invocationThis.getClass());
        if (!isMessageHandler && this.logger.isWarnEnabled()) {
            String clazzName = invocationThis == null ? method.getDeclaringClass().getName() : invocationThis.getClass().getName();
            this.logger.warn("This advice " + this.getClass().getName() + " can only be used for MessageHandlers; an attempt to advise method '" + method.getName() + "' in '" + clazzName + "' is ignored");
        }
        return invocation.proceed();
    } else {
        Message<?> message = (Message<?>) arguments[0];
        try {
            return doInvoke(new ExecutionCallback() {

                @Override
                public Object execute() throws Exception {
                    try {
                        return invocation.proceed();
                    } catch (Exception e) {
                        // NOSONAR - catch necessary so we can wrap Errors
                        throw e;
                    } catch (Throwable e) {
                        // NOSONAR - ok to catch; unwrapped and rethrown below
                        throw new ThrowableHolderException(e);
                    }
                }

                @Override
                public Object cloneAndExecute() throws Exception {
                    try {
                        /*
				 			* If we don't copy the invocation carefully it won't keep a reference to the other
				 			* interceptors in the chain.
				 			*/
                        if (invocation instanceof ProxyMethodInvocation) {
                            return ((ProxyMethodInvocation) invocation).invocableClone().proceed();
                        } else {
                            throw new IllegalStateException("MethodInvocation of the wrong type detected - this should not happen with Spring AOP," + " so please raise an issue if you see this exception");
                        }
                    } catch (Exception e) {
                        // NOSONAR - catch necessary so we can wrap Errors
                        throw e;
                    } catch (Throwable e) {
                        // NOSONAR - ok to catch; unwrapped and rethrown below
                        throw new ThrowableHolderException(e);
                    }
                }
            }, invocationThis, message);
        } catch (Exception e) {
            throw this.unwrapThrowableIfNecessary(e);
        }
    }
}
Also used : Message(org.springframework.messaging.Message) MessageHandler(org.springframework.messaging.MessageHandler) AbstractReplyProducingMessageHandler(org.springframework.integration.handler.AbstractReplyProducingMessageHandler) Method(java.lang.reflect.Method) ProxyMethodInvocation(org.springframework.aop.ProxyMethodInvocation)

Example 83 with Message

use of org.springframework.messaging.Message in project spring-integration by spring-projects.

the class ScatterGatherHandler method doInit.

@Override
protected void doInit() {
    if (this.gatherChannel == null) {
        this.gatherChannel = new FixedSubscriberChannel(this.gatherer);
    } else {
        if (this.gatherChannel instanceof SubscribableChannel) {
            this.gatherEndpoint = new EventDrivenConsumer((SubscribableChannel) this.gatherChannel, this.gatherer);
        } else if (this.gatherChannel instanceof PollableChannel) {
            this.gatherEndpoint = new PollingConsumer((PollableChannel) this.gatherChannel, this.gatherer);
            ((PollingConsumer) this.gatherEndpoint).setReceiveTimeout(this.gatherTimeout);
        } else {
            throw new MessagingException("Unsupported 'replyChannel' type [" + this.gatherChannel.getClass() + "]." + "SubscribableChannel or PollableChannel type are supported.");
        }
        this.gatherEndpoint.setBeanFactory(this.getBeanFactory());
        this.gatherEndpoint.afterPropertiesSet();
    }
    ((MessageProducer) this.gatherer).setOutputChannel(new FixedSubscriberChannel(message -> {
        MessageHeaders headers = message.getHeaders();
        if (headers.containsKey(GATHER_RESULT_CHANNEL)) {
            Object gatherResultChannel = headers.get(GATHER_RESULT_CHANNEL);
            if (gatherResultChannel instanceof MessageChannel) {
                messagingTemplate.send((MessageChannel) gatherResultChannel, message);
            } else if (gatherResultChannel instanceof String) {
                messagingTemplate.send((String) gatherResultChannel, message);
            }
        } else {
            throw new MessageDeliveryException(message, "The 'gatherResultChannel' header is required to delivery gather result.");
        }
    }));
    this.replyChannelRegistry = getBeanFactory().getBean(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME, HeaderChannelRegistry.class);
}
Also used : QueueChannel(org.springframework.integration.channel.QueueChannel) MessagingException(org.springframework.messaging.MessagingException) AbstractEndpoint(org.springframework.integration.endpoint.AbstractEndpoint) HeaderChannelRegistry(org.springframework.integration.support.channel.HeaderChannelRegistry) ClassUtils(org.springframework.util.ClassUtils) AopUtils(org.springframework.aop.support.AopUtils) AbstractReplyProducingMessageHandler(org.springframework.integration.handler.AbstractReplyProducingMessageHandler) SubscribableChannel(org.springframework.messaging.SubscribableChannel) MessageProducer(org.springframework.integration.core.MessageProducer) PollingConsumer(org.springframework.integration.endpoint.PollingConsumer) MessageChannel(org.springframework.messaging.MessageChannel) MessageHeaders(org.springframework.messaging.MessageHeaders) IntegrationContextUtils(org.springframework.integration.context.IntegrationContextUtils) Lifecycle(org.springframework.context.Lifecycle) MessageDeliveryException(org.springframework.messaging.MessageDeliveryException) EventDrivenConsumer(org.springframework.integration.endpoint.EventDrivenConsumer) MessageHandler(org.springframework.messaging.MessageHandler) FixedSubscriberChannel(org.springframework.integration.channel.FixedSubscriberChannel) Message(org.springframework.messaging.Message) PollableChannel(org.springframework.messaging.PollableChannel) Assert(org.springframework.util.Assert) EventDrivenConsumer(org.springframework.integration.endpoint.EventDrivenConsumer) PollingConsumer(org.springframework.integration.endpoint.PollingConsumer) MessagingException(org.springframework.messaging.MessagingException) MessageDeliveryException(org.springframework.messaging.MessageDeliveryException) HeaderChannelRegistry(org.springframework.integration.support.channel.HeaderChannelRegistry) MessageChannel(org.springframework.messaging.MessageChannel) PollableChannel(org.springframework.messaging.PollableChannel) MessageProducer(org.springframework.integration.core.MessageProducer) MessageHeaders(org.springframework.messaging.MessageHeaders) SubscribableChannel(org.springframework.messaging.SubscribableChannel) FixedSubscriberChannel(org.springframework.integration.channel.FixedSubscriberChannel)

Example 84 with Message

use of org.springframework.messaging.Message in project spring-integration by spring-projects.

the class AbstractMessageSplitter method handleRequestMessage.

@Override
@SuppressWarnings("unchecked")
protected final Object handleRequestMessage(Message<?> message) {
    Object result = this.splitMessage(message);
    // return null if 'null'
    if (result == null) {
        return null;
    }
    boolean reactive = getOutputChannel() instanceof ReactiveStreamsSubscribableChannel;
    setAsync(reactive);
    Iterator<Object> iterator = null;
    Flux<Object> flux = null;
    final int sequenceSize;
    if (result instanceof Iterable<?>) {
        Iterable<Object> iterable = (Iterable<Object>) result;
        sequenceSize = obtainSizeIfPossible(iterable);
        if (reactive) {
            flux = Flux.fromIterable(iterable);
        } else {
            iterator = iterable.iterator();
        }
    } else if (result.getClass().isArray()) {
        Object[] items = (Object[]) result;
        sequenceSize = items.length;
        if (reactive) {
            flux = Flux.fromArray(items);
        } else {
            iterator = Arrays.asList(items).iterator();
        }
    } else if (result instanceof Iterator<?>) {
        Iterator<Object> iter = (Iterator<Object>) result;
        sequenceSize = obtainSizeIfPossible(iter);
        if (reactive) {
            flux = Flux.fromIterable(() -> iter);
        } else {
            iterator = iter;
        }
    } else if (result instanceof Stream<?>) {
        Stream<Object> stream = ((Stream<Object>) result);
        sequenceSize = 0;
        if (reactive) {
            flux = Flux.fromStream(stream);
        } else {
            iterator = stream.iterator();
        }
    } else if (result instanceof Publisher<?>) {
        Publisher<Object> publisher = (Publisher<Object>) result;
        sequenceSize = 0;
        if (reactive) {
            flux = Flux.from(publisher);
        } else {
            iterator = Flux.from((Publisher<Object>) result).toIterable().iterator();
        }
    } else {
        sequenceSize = 1;
        if (reactive) {
            flux = Flux.just(result);
        } else {
            iterator = Collections.singleton(result).iterator();
        }
    }
    if (iterator != null && !iterator.hasNext()) {
        return null;
    }
    Map<String, Object> messageHeaders = message.getHeaders();
    if (willAddHeaders(message)) {
        messageHeaders = new HashMap<>(messageHeaders);
        addHeaders(message, messageHeaders);
    }
    final Map<String, Object> headers = messageHeaders;
    final Object correlationId = message.getHeaders().getId();
    final AtomicInteger sequenceNumber = new AtomicInteger(1);
    Function<Object, AbstractIntegrationMessageBuilder<?>> messageBuilderFunction = object -> createBuilder(object, headers, correlationId, sequenceNumber.getAndIncrement(), sequenceSize);
    if (reactive) {
        return flux.map(messageBuilderFunction);
    } else {
        return new FunctionIterator<>(iterator, messageBuilderFunction);
    }
}
Also used : Arrays(java.util.Arrays) Iterator(java.util.Iterator) Collection(java.util.Collection) Publisher(org.reactivestreams.Publisher) AbstractReplyProducingMessageHandler(org.springframework.integration.handler.AbstractReplyProducingMessageHandler) HashMap(java.util.HashMap) ReactiveStreamsSubscribableChannel(org.springframework.integration.channel.ReactiveStreamsSubscribableChannel) Function(java.util.function.Function) Flux(reactor.core.publisher.Flux) Stream(java.util.stream.Stream) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Closeable(java.io.Closeable) Map(java.util.Map) Message(org.springframework.messaging.Message) AbstractIntegrationMessageBuilder(org.springframework.integration.support.AbstractIntegrationMessageBuilder) Collections(java.util.Collections) FunctionIterator(org.springframework.integration.util.FunctionIterator) FunctionIterator(org.springframework.integration.util.FunctionIterator) ReactiveStreamsSubscribableChannel(org.springframework.integration.channel.ReactiveStreamsSubscribableChannel) Publisher(org.reactivestreams.Publisher) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AbstractIntegrationMessageBuilder(org.springframework.integration.support.AbstractIntegrationMessageBuilder) Iterator(java.util.Iterator) FunctionIterator(org.springframework.integration.util.FunctionIterator) Stream(java.util.stream.Stream)

Example 85 with Message

use of org.springframework.messaging.Message in project spring-integration by spring-projects.

the class MessageGroupQueue method drainTo.

@Override
public int drainTo(Collection<? super Message<?>> collection, int maxElements) {
    Assert.notNull(collection, "'collection' must not be null");
    int originalSize = collection.size();
    ArrayList<Message<?>> list = new ArrayList<Message<?>>();
    final Lock storeLock = this.storeLock;
    try {
        storeLock.lockInterruptibly();
        try {
            Message<?> message = this.messageGroupStore.pollMessageFromGroup(this.groupId);
            for (int i = 0; i < maxElements && message != null; i++) {
                list.add(message);
                message = this.messageGroupStore.pollMessageFromGroup(this.groupId);
            }
            this.messageStoreNotFull.signal();
        } finally {
            storeLock.unlock();
        }
    } catch (InterruptedException e) {
        this.logger.warn("Queue may not have drained completely since this operation was interrupted", e);
        Thread.currentThread().interrupt();
    }
    collection.addAll(list);
    return collection.size() - originalSize;
}
Also used : Message(org.springframework.messaging.Message) ArrayList(java.util.ArrayList) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Lock(java.util.concurrent.locks.Lock)

Aggregations

Message (org.springframework.messaging.Message)597 Test (org.junit.Test)423 GenericMessage (org.springframework.messaging.support.GenericMessage)272 QueueChannel (org.springframework.integration.channel.QueueChannel)189 MessageChannel (org.springframework.messaging.MessageChannel)128 ArrayList (java.util.ArrayList)113 BeanFactory (org.springframework.beans.factory.BeanFactory)85 CountDownLatch (java.util.concurrent.CountDownLatch)80 DirectChannel (org.springframework.integration.channel.DirectChannel)69 AtomicReference (java.util.concurrent.atomic.AtomicReference)68 Test (org.junit.jupiter.api.Test)65 MessageHandler (org.springframework.messaging.MessageHandler)58 List (java.util.List)56 PollableChannel (org.springframework.messaging.PollableChannel)56 ErrorMessage (org.springframework.messaging.support.ErrorMessage)52 Matchers.containsString (org.hamcrest.Matchers.containsString)50 MessagingException (org.springframework.messaging.MessagingException)50 ConfigurableApplicationContext (org.springframework.context.ConfigurableApplicationContext)43 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)41 Assert.assertEquals (org.junit.Assert.assertEquals)40