Search in sources :

Example 1 with QuarkusMediatorConfiguration

use of io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration in project quarkus by quarkusio.

the class SmallRyeReactiveMessagingProcessor method build.

@BuildStep
@Record(STATIC_INIT)
public void build(SmallRyeReactiveMessagingRecorder recorder, RecorderContext recorderContext, BuildProducer<SyntheticBeanBuildItem> syntheticBeans, List<MediatorBuildItem> mediatorMethods, List<InjectedEmitterBuildItem> emitterFields, List<InjectedChannelBuildItem> channelFields, BuildProducer<GeneratedClassBuildItem> generatedClass, BuildProducer<ReflectiveClassBuildItem> reflectiveClass, ReactiveMessagingConfiguration conf) {
    ClassOutput classOutput = new GeneratedClassGizmoAdaptor(generatedClass, true);
    List<QuarkusMediatorConfiguration> mediatorConfigurations = new ArrayList<>(mediatorMethods.size());
    List<WorkerConfiguration> workerConfigurations = new ArrayList<>();
    List<EmitterConfiguration> emittersConfigurations = new ArrayList<>();
    List<ChannelConfiguration> channelConfigurations = new ArrayList<>();
    /*
         * Go through the collected MediatorMethods and build up the corresponding MediaConfiguration
         * This includes generating an invoker for each method
         * The configuration will then be captured and used at static init time to push data into smallrye
         */
    for (MediatorBuildItem mediatorMethod : mediatorMethods) {
        MethodInfo methodInfo = mediatorMethod.getMethod();
        BeanInfo bean = mediatorMethod.getBean();
        if (methodInfo.hasAnnotation(BLOCKING) || methodInfo.hasAnnotation(SMALLRYE_BLOCKING) || methodInfo.hasAnnotation(TRANSACTIONAL)) {
            // Just in case both annotation are used, use @Blocking value.
            String poolName = Blocking.DEFAULT_WORKER_POOL;
            // If the method is annotated with the SmallRye Reactive Messaging @Blocking, extract the worker pool name if any
            if (methodInfo.hasAnnotation(ReactiveMessagingDotNames.BLOCKING)) {
                AnnotationInstance blocking = methodInfo.annotation(ReactiveMessagingDotNames.BLOCKING);
                poolName = blocking.value() == null ? Blocking.DEFAULT_WORKER_POOL : blocking.value().asString();
            }
            workerConfigurations.add(new WorkerConfiguration(methodInfo.declaringClass().toString(), methodInfo.name(), poolName));
        }
        try {
            boolean isSuspendMethod = isSuspendMethod(methodInfo);
            QuarkusMediatorConfiguration mediatorConfiguration = QuarkusMediatorConfigurationUtil.create(methodInfo, isSuspendMethod, bean, recorderContext, Thread.currentThread().getContextClassLoader(), conf.strict);
            mediatorConfigurations.add(mediatorConfiguration);
            String generatedInvokerName = generateInvoker(bean, methodInfo, isSuspendMethod, mediatorConfiguration, classOutput);
            /*
                 * We need to register the invoker's constructor for reflection since it will be called inside smallrye.
                 * We could potentially lift this restriction with some extra CDI bean generation, but it's probably not worth
                 * it
                 */
            reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, generatedInvokerName));
            mediatorConfiguration.setInvokerClass((Class<? extends Invoker>) recorderContext.classProxy(generatedInvokerName));
        } catch (IllegalArgumentException e) {
            // needed to pass the TCK
            throw new DeploymentException(e);
        }
    }
    for (InjectedEmitterBuildItem it : emitterFields) {
        emittersConfigurations.add(it.getEmitterConfig());
    }
    for (InjectedChannelBuildItem it : channelFields) {
        channelConfigurations.add(it.getChannelConfig());
    }
    syntheticBeans.produce(SyntheticBeanBuildItem.configure(SmallRyeReactiveMessagingContext.class).supplier(recorder.createContext(mediatorConfigurations, workerConfigurations, emittersConfigurations, channelConfigurations)).done());
}
Also used : InjectedChannelBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedChannelBuildItem) BeanInfo(io.quarkus.arc.processor.BeanInfo) ArrayList(java.util.ArrayList) ChannelConfiguration(io.smallrye.reactive.messaging.providers.extension.ChannelConfiguration) GeneratedClassGizmoAdaptor(io.quarkus.deployment.GeneratedClassGizmoAdaptor) EmitterConfiguration(io.smallrye.reactive.messaging.EmitterConfiguration) MediatorBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.MediatorBuildItem) QuarkusMediatorConfiguration(io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration) WorkerConfiguration(io.quarkus.smallrye.reactivemessaging.runtime.WorkerConfiguration) ClassOutput(io.quarkus.gizmo.ClassOutput) InjectedEmitterBuildItem(io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedEmitterBuildItem) MethodInfo(org.jboss.jandex.MethodInfo) DeploymentException(javax.enterprise.inject.spi.DeploymentException) SmallRyeReactiveMessagingContext(io.quarkus.smallrye.reactivemessaging.runtime.SmallRyeReactiveMessagingRecorder.SmallRyeReactiveMessagingContext) AnnotationInstance(org.jboss.jandex.AnnotationInstance) ReflectiveClassBuildItem(io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem) BuildStep(io.quarkus.deployment.annotations.BuildStep) Record(io.quarkus.deployment.annotations.Record)

