Search in sources :

Example 1 with MessageListenerException

use of io.micronaut.messaging.exceptions.MessageListenerException in project micronaut-nats by micronaut-projects.

the class NatsConsumerAdvice method process.

@Override
public void process(BeanDefinition<?> beanDefinition, ExecutableMethod<?, ?> method) {
    if (method.hasAnnotation(NatsListener.class)) {
        AnnotationValue<Subject> subjectAnn = method.getAnnotation(Subject.class);
        if (subjectAnn != null) {
            String subject = subjectAnn.getRequiredValue(String.class);
            String connectionName = method.findAnnotation(NatsConnection.class).flatMap(conn -> conn.get("connection", String.class)).orElse(NatsConnection.DEFAULT_CONNECTION);
            io.micronaut.context.Qualifier<Object> qualifer = beanDefinition.getAnnotationTypeByStereotype("javax.inject.Qualifier").map(type -> Qualifiers.byAnnotation(beanDefinition, type)).orElse(null);
            Class<Object> beanType = (Class<Object>) beanDefinition.getBeanType();
            Class<?> returnTypeClass = method.getReturnType().getType();
            boolean isVoid = returnTypeClass == Void.class || returnTypeClass == void.class;
            Object bean = beanContext.findBean(beanType, qualifer).orElseThrow(() -> new MessageListenerException("Could not find the bean to execute the method " + method));
            Connection connection = beanContext.getBean(Connection.class, Qualifiers.byName(connectionName));
            DefaultExecutableBinder<Message> binder = new DefaultExecutableBinder<>();
            Dispatcher ds = connection.createDispatcher(msg -> {
                BoundExecutable boundExecutable = null;
                try {
                    boundExecutable = binder.bind(method, binderRegistry, msg);
                } catch (Throwable e) {
                    handleException(new NatsListenerException("An error occurred binding the message to the method", e, bean, msg));
                }
                if (boundExecutable != null) {
                    Object returnedValue = boundExecutable.invoke(bean);
                    if (!isVoid && StringUtils.isNotEmpty(msg.getReplyTo())) {
                        byte[] converted = null;
                        if (returnedValue != null) {
                            NatsMessageSerDes serDes = serDesRegistry.findSerdes(method.getReturnType().asArgument()).map(NatsMessageSerDes.class::cast).orElseThrow(() -> new NatsListenerException(String.format("Could not find a serializer for the body argument of type [%s]", returnedValue.getClass().getName()), bean, msg));
                            converted = serDes.serialize(returnedValue);
                        }
                        connection.publish(msg.getReplyTo(), converted);
                    }
                }
            });
            Optional<String> queueOptional = subjectAnn.get("queue", String.class);
            if (queueOptional.isPresent() && !queueOptional.get().isEmpty()) {
                ds.subscribe(subject, queueOptional.get());
            } else {
                ds.subscribe(subject);
            }
            consumerDispatchers.put(ds, subject);
        }
    }
}
Also used : NatsBinderRegistry(io.micronaut.nats.bind.NatsBinderRegistry) BeanContext(io.micronaut.context.BeanContext) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) NatsConnection(io.micronaut.nats.annotation.NatsConnection) Dispatcher(io.nats.client.Dispatcher) NatsMessageSerDes(io.micronaut.nats.serdes.NatsMessageSerDes) ExecutableMethod(io.micronaut.inject.ExecutableMethod) NatsListenerExceptionHandler(io.micronaut.nats.exception.NatsListenerExceptionHandler) Message(io.nats.client.Message) NatsListenerException(io.micronaut.nats.exception.NatsListenerException) NatsMessageSerDesRegistry(io.micronaut.nats.serdes.NatsMessageSerDesRegistry) Map(java.util.Map) Connection(io.nats.client.Connection) BoundExecutable(io.micronaut.core.bind.BoundExecutable) DefaultExecutableBinder(io.micronaut.core.bind.DefaultExecutableBinder) Iterator(java.util.Iterator) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) Singleton(jakarta.inject.Singleton) ExecutableMethodProcessor(io.micronaut.context.processor.ExecutableMethodProcessor) StringUtils(io.micronaut.core.util.StringUtils) NatsListener(io.micronaut.nats.annotation.NatsListener) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Subject(io.micronaut.nats.annotation.Subject) Optional(java.util.Optional) BeanDefinition(io.micronaut.inject.BeanDefinition) Message(io.nats.client.Message) Dispatcher(io.nats.client.Dispatcher) NatsMessageSerDes(io.micronaut.nats.serdes.NatsMessageSerDes) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) DefaultExecutableBinder(io.micronaut.core.bind.DefaultExecutableBinder) NatsConnection(io.micronaut.nats.annotation.NatsConnection) Connection(io.nats.client.Connection) Subject(io.micronaut.nats.annotation.Subject) BoundExecutable(io.micronaut.core.bind.BoundExecutable) NatsListenerException(io.micronaut.nats.exception.NatsListenerException)

Example 2 with MessageListenerException

use of io.micronaut.messaging.exceptions.MessageListenerException in project micronaut-gcp by micronaut-projects.

the class PubSubConsumerAdvice method process.

@Override
public void process(BeanDefinition<?> beanDefinition, ExecutableMethod<?, ?> method) {
    if (beanDefinition.hasDeclaredAnnotation(PubSubListener.class)) {
        AnnotationValue<Subscription> subscriptionAnnotation = method.getAnnotation(Subscription.class);
        io.micronaut.context.Qualifier<Object> qualifier = beanDefinition.getAnnotationTypeByStereotype(Qualifier.class).map(type -> Qualifiers.byAnnotation(beanDefinition, type)).orElse(null);
        boolean hasAckArg = Arrays.stream(method.getArguments()).anyMatch(arg -> Acknowledgement.class.isAssignableFrom(arg.getType()));
        Class<Object> beanType = (Class<Object>) beanDefinition.getBeanType();
        Object bean = beanContext.findBean(beanType, qualifier).orElseThrow(() -> new MessageListenerException("Could not find the bean to execute the method " + method));
        DefaultExecutableBinder<PubSubConsumerState> binder = new DefaultExecutableBinder<>();
        if (subscriptionAnnotation != null) {
            String subscriptionName = subscriptionAnnotation.getRequiredValue(String.class);
            ProjectSubscriptionName projectSubscriptionName = PubSubSubscriptionUtils.toProjectSubscriptionName(subscriptionName, googleCloudConfiguration.getProjectId());
            String defaultContentType = subscriptionAnnotation.stringValue("contentType").orElse(MediaType.APPLICATION_JSON);
            String configuration = subscriptionAnnotation.stringValue("configuration").orElse("");
            MessageReceiver receiver = (PubsubMessage message, AckReplyConsumer ackReplyConsumer) -> {
                String messageContentType = message.getAttributesMap().getOrDefault("Content-Type", "");
                String contentType = Optional.of(messageContentType).filter(StringUtils::isNotEmpty).orElse(defaultContentType);
                DefaultPubSubAcknowledgement pubSubAcknowledgement = new DefaultPubSubAcknowledgement(ackReplyConsumer);
                PubSubConsumerState consumerState = new PubSubConsumerState(message, ackReplyConsumer, projectSubscriptionName, contentType);
                try {
                    BoundExecutable executable = null;
                    try {
                        executable = binder.bind(method, binderRegistry, consumerState);
                    } catch (Exception ex) {
                        handleException(new PubSubMessageReceiverException("Error binding message to the method", ex, bean, consumerState));
                    }
                    // Discard result
                    executable.invoke(bean);
                    if (!hasAckArg) {
                        // if manual ack is not specified we auto ack message after method execution
                        pubSubAcknowledgement.ack();
                    } else {
                        Optional<Object> boundAck = Arrays.stream(executable.getBoundArguments()).filter(o -> (o instanceof DefaultPubSubAcknowledgement)).findFirst();
                        if (boundAck.isPresent()) {
                            DefaultPubSubAcknowledgement manualAck = (DefaultPubSubAcknowledgement) boundAck.get();
                            if (!manualAck.isClientAck()) {
                                logger.warn("Method {} was executed and no message acknowledge detected. Did you forget to invoke ack()/nack()?", method.getName());
                            }
                        }
                    }
                } catch (Exception e) {
                    handleException(new PubSubMessageReceiverException("Error handling message", e, bean, consumerState));
                }
            };
            try {
                this.subscriberFactory.createSubscriber(new SubscriberFactoryConfig(projectSubscriptionName, receiver, configuration, pubSubConfigurationProperties.getSubscribingExecutor()));
            } catch (Exception e) {
                throw new PubSubListenerException("Failed to create subscriber", e);
            }
        }
    }
}
Also used : java.util(java.util) Subscription(io.micronaut.gcp.pubsub.annotation.Subscription) BeanContext(io.micronaut.context.BeanContext) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) LoggerFactory(org.slf4j.LoggerFactory) PubSubSubscriptionUtils(io.micronaut.gcp.pubsub.support.PubSubSubscriptionUtils) ExecutableMethod(io.micronaut.inject.ExecutableMethod) AckReplyConsumer(com.google.cloud.pubsub.v1.AckReplyConsumer) PubSubMessageSerDesRegistry(io.micronaut.gcp.pubsub.serdes.PubSubMessageSerDesRegistry) PubsubMessage(com.google.pubsub.v1.PubsubMessage) MediaType(io.micronaut.http.MediaType) PubSubConfigurationProperties(io.micronaut.gcp.pubsub.configuration.PubSubConfigurationProperties) BoundExecutable(io.micronaut.core.bind.BoundExecutable) ConversionService(io.micronaut.core.convert.ConversionService) DefaultExecutableBinder(io.micronaut.core.bind.DefaultExecutableBinder) PubSubListener(io.micronaut.gcp.pubsub.annotation.PubSubListener) MessageReceiver(com.google.cloud.pubsub.v1.MessageReceiver) Logger(org.slf4j.Logger) GoogleCloudConfiguration(io.micronaut.gcp.GoogleCloudConfiguration) PubSubMessageReceiverException(io.micronaut.gcp.pubsub.exception.PubSubMessageReceiverException) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) Singleton(jakarta.inject.Singleton) Acknowledgement(io.micronaut.messaging.Acknowledgement) ExecutableMethodProcessor(io.micronaut.context.processor.ExecutableMethodProcessor) StringUtils(io.micronaut.core.util.StringUtils) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) ProjectSubscriptionName(com.google.pubsub.v1.ProjectSubscriptionName) BeanDefinition(io.micronaut.inject.BeanDefinition) Qualifier(jakarta.inject.Qualifier) io.micronaut.gcp.pubsub.bind(io.micronaut.gcp.pubsub.bind) PubSubMessageReceiverExceptionHandler(io.micronaut.gcp.pubsub.exception.PubSubMessageReceiverExceptionHandler) PubSubListenerException(io.micronaut.gcp.pubsub.exception.PubSubListenerException) PubsubMessage(com.google.pubsub.v1.PubsubMessage) Acknowledgement(io.micronaut.messaging.Acknowledgement) StringUtils(io.micronaut.core.util.StringUtils) Subscription(io.micronaut.gcp.pubsub.annotation.Subscription) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) AckReplyConsumer(com.google.cloud.pubsub.v1.AckReplyConsumer) ProjectSubscriptionName(com.google.pubsub.v1.ProjectSubscriptionName) PubSubMessageReceiverException(io.micronaut.gcp.pubsub.exception.PubSubMessageReceiverException) DefaultExecutableBinder(io.micronaut.core.bind.DefaultExecutableBinder) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) PubSubMessageReceiverException(io.micronaut.gcp.pubsub.exception.PubSubMessageReceiverException) PubSubListenerException(io.micronaut.gcp.pubsub.exception.PubSubListenerException) MessageReceiver(com.google.cloud.pubsub.v1.MessageReceiver) BoundExecutable(io.micronaut.core.bind.BoundExecutable) PubSubListenerException(io.micronaut.gcp.pubsub.exception.PubSubListenerException)

