Search in sources :

Example 1 with KafkaClient

use of io.micronaut.configuration.kafka.annotation.KafkaClient in project micronaut-kafka by micronaut-projects.

the class KafkaProducerFactory method getProducer.

/**
 * Creates a new {@link KafkaProducer} for the given configuration.
 *
 * @param injectionPoint The injection point used to create the bean
 * @param producerConfiguration An optional producer configuration
 * @param <K> The key type
 * @param <V> The value type
 * @return The consumer
 */
@Bean
@Any
public <K, V> Producer<K, V> getProducer(@Nullable InjectionPoint<KafkaProducer<K, V>> injectionPoint, @Nullable @Parameter AbstractKafkaProducerConfiguration<K, V> producerConfiguration) {
    if (injectionPoint == null) {
        if (producerConfiguration != null) {
            Optional<Serializer<K>> keySerializer = producerConfiguration.getKeySerializer();
            Optional<Serializer<V>> valueSerializer = producerConfiguration.getValueSerializer();
            Properties config = producerConfiguration.getConfig();
            if (keySerializer.isPresent() && valueSerializer.isPresent()) {
                Serializer<K> ks = keySerializer.get();
                Serializer<V> vs = valueSerializer.get();
                return new KafkaProducer<>(config, ks, vs);
            } else if (keySerializer.isPresent() || valueSerializer.isPresent()) {
                throw new ConfigurationException("Both the [keySerializer] and [valueSerializer] must be set when setting either");
            } else {
                return new KafkaProducer<>(config);
            }
        } else {
            throw new ConfigurationException("No Kafka configuration specified when using direct instantiation");
        }
    }
    Argument<?> argument;
    if (injectionPoint instanceof FieldInjectionPoint) {
        argument = ((FieldInjectionPoint<?, ?>) injectionPoint).asArgument();
    } else if (injectionPoint instanceof ArgumentInjectionPoint) {
        argument = ((ArgumentInjectionPoint<?, ?>) injectionPoint).getArgument();
    } else {
        throw new ConfigurationException("Cannot directly retrieve KafkaProducer instances. Use @Inject or constructor injection");
    }
    Argument<?> k = argument.getTypeVariable("K").orElse(null);
    Argument<?> v = argument.getTypeVariable("V").orElse(null);
    if (k == null || v == null) {
        throw new ConfigurationException("@KafkaClient used on type missing generic argument values for Key and Value: " + injectionPoint);
    }
    final String id = injectionPoint.getAnnotationMetadata().stringValue(KafkaClient.class).orElse(null);
    return getKafkaProducer(id, null, k, v, false);
}
Also used : KafkaProducer(org.apache.kafka.clients.producer.KafkaProducer) Properties(java.util.Properties) ArgumentInjectionPoint(io.micronaut.inject.ArgumentInjectionPoint) ConfigurationException(io.micronaut.context.exceptions.ConfigurationException) KafkaClient(io.micronaut.configuration.kafka.annotation.KafkaClient) FieldInjectionPoint(io.micronaut.inject.FieldInjectionPoint) Serializer(org.apache.kafka.common.serialization.Serializer) Any(io.micronaut.context.annotation.Any) Bean(io.micronaut.context.annotation.Bean)

Example 2 with KafkaClient

use of io.micronaut.configuration.kafka.annotation.KafkaClient in project micronaut-kafka by micronaut-projects.

the class KafkaClientIntroductionAdvice method intercept.

@SuppressWarnings("unchecked")
@Override
public final Object intercept(MethodInvocationContext<Object, Object> context) {
    if (context.hasAnnotation(KafkaClient.class)) {
        if (!context.hasAnnotation(KafkaClient.class)) {
            throw new IllegalStateException("No @KafkaClient annotation present on method: " + context);
        }
        ProducerState producerState = getProducer(context);
        InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
        try {
            Argument<?> returnType = interceptedMethod.returnTypeValue();
            if (Argument.OBJECT_ARGUMENT.equalsType(returnType)) {
                returnType = Argument.of(RecordMetadata.class);
            }
            switch(interceptedMethod.resultType()) {
                case COMPLETION_STAGE:
                    CompletableFuture<Object> completableFuture = returnCompletableFuture(context, producerState, returnType);
                    return interceptedMethod.handleResult(completableFuture);
                case PUBLISHER:
                    Flux<Object> returnFlowable = returnPublisher(context, producerState, returnType);
                    return interceptedMethod.handleResult(returnFlowable);
                case SYNCHRONOUS:
                    return returnSynchronous(context, producerState);
                default:
                    return interceptedMethod.unsupported();
            }
        } catch (Exception e) {
            return interceptedMethod.handleException(e);
        }
    } else {
        // can't be implemented so proceed
        return context.proceed();
    }
}
Also used : RecordMetadata(org.apache.kafka.clients.producer.RecordMetadata) InterceptedMethod(io.micronaut.aop.InterceptedMethod) KafkaClient(io.micronaut.configuration.kafka.annotation.KafkaClient) MessagingClientException(io.micronaut.messaging.exceptions.MessagingClientException)

Example 3 with KafkaClient

use of io.micronaut.configuration.kafka.annotation.KafkaClient in project micronaut-kafka by micronaut-projects.

the class KafkaClientIntroductionAdvice method buildSendFluxForReactiveValue.

private Flux<Object> buildSendFluxForReactiveValue(MethodInvocationContext<Object, Object> context, ProducerState producerState, Argument<?> returnType, Object value) {
    Flux<?> valueFlowable = Flux.from(Publishers.convertPublisher(value, Publisher.class));
    Class<?> javaReturnType = returnType.getType();
    if (Iterable.class.isAssignableFrom(javaReturnType)) {
        returnType = returnType.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
    }
    boolean transactional = producerState.transactional;
    Producer<?, ?> kafkaProducer = producerState.kafkaProducer;
    if (transactional) {
        LOG.trace("Beginning transaction for producer: {}", producerState.transactionalId);
        kafkaProducer.beginTransaction();
    }
    Argument<?> finalReturnType = returnType;
    Flux<Object> sendFlowable = valueFlowable.flatMap(o -> {
        ProducerRecord record = buildProducerRecord(context, producerState, o);
        LOG.trace("@KafkaClient method [{}] Sending producer record: {}", context, record);
        return producerSend(kafkaProducer, record).map(metadata -> convertResult(metadata, finalReturnType, o, producerState.bodyArgument)).onErrorMap(e -> wrapException(context, e));
    });
    if (transactional) {
        sendFlowable = addTransactionalProcessing(producerState, sendFlowable);
    }
    if (producerState.maxBlock != null) {
        sendFlowable = sendFlowable.timeout(producerState.maxBlock);
    }
    return sendFlowable;
}
Also used : Topic(io.micronaut.configuration.kafka.annotation.Topic) Publishers(io.micronaut.core.async.publisher.Publishers) Bindable(io.micronaut.core.bind.annotation.Bindable) Arrays(java.util.Arrays) BeanContext(io.micronaut.context.BeanContext) BiFunction(java.util.function.BiFunction) LoggerFactory(org.slf4j.LoggerFactory) MessageHeader(io.micronaut.messaging.annotation.MessageHeader) KafkaPartition(io.micronaut.configuration.kafka.annotation.KafkaPartition) InterceptorBean(io.micronaut.aop.InterceptorBean) PreDestroy(javax.annotation.PreDestroy) KafkaPartitionKey(io.micronaut.configuration.kafka.annotation.KafkaPartitionKey) Duration(java.time.Duration) Map(java.util.Map) MessagingClientException(io.micronaut.messaging.exceptions.MessagingClientException) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) KafkaClient(io.micronaut.configuration.kafka.annotation.KafkaClient) Qualifiers(io.micronaut.inject.qualifiers.Qualifiers) AbstractKafkaProducerConfiguration(io.micronaut.configuration.kafka.config.AbstractKafkaProducerConfiguration) RecordMetadata(org.apache.kafka.clients.producer.RecordMetadata) StandardCharsets(java.nio.charset.StandardCharsets) KafkaKey(io.micronaut.configuration.kafka.annotation.KafkaKey) KafkaTimestamp(io.micronaut.configuration.kafka.annotation.KafkaTimestamp) Objects(java.util.Objects) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) SerdeRegistry(io.micronaut.configuration.kafka.serde.SerdeRegistry) Header(org.apache.kafka.common.header.Header) MethodInvocationContext(io.micronaut.aop.MethodInvocationContext) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Optional(java.util.Optional) MessageBody(io.micronaut.messaging.annotation.MessageBody) ProducerRecord(org.apache.kafka.clients.producer.ProducerRecord) Headers(org.apache.kafka.common.header.Headers) CompletableFuture(java.util.concurrent.CompletableFuture) RecordHeader(org.apache.kafka.common.header.internals.RecordHeader) InterceptedMethod(io.micronaut.aop.InterceptedMethod) Function(java.util.function.Function) ExecutableMethod(io.micronaut.inject.ExecutableMethod) ArrayList(java.util.ArrayList) RecordHeaders(org.apache.kafka.common.header.internals.RecordHeaders) ByteArraySerializer(org.apache.kafka.common.serialization.ByteArraySerializer) MethodInterceptor(io.micronaut.aop.MethodInterceptor) Nullable(io.micronaut.core.annotation.Nullable) ReturnType(io.micronaut.core.type.ReturnType) Argument(io.micronaut.core.type.Argument) LinkedList(java.util.LinkedList) ConversionService(io.micronaut.core.convert.ConversionService) ProducerConfig(org.apache.kafka.clients.producer.ProducerConfig) Subscriber(org.reactivestreams.Subscriber) KafkaProducerConfiguration(io.micronaut.configuration.kafka.config.KafkaProducerConfiguration) Utils(org.apache.kafka.common.utils.Utils) Logger(org.slf4j.Logger) Properties(java.util.Properties) Producer(org.apache.kafka.clients.producer.Producer) Publisher(org.reactivestreams.Publisher) Mono(reactor.core.publisher.Mono) TimeUnit(java.util.concurrent.TimeUnit) Flux(reactor.core.publisher.Flux) Serializer(org.apache.kafka.common.serialization.Serializer) Subscription(org.reactivestreams.Subscription) DefaultKafkaProducerConfiguration(io.micronaut.configuration.kafka.config.DefaultKafkaProducerConfiguration) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) ProducerRecord(org.apache.kafka.clients.producer.ProducerRecord) Publisher(org.reactivestreams.Publisher)

Aggregations

KafkaClient (io.micronaut.configuration.kafka.annotation.KafkaClient)3 InterceptedMethod (io.micronaut.aop.InterceptedMethod)2 MessagingClientException (io.micronaut.messaging.exceptions.MessagingClientException)2 RecordMetadata (org.apache.kafka.clients.producer.RecordMetadata)2 InterceptorBean (io.micronaut.aop.InterceptorBean)1 MethodInterceptor (io.micronaut.aop.MethodInterceptor)1 MethodInvocationContext (io.micronaut.aop.MethodInvocationContext)1 KafkaKey (io.micronaut.configuration.kafka.annotation.KafkaKey)1 KafkaPartition (io.micronaut.configuration.kafka.annotation.KafkaPartition)1 KafkaPartitionKey (io.micronaut.configuration.kafka.annotation.KafkaPartitionKey)1 KafkaTimestamp (io.micronaut.configuration.kafka.annotation.KafkaTimestamp)1 Topic (io.micronaut.configuration.kafka.annotation.Topic)1 AbstractKafkaProducerConfiguration (io.micronaut.configuration.kafka.config.AbstractKafkaProducerConfiguration)1 DefaultKafkaProducerConfiguration (io.micronaut.configuration.kafka.config.DefaultKafkaProducerConfiguration)1 KafkaProducerConfiguration (io.micronaut.configuration.kafka.config.KafkaProducerConfiguration)1 SerdeRegistry (io.micronaut.configuration.kafka.serde.SerdeRegistry)1 BeanContext (io.micronaut.context.BeanContext)1 Any (io.micronaut.context.annotation.Any)1 Bean (io.micronaut.context.annotation.Bean)1 ConfigurationException (io.micronaut.context.exceptions.ConfigurationException)1