Example 2 with QuarkusMediatorConfiguration

use of io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration in project quarkus by quarkusio.

the class QuarkusMediatorConfigurationUtil method create.

public static QuarkusMediatorConfiguration create(MethodInfo methodInfo, boolean isSuspendMethod, BeanInfo bean, RecorderContext recorderContext, ClassLoader cl, boolean strict) {
    Class[] parameterTypeClasses;
    Class<?> returnTypeClass;
    MediatorConfigurationSupport.GenericTypeAssignable genericReturnTypeAssignable;
    if (isSuspendMethod) {
        parameterTypeClasses = new Class[methodInfo.parameters().size() - 1];
        for (int i = 0; i < methodInfo.parameters().size() - 1; i++) {
            parameterTypeClasses[i] = load(methodInfo.parameters().get(i).name().toString(), cl);
        }
        // the generated invoker will always return a CompletionStage
        // TODO: avoid hard coding this and use an SPI to communicate the info with the invoker generation code
        returnTypeClass = CompletionStage.class;
        genericReturnTypeAssignable = new JandexGenericTypeAssignable(determineReturnTypeOfSuspendMethod(methodInfo), cl);
    } else {
        parameterTypeClasses = new Class[methodInfo.parameters().size()];
        for (int i = 0; i < methodInfo.parameters().size(); i++) {
            parameterTypeClasses[i] = load(methodInfo.parameters().get(i).name().toString(), cl);
        }
        returnTypeClass = load(methodInfo.returnType().name().toString(), cl);
        genericReturnTypeAssignable = new ReturnTypeGenericTypeAssignable(methodInfo, cl);
    }
    QuarkusMediatorConfiguration configuration = new QuarkusMediatorConfiguration();
    MediatorConfigurationSupport mediatorConfigurationSupport = new MediatorConfigurationSupport(fullMethodName(methodInfo), returnTypeClass, parameterTypeClasses, genericReturnTypeAssignable, methodInfo.parameters().isEmpty() ? new AlwaysInvalidIndexGenericTypeAssignable() : new MethodParamGenericTypeAssignable(methodInfo, 0, cl));
    if (strict) {
        mediatorConfigurationSupport.strict();
    }
    configuration.setBeanId(bean.getIdentifier());
    configuration.setMethodName(methodInfo.name());
    String returnTypeName = returnTypeClass.getName();
    configuration.setReturnType(recorderContext.classProxy(returnTypeName));
    Class<?>[] parameterTypes = new Class[methodInfo.parameters().size()];
    for (int i = 0; i < methodInfo.parameters().size(); i++) {
        parameterTypes[i] = recorderContext.classProxy(methodInfo.parameters().get(i).name().toString());
    }
    configuration.setParameterTypes(parameterTypes);
    // We need to extract the value of @Incoming and @Incomings (which contains an array of @Incoming)
    List<String> incomingValues = new ArrayList<>(getValues(methodInfo, INCOMING));
    incomingValues.addAll(getIncomingValues(methodInfo));
    configuration.setIncomings(incomingValues);
    String outgoingValue = getValue(methodInfo, OUTGOING);
    configuration.setOutgoing(outgoingValue);
    Shape shape = mediatorConfigurationSupport.determineShape(incomingValues, outgoingValue);
    configuration.setShape(shape);
    Acknowledgment.Strategy acknowledgment = mediatorConfigurationSupport.processSuppliedAcknowledgement(incomingValues, () -> {
        AnnotationInstance instance = methodInfo.annotation(ACKNOWLEDGMENT);
        if (instance != null) {
            return Acknowledgment.Strategy.valueOf(instance.value().asEnum());
        }
        return null;
    });
    configuration.setAcknowledgment(acknowledgment);
    MediatorConfigurationSupport.ValidationOutput validationOutput = mediatorConfigurationSupport.validate(shape, acknowledgment);
    configuration.setProduction(validationOutput.getProduction());
    configuration.setConsumption(validationOutput.getConsumption());
    configuration.setIngestedPayloadType(validationOutput.getIngestedPayloadType());
    if (validationOutput.getUseBuilderTypes()) {
        configuration.setUseBuilderTypes(validationOutput.getUseBuilderTypes());
    } else {
        configuration.setUseBuilderTypes(false);
    }
    if (acknowledgment == null) {
        acknowledgment = mediatorConfigurationSupport.processDefaultAcknowledgement(shape, validationOutput.getConsumption(), validationOutput.getProduction());
        configuration.setAcknowledgment(acknowledgment);
    }
    configuration.setMerge(mediatorConfigurationSupport.processMerge(incomingValues, new Supplier<Merge.Mode>() {

        @Override
        public Merge.Mode get() {
            AnnotationInstance instance = methodInfo.annotation(MERGE);
            if (instance != null) {
                AnnotationValue value = instance.value();
                if (value == null) {
                    // the default value of @Merge
                    return Merge.Mode.MERGE;
                }
                return Merge.Mode.valueOf(value.asEnum());
            }
            return null;
        }
    }));
    configuration.setBroadcastValue(mediatorConfigurationSupport.processBroadcast(outgoingValue, new Supplier<Integer>() {

        @Override
        public Integer get() {
            AnnotationInstance instance = methodInfo.annotation(BROADCAST);
            if (instance != null) {
                AnnotationValue value = instance.value();
                if (value == null) {
                    // the default value of @Broadcast
                    return 0;
                }
                return value.asInt();
            }
            return null;
        }
    }));
    AnnotationInstance blockingAnnotation = methodInfo.annotation(BLOCKING);
    AnnotationInstance smallryeBlockingAnnotation = methodInfo.annotation(SMALLRYE_BLOCKING);
    AnnotationInstance transactionalAnnotation = methodInfo.annotation(TRANSACTIONAL);
    if (blockingAnnotation != null || smallryeBlockingAnnotation != null || transactionalAnnotation != null) {
        mediatorConfigurationSupport.validateBlocking(validationOutput);
        configuration.setBlocking(true);
        if (blockingAnnotation != null) {
            AnnotationValue ordered = blockingAnnotation.value("ordered");
            configuration.setBlockingExecutionOrdered(ordered == null || ordered.asBoolean());
            String poolName;
            if (blockingAnnotation.value() != null && !(poolName = blockingAnnotation.value().asString()).equals(Blocking.DEFAULT_WORKER_POOL)) {
                configuration.setWorkerPoolName(poolName);
            }
        } else {
            configuration.setBlockingExecutionOrdered(true);
        }
    }
    return configuration;
}
Also used : MediatorConfigurationSupport(io.smallrye.reactive.messaging.providers.MediatorConfigurationSupport) Shape(io.smallrye.reactive.messaging.Shape) ArrayList(java.util.ArrayList) QuarkusMediatorConfiguration(io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration) Merge(io.smallrye.reactive.messaging.annotations.Merge) Acknowledgment(org.eclipse.microprofile.reactive.messaging.Acknowledgment) AnnotationValue(org.jboss.jandex.AnnotationValue) Supplier(java.util.function.Supplier) AnnotationInstance(org.jboss.jandex.AnnotationInstance)

Aggregations

QuarkusMediatorConfiguration (io.quarkus.smallrye.reactivemessaging.runtime.QuarkusMediatorConfiguration)2 ArrayList (java.util.ArrayList)2 AnnotationInstance (org.jboss.jandex.AnnotationInstance)2 BeanInfo (io.quarkus.arc.processor.BeanInfo)1 GeneratedClassGizmoAdaptor (io.quarkus.deployment.GeneratedClassGizmoAdaptor)1 BuildStep (io.quarkus.deployment.annotations.BuildStep)1 Record (io.quarkus.deployment.annotations.Record)1 ReflectiveClassBuildItem (io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem)1 ClassOutput (io.quarkus.gizmo.ClassOutput)1 InjectedChannelBuildItem (io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedChannelBuildItem)1 InjectedEmitterBuildItem (io.quarkus.smallrye.reactivemessaging.deployment.items.InjectedEmitterBuildItem)1 MediatorBuildItem (io.quarkus.smallrye.reactivemessaging.deployment.items.MediatorBuildItem)1 SmallRyeReactiveMessagingContext (io.quarkus.smallrye.reactivemessaging.runtime.SmallRyeReactiveMessagingRecorder.SmallRyeReactiveMessagingContext)1 WorkerConfiguration (io.quarkus.smallrye.reactivemessaging.runtime.WorkerConfiguration)1 EmitterConfiguration (io.smallrye.reactive.messaging.EmitterConfiguration)1 Shape (io.smallrye.reactive.messaging.Shape)1 Merge (io.smallrye.reactive.messaging.annotations.Merge)1 MediatorConfigurationSupport (io.smallrye.reactive.messaging.providers.MediatorConfigurationSupport)1 ChannelConfiguration (io.smallrye.reactive.messaging.providers.extension.ChannelConfiguration)1 Supplier (java.util.function.Supplier)1