Example 3 with MessageListenerException

use of io.micronaut.messaging.exceptions.MessageListenerException in project micronaut-jms by micronaut-projects.

the class JMSListenerContainer method registerListener.

/**
 * Registers a {@link JMSListenerContainer} with default concurrency.
 * <p>
 * NOTE: this method is not recommended; instead use the annotation driven
 * {@link io.micronaut.jms.annotations.JMSListener}
 *
 * @param destination the queue or topic name
 * @param listener    the message handler
 * @param clazz       the message type
 */
public void registerListener(String destination, MessageHandler<T> listener, Class<T> clazz) {
    try {
        final Connection connection = connectionPool.createConnection();
        final Session session = connection.createSession(DEFAULT_TRANSACTED, DEFAULT_ACKNOWLEDGE_MODE);
        openConnections.add(connection);
        final MessageConsumer consumer = session.createConsumer(lookupDestination(destination, session));
        consumer.setMessageListener(new MessageHandlerAdapter<>(new ConcurrentMessageHandler<>(listener, new ThreadPoolExecutor(threadPoolSize, maxThreadPoolSize, DEFAULT_KEEP_ALIVE_TIME, SECONDS, new LinkedBlockingQueue<>(DEFAULT_EXECUTOR_QUEUE_SIZE), Executors.defaultThreadFactory())), clazz));
        LOGGER.debug("registered {} listener {} for destination '{}' and class {}", type.name().toLowerCase(), listener, destination, clazz.getName());
    } catch (Exception e) {
        throw new MessageListenerException("Problem registering a MessageConsumer for " + destination, e);
    }
}
Also used : MessageConsumer(javax.jms.MessageConsumer) Connection(javax.jms.Connection) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) JMSException(javax.jms.JMSException) Session(javax.jms.Session)

