io.micronaut.configuration.rabbitmq.intercept.RabbitMQConsumerAdvice Maven / Gradle / Ivy
/*
* Copyright 2017-2018 original 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 io.micronaut.configuration.rabbitmq.intercept;
import com.rabbitmq.client.*;
import io.micronaut.configuration.rabbitmq.annotation.Queue;
import io.micronaut.configuration.rabbitmq.annotation.RabbitListener;
import io.micronaut.configuration.rabbitmq.annotation.RabbitProperty;
import io.micronaut.configuration.rabbitmq.bind.RabbitBinderRegistry;
import io.micronaut.configuration.rabbitmq.bind.RabbitMessageCloseable;
import io.micronaut.configuration.rabbitmq.bind.RabbitConsumerState;
import io.micronaut.configuration.rabbitmq.connect.ChannelPool;
import io.micronaut.configuration.rabbitmq.exception.RabbitListenerException;
import io.micronaut.configuration.rabbitmq.exception.RabbitListenerExceptionHandler;
import io.micronaut.configuration.rabbitmq.serdes.RabbitMessageSerDes;
import io.micronaut.configuration.rabbitmq.serdes.RabbitMessageSerDesRegistry;
import io.micronaut.context.BeanContext;
import io.micronaut.context.processor.ExecutableMethodProcessor;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.bind.BoundExecutable;
import io.micronaut.core.bind.DefaultExecutableBinder;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.BeanDefinition;
import io.micronaut.inject.ExecutableMethod;
import io.micronaut.inject.qualifiers.Qualifiers;
import io.micronaut.messaging.Acknowledgement;
import io.micronaut.messaging.exceptions.MessageAcknowledgementException;
import io.micronaut.messaging.exceptions.MessageListenerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PreDestroy;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.*;
/**
* An {@link ExecutableMethodProcessor} that will process all beans annotated
* with {@link RabbitListener} and create and subscribe the relevant methods
* as consumers to RabbitMQ queues.
*
* @author James Kleeh
* @since 1.1.0
*/
@Singleton
public class RabbitMQConsumerAdvice implements ExecutableMethodProcessor, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(RabbitMQConsumerAdvice.class);
private final BeanContext beanContext;
private final ChannelPool channelPool;
private final RabbitBinderRegistry binderRegistry;
private final RabbitListenerExceptionHandler exceptionHandler;
private final RabbitMessageSerDesRegistry serDesRegistry;
private final ConversionService conversionService;
private final List consumerChannels = new ArrayList<>();
/**
* Default constructor.
*
* @param beanContext The bean context
* @param channelPool The pool to retrieve channels from
* @param binderRegistry The registry to bind arguments to the method
* @param exceptionHandler The exception handler to use if the consumer isn't a handler
* @param serDesRegistry The serialization/deserialization registry
* @param conversionService The service to convert consume argument values
*/
public RabbitMQConsumerAdvice(BeanContext beanContext,
ChannelPool channelPool,
RabbitBinderRegistry binderRegistry,
RabbitListenerExceptionHandler exceptionHandler,
RabbitMessageSerDesRegistry serDesRegistry,
ConversionService conversionService) {
this.beanContext = beanContext;
this.channelPool = channelPool;
this.binderRegistry = binderRegistry;
this.exceptionHandler = exceptionHandler;
this.serDesRegistry = serDesRegistry;
this.conversionService = conversionService;
}
@Override
public void process(BeanDefinition> beanDefinition, ExecutableMethod, ?> method) {
AnnotationValue queueAnn = method.getAnnotation(Queue.class);
if (queueAnn != null) {
String queue = queueAnn.getRequiredValue(String.class);
String clientTag = method.getDeclaringType().getSimpleName() + '#' + method.toString();
boolean reQueue = queueAnn.getRequiredValue("reQueue", boolean.class);
boolean exclusive = queueAnn.getRequiredValue("exclusive", boolean.class);
boolean hasAckArg = Arrays.stream(method.getArguments())
.anyMatch(arg -> Acknowledgement.class.isAssignableFrom(arg.getType()));
Channel channel = getChannel();
consumerChannels.add(channel);
Map arguments = new HashMap<>();
List> propertyAnnotations = method.getAnnotationValuesByType(RabbitProperty.class);
Collections.reverse(propertyAnnotations); //set the values in the class first so methods can override
propertyAnnotations.forEach((prop) -> {
String name = prop.getRequiredValue("name", String.class);
String value = prop.getValue(String.class).orElse(null);
Class type = prop.get("type", Class.class).orElse(null);
if (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) {
if (type != null && type != Void.class) {
Optional © 2015 - 2025 Weber Informatics LLC | Privacy Policy