All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mats3.spring.MatsMapping Maven / Gradle / Ivy

Go to download

Mats^3 Spring integration ("SpringConfig"), supplying a set of annotations including @EnableMats to enable bean scanning for @MatsMapping and @MatsClassMapping annotations, simplifying Mats^3 use in a Spring context.

There is a newer version: 0.19.22-2024-11-09
Show newest version
package io.mats3.spring;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.AliasFor;

import io.mats3.MatsEndpoint.EndpointConfig;
import io.mats3.MatsFactory;
import io.mats3.MatsInitiator;
import io.mats3.MatsInitiator.MatsInitiate;
import io.mats3.spring.MatsMapping.MatsMappings;

/**
 * A method annotated with this repeatable annotation directly becomes a
 * {@link MatsFactory#single(String, Class, Class, io.mats3.MatsEndpoint.ProcessSingleLambda) Mats Single-stage
 * Endpoint} or a
 * {@link MatsFactory#terminator(String, Class, Class, io.mats3.MatsEndpoint.ProcessTerminatorLambda) Mats
 * Terminator Endpoint}, depending on whether the method specifies a return type, or is void.
 * 

*

Single-stage (service) endpoint

For the Single-Stage endpoint (where the return type is set), one method * parameter should be annotated with {@link Dto @Dto}: When the endpoint is invoked, it will be set to the incoming * (request) Data Transfer Object - and the argument's type thus also specifies its expected deserialization class. The * method's return type represent the outgoing reply Data Transfer Object. *

*

Terminator endpoint

For the Terminator endpoint (where the return type is void), one method * parameter should be annotated with {@link Dto @Dto}: When the endpoint is invoked, it will be set to the incoming * (typically request - or just "message") Data Transfer Object - and the argument's type thus also specifies its * expected deserialization class. The method's return type represent the outgoing reply Data Transfer Object. In * addition, another method parameter can be annotated with {@link Sto @Sto}, which will be the "State Transfer Object" * - this is the object which an initiator supplied to the * {@link MatsInitiator#initiate(io.mats3.MatsInitiator.InitiateLambda) initiate call} when it set this * Terminator endpoint as the {@link MatsInitiate#replyTo(String, Object) replyTo} endpointId. *

*

Which {@link MatsFactory} the endpoint is created on

If you have a setup with multiple {@link MatsFactory}s, * you must either have one (and only one) of the factories denoted as {@link Primary @Primary}, or you must qualify * which MatsFactory to use. This can be done by the following means: *
    *
  • Add a {@link Qualifier @Qualifier(qualifiervalue)} annotation to the @MatsMapping-annotated method - this both * matches a MatsFactory with the same @Qualifier(qualifiervalue)-annotation, and a MatsFactory whose bean * name is the 'qualifierValue' (this dual-logic is Spring's standard).
  • *
  • Add a custom qualifier annotation, e.g. @SpecialMatsFactory, or you can make a custom qualification * taking parameters like @SpecialMatsFactory(location="somevalue"). Whether a qualification matches or not * is evaluated by .equals(..)-semantics.
  • *
  • Use the {@link #matsFactoryBeanName()} annotation value
  • *
  • Use the {@link #matsFactoryQualifierValue()} annotation value
  • *
  • Use the {@link #matsFactoryCustomQualifierType()} annotation value (please read the JavaDoc for special * considerations with this).
  • *
* You cannot specify more than one qualification per @MatsMapping. As mentioned, @MatsMapping is repeatable, so you can * specify multiple mappings on one method. However, the two first ways to qualify which MatsFactory to use (that is, by * means of annotating the @MatsMapping-annotated method with the qualifier annotation) will then apply to all of the * mappings, while the three annotation-value based qualifications applies to the specific mapping. * * @see MatsClassMapping * * @author Endre Stølsvik - 2016-05-19 - http://endre.stolsvik.com */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Repeatable(MatsMappings.class) public @interface MatsMapping { /** * The Mats Endpoint Id that this endpoint should listen to. * * @return the Mats Endpoint Id which this endpoint listens to. */ @AliasFor("value") String endpointId() default ""; /** * Alias for "endpointId", so that if you only need to set the endpointId, you can do so directly: * @MatsMapping("endpointId") * * @return the endpointId. */ @AliasFor("endpointId") String value() default ""; /** * If this MatsEndpoint is subscription based. Only Terminators can be that, so this can only be set to * true on methods that have 'void' as the return type. * * @return whether the Mats Endpoint should be subscription-based - and only Terminators are allowed to be that * (i.e. the method must not return anything, i.e. "void"). */ boolean subscription() default false; /** * A string representing the {@link EndpointConfig#setConcurrency(int) concurrency} of the Endpoint. Currently * only digits are allowed, and the value is passed directly to {@link Integer#parseInt(String)}. (In a future * version it might be possible to specify a Spring SpEL expression, which would be evaluated against a context * of the parent MatsFactory so that you could say "parentFactory * 2", and include the Spring Environment, so * that you could say "env['mats.concurrency'] * 2" or similar constructs.) */ String concurrency() default ""; /** * Specifies the {@link MatsFactory} to use by means of a specific qualifier annotation type (which thus must be * meta-annotated with {@link Qualifier}). Notice that this will search for the custom qualifier annotation * type, as opposed to if you add the annotation to the @MatsMapped-annotated method directly, in which case * it "equals" the annotation instance (as Spring also does when performing injection with such qualifiers). * The difference comes into play if the annotation has values, where e.g. a * @SpecialMatsFactory(location="central") is not equal to * @SpecialMatsFactory(location="region_west") - but they are equal when comparing types, as the * qualification here does. Thus, if using this qualifier-approach, you should probably not use values on your * custom qualifier annotations (instead make separate custom qualifier annotations, e.g. * @MatsFactoryCentral and @MatsFactoryRegionWest for the example). * * @return the custom qualifier type which the wanted {@link MatsFactory} is qualified with. */ Class matsFactoryCustomQualifierType() default Annotation.class; /** * Specified the {@link MatsFactory} to use by means of specifying the @Qualifier value. Spring * performs such lookup by first looking for actual qualifiers with the specified value, e.g. * @Qualifier(value="the_value"). If this does not produce a result, it will try to find a bean with * this value as the bean name. * * @return the qualifier value which the wanted {@link MatsFactory} is qualified with. */ String matsFactoryQualifierValue() default ""; /** * Specified the {@link MatsFactory} to use by means of specifying the bean name of the {@link MatsFactory}. * * @return the bean name of the wanted {@link MatsFactory}. */ String matsFactoryBeanName() default ""; @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @interface MatsMappings { MatsMapping[] value(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy