 
                        
        
                        
        org.springframework.messaging.rsocket.RSocketStrategies Maven / Gradle / Ivy
/*
 * Copyright 2002-2020 the original author or 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
 *
 *      https://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 org.springframework.messaging.rsocket;
import java.util.List;
import java.util.function.Consumer;
import io.rsocket.Payload;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.MimeType;
import org.springframework.util.RouteMatcher;
import org.springframework.util.SimpleRouteMatcher;
/**
 * Access to strategies for use by RSocket requester and responder components.
 *
 * @author Rossen Stoyanchev
 * @since 5.2
 */
public interface RSocketStrategies {
	/**
	 * Return the configured {@link Builder#encoder(Encoder[]) encoders}.
	 * @see #encoder(ResolvableType, MimeType)
	 */
	List> encoders();
	/**
	 * Find a compatible Encoder for the given element type.
	 * @param elementType the element type to match
	 * @param mimeType the MimeType to match
	 * @param  for casting the Encoder to the expected element type
	 * @return the matching Encoder
	 * @throws IllegalArgumentException if no matching Encoder is found
	 */
	@SuppressWarnings("unchecked")
	default  Encoder encoder(ResolvableType elementType, @Nullable MimeType mimeType) {
		for (Encoder> encoder : encoders()) {
			if (encoder.canEncode(elementType, mimeType)) {
				return (Encoder) encoder;
			}
		}
		throw new IllegalArgumentException("No encoder for " + elementType);
	}
	/**
	 * Return the configured {@link Builder#decoder(Decoder[]) decoders}.
	 * @see #decoder(ResolvableType, MimeType)
	 */
	List> decoders();
	/**
	 * Find a compatible Decoder for the given element type.
	 * @param elementType the element type to match
	 * @param mimeType the MimeType to match
	 * @param  for casting the Decoder to the expected element type
	 * @return the matching Decoder
	 * @throws IllegalArgumentException if no matching Decoder is found
	 */
	@SuppressWarnings("unchecked")
	default  Decoder decoder(ResolvableType elementType, @Nullable MimeType mimeType) {
		for (Decoder> decoder : decoders()) {
			if (decoder.canDecode(elementType, mimeType)) {
				return (Decoder) decoder;
			}
		}
		throw new IllegalArgumentException("No decoder for " + elementType);
	}
	/**
	 * Return the configured {@link Builder#routeMatcher(RouteMatcher)}.
	 */
	RouteMatcher routeMatcher();
	/**
	 * Return the configured
	 * {@link Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) reactiveAdapterRegistry}.
	 */
	ReactiveAdapterRegistry reactiveAdapterRegistry();
	/**
	 * Return the configured
	 * {@link Builder#dataBufferFactory(DataBufferFactory) dataBufferFactory}.
	 */
	DataBufferFactory dataBufferFactory();
	/**
	 * Return the configured {@link Builder#metadataExtractor(MetadataExtractor)}.
	 */
	MetadataExtractor metadataExtractor();
	/**
	 * Return a builder to create a new {@link RSocketStrategies} instance
	 * replicated from the current instance.
	 */
	default Builder mutate() {
		return new DefaultRSocketStrategies.DefaultRSocketStrategiesBuilder(this);
	}
	/**
	 * Create an {@code RSocketStrategies} instance with default settings.
	 * Equivalent to {@code RSocketStrategies.builder().build()}. See individual
	 * builder methods for details on default settings.
	 */
	static RSocketStrategies create() {
		return new DefaultRSocketStrategies.DefaultRSocketStrategiesBuilder().build();
	}
	/**
	 * Return a builder to prepare a new {@code RSocketStrategies} instance.
	 * The builder applies default settings, see individual builder methods for
	 * details.
	 */
	static Builder builder() {
		return new DefaultRSocketStrategies.DefaultRSocketStrategiesBuilder();
	}
	/**
	 * The builder options for creating {@code RSocketStrategies}.
	 */
	interface Builder {
		/**
		 * Append to the list of encoders to use for serializing Objects to the
		 * data or metadata of a {@link Payload}.
		 * By default this is initialized with encoders for {@code String},
		 * {@code byte[]}, {@code ByteBuffer}, and {@code DataBuffer}.
		 */
		Builder encoder(Encoder>... encoder);
		/**
		 * Apply the consumer to the list of configured encoders, immediately.
		 */
		Builder encoders(Consumer>> consumer);
		/**
		 * Append to the list of decoders to use for de-serializing Objects from
		 * the data or metadata of a {@link Payload}.
		 * By default this is initialized with decoders for {@code String},
		 * {@code byte[]}, {@code ByteBuffer}, and {@code DataBuffer}.
		 */
		Builder decoder(Decoder>... decoder);
		/**
		 * Apply the consumer to the list of configured decoders, immediately.
		 */
		Builder decoders(Consumer>> consumer);
		/**
		 * Configure a {@code RouteMatcher} for matching routes to message
		 * handlers based on route patterns. This option is applicable to
		 * client or server responders.
		 * By default, {@link SimpleRouteMatcher} is used, backed by
		 * {@link AntPathMatcher} with "." as separator. For better
		 * efficiency consider switching to {@code PathPatternRouteMatcher} from
		 * {@code spring-web} instead.
		 */
		Builder routeMatcher(@Nullable RouteMatcher routeMatcher);
		/**
		 * Configure the registry for reactive type support. This can be used
		 * to adapt to, and/or determine the semantics of a given
		 * {@link org.reactivestreams.Publisher Publisher}.
		 * 
By default this {@link ReactiveAdapterRegistry#getSharedInstance()}.
		 */
		Builder reactiveAdapterStrategy(@Nullable ReactiveAdapterRegistry registry);
		/**
		 * Configure the DataBufferFactory to use for allocating buffers when
		 * preparing requests or creating responses.
		 * 
By default this is set to {@link NettyDataBufferFactory} with
		 * pooled, allocated buffers for zero copy. RSocket must also be
		 * configured
		 * for zero copy. For client setup, {@link RSocketRequester.Builder}
		 * adapts automatically to the {@code DataBufferFactory} configured
		 * here, and sets the frame decoder in
		 * {@link io.rsocket.core.RSocketConnector RSocketConnector}
		 * accordingly. For server setup, the
		 * {@link io.rsocket.core.RSocketServer RSocketServer} must be configured
		 * accordingly for zero copy too.
		 * 
If using {@link DefaultDataBufferFactory} instead, there is no
		 * need for related config changes in RSocket.
		 */
		Builder dataBufferFactory(@Nullable DataBufferFactory bufferFactory);
		/**
		 * Configure a {@link MetadataExtractor} to extract the route along with
		 * other metadata. This option is applicable to client or server
		 * responders.
		 * 
By default this is {@link DefaultMetadataExtractor} created with
		 * the {@link #decoder(Decoder[]) configured} decoders and extracting a
		 * route from {@code "message/x.rsocket.routing.v0"} metadata.
		 */
		Builder metadataExtractor(@Nullable MetadataExtractor metadataExtractor);
		/**
		 * Apply the consumer to the {@link MetadataExtractorRegistry} in order
		 * to register extra metadata entry extractors.
		 */
		Builder metadataExtractorRegistry(Consumer consumer);
		/**
		 * Build the {@code RSocketStrategies} instance.
		 */
		RSocketStrategies build();
	}
}