Example 4 with MessageListenerException

use of io.micronaut.messaging.exceptions.MessageListenerException in project micronaut-jms by micronaut-projects.

the class JMSListenerContainer method registerListener.

/**
 * Internal method used by the {@link JMSListenerContainerFactory} for
 * registering new listeners.
 * <p>
 * NOTE: this method is used internally by the
 * {@link io.micronaut.jms.configuration.AbstractJMSListenerMethodProcessor}
 * and is not recommended for use. Instead the annotation driven
 * {@link io.micronaut.jms.annotations.JMSListener} is preferred.
 *
 * @param destination     the queue or topic name
 * @param listener        the message handler
 * @param clazz           the message type
 * @param transacted      indicates whether the session will use a local transaction
 * @param acknowledgeMode when transacted is false, indicates how messages
 *                        received by the session will be acknowledged
 * @see Session#AUTO_ACKNOWLEDGE
 * @see Session#CLIENT_ACKNOWLEDGE
 * @see Session#DUPS_OK_ACKNOWLEDGE
 */
public void registerListener(String destination, MessageListener listener, // TODO unused
Class<T> clazz, boolean transacted, int acknowledgeMode) {
    try {
        final Connection connection = connectionPool.createConnection();
        final Session session = connection.createSession(transacted, acknowledgeMode);
        openConnections.add(connection);
        final MessageConsumer consumer = session.createConsumer(lookupDestination(destination, session));
        consumer.setMessageListener((message) -> {
            try {
                listener.onMessage(message);
                if (transacted) {
                    session.commit();
                }
            } catch (Exception e) {
                if (transacted) {
                    try {
                        session.rollback();
                    } catch (JMSException | RuntimeException e2) {
                        throw new MessageListenerException("Problem rolling back transaction", e2);
                    }
                }
                throw new MessageListenerException(e.getMessage(), e);
            }
        });
        LOGGER.debug("registered {} listener {} for destination '{}'; " + "transacted: {}, ack mode: {}", type.name().toLowerCase(), listener, destination, transacted, acknowledgeMode);
    } catch (JMSException | RuntimeException e) {
        throw new MessageListenerException("Problem registering a MessageConsumer for " + destination, e);
    }
}
Also used : MessageConsumer(javax.jms.MessageConsumer) Connection(javax.jms.Connection) JMSException(javax.jms.JMSException) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) MessageListenerException(io.micronaut.messaging.exceptions.MessageListenerException) JMSException(javax.jms.JMSException) Session(javax.jms.Session)

Aggregations

MessageListenerException (io.micronaut.messaging.exceptions.MessageListenerException)4 BeanContext (io.micronaut.context.BeanContext)2 ExecutableMethodProcessor (io.micronaut.context.processor.ExecutableMethodProcessor)2 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)2 BoundExecutable (io.micronaut.core.bind.BoundExecutable)2 DefaultExecutableBinder (io.micronaut.core.bind.DefaultExecutableBinder)2 StringUtils (io.micronaut.core.util.StringUtils)2 BeanDefinition (io.micronaut.inject.BeanDefinition)2 ExecutableMethod (io.micronaut.inject.ExecutableMethod)2 Qualifiers (io.micronaut.inject.qualifiers.Qualifiers)2 Singleton (jakarta.inject.Singleton)2 Connection (javax.jms.Connection)2 JMSException (javax.jms.JMSException)2 MessageConsumer (javax.jms.MessageConsumer)2 Session (javax.jms.Session)2 AckReplyConsumer (com.google.cloud.pubsub.v1.AckReplyConsumer)1 MessageReceiver (com.google.cloud.pubsub.v1.MessageReceiver)1 ProjectSubscriptionName (com.google.pubsub.v1.ProjectSubscriptionName)1 PubsubMessage (com.google.pubsub.v1.PubsubMessage)1 ConversionService (io.micronaut.core.convert.ConversionService)1