Java Code Examples for org.springframework.core.ResolvableType#getGeneric()

The following examples show how to use org.springframework.core.ResolvableType#getGeneric() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: KeyValueSerdeResolver.java    From spring-cloud-stream-binder-kafka with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("unchecked")
private Serde<?> getValueSerde(String valueSerdeString, ResolvableType resolvableType)
		throws ClassNotFoundException {
	Serde<?> valueSerde = null;
	if (StringUtils.hasText(valueSerdeString)) {
		valueSerde = Utils.newInstance(valueSerdeString, Serde.class);
	}
	else {

		if (resolvableType != null && ((isResolvalbeKafkaStreamsType(resolvableType)) ||
				(isResolvableKStreamArrayType(resolvableType)))) {
			Serde<?> fallbackSerde = getFallbackSerde("default.value.serde");
			ResolvableType generic = resolvableType.isArray() ? resolvableType.getComponentType().getGeneric(1) : resolvableType.getGeneric(1);
			valueSerde = getSerde(generic, fallbackSerde);
		}
		if (valueSerde == null) {

			valueSerde = Serdes.ByteArray();
		}
	}
	valueSerde.configure(streamConfigGlobalProperties, false);
	return valueSerde;
}
 
Example 2
Source File: KeyValueSerdeResolver.java    From spring-cloud-stream-binder-kafka with Apache License 2.0 6 votes vote down vote up
private Serde<?> getKeySerde(String keySerdeString, ResolvableType resolvableType) {
	Serde<?> keySerde = null;
	try {
		if (StringUtils.hasText(keySerdeString)) {
			keySerde = Utils.newInstance(keySerdeString, Serde.class);
		}
		else {
			if (resolvableType != null &&
					(isResolvalbeKafkaStreamsType(resolvableType) || isResolvableKStreamArrayType(resolvableType))) {
				ResolvableType generic = resolvableType.isArray() ? resolvableType.getComponentType().getGeneric(0) : resolvableType.getGeneric(0);
				Serde<?> fallbackSerde = getFallbackSerde("default.key.serde");
				keySerde = getSerde(generic, fallbackSerde);
			}
			if (keySerde == null) {
				keySerde = Serdes.ByteArray();
			}
		}
		keySerde.configure(this.streamConfigGlobalProperties, true);
	}
	catch (ClassNotFoundException ex) {
		throw new IllegalStateException("Serde class not found: ", ex);
	}
	return keySerde;
}
 
Example 3
Source File: AbstractConverter.java    From spring-cloud-sockets with Apache License 2.0 5 votes vote down vote up
public ResolvableType getActualType(ResolvableType original){
	if(!original.hasGenerics()){
		return  original;
	}else{
		return original.getGeneric(0);
	}
}
 
Example 4
Source File: CarHandler.java    From tutorials with MIT License 5 votes vote down vote up
public List<Vehicle> getVehicles() throws NoSuchFieldException {
    ResolvableType vehiclesType = ResolvableType.forField(getClass().getDeclaredField("vehicles"));
    System.out.println(vehiclesType);
    ResolvableType type = vehiclesType.getGeneric();
    System.out.println(type);
    Class<?> aClass = type.resolve();
    System.out.println(aClass);
    return this.vehicles;
}
 
Example 5
Source File: KafkaStreamsBindableProxyFactory.java    From spring-cloud-stream-binder-kafka with Apache License 2.0 5 votes vote down vote up
private int getNumberOfInputs() {
	int numberOfInputs = 1;
	ResolvableType arg1 = this.type.getGeneric(1);

	while (isAnotherFunctionOrConsumerFound(arg1)) {
		arg1 = arg1.getGeneric(1);
		numberOfInputs++;
	}
	return numberOfInputs;

}
 
Example 6
Source File: GenericApplicationListenerAdapter.java    From spring4-understanding with Apache License 2.0 5 votes vote down vote up
static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
	ResolvableType resolvableType = ResolvableType.forClass(listenerType).as(ApplicationListener.class);
	if (resolvableType == null || !resolvableType.hasGenerics()) {
		return null;
	}
	return resolvableType.getGeneric();
}
 
Example 7
Source File: ProtoFileResourceUtils.java    From raptor with Apache License 2.0 5 votes vote down vote up
private static Set<ProtoFileInfo> findProtoFilesByMessage(Class<?> messageClass, Set<Class<?>> founds, ClassLoader classLoader) {
    Set<ProtoFileInfo> results = new HashSet<>();
    ProtoFileInfo protoFileInfo = findMessageProtoFile(messageClass, classLoader);
    if (protoFileInfo != null && !founds.contains(messageClass)) {
        results.add(protoFileInfo);
        founds.add(messageClass);
        Field[] fields = messageClass.getDeclaredFields();
        for (Field field : fields) {
            Class<?> fieldType = field.getType();
            RaptorMessage annotation = AnnotationUtils.findAnnotation(fieldType, RaptorMessage.class);
            ResolvableType resolvableType = ResolvableType.forField(field);
            if (annotation != null) {
                Set<ProtoFileInfo> filedMessageProtoFiles = findProtoFilesByMessage(fieldType, founds, classLoader);
                results.addAll(filedMessageProtoFiles);
            } else if (List.class.isAssignableFrom(fieldType)) {
                ResolvableType genericType = resolvableType.getGeneric(0);
                results.addAll(findProtoFilesByMessage(genericType.getRawClass(), founds, classLoader));
            } else if (Map.class.isAssignableFrom(fieldType)) {
                ResolvableType keyType = resolvableType.getGeneric(0);
                ResolvableType valueType = resolvableType.getGeneric(1);
                results.addAll(findProtoFilesByMessage(keyType.getRawClass(), founds, classLoader));
                results.addAll(findProtoFilesByMessage(valueType.getRawClass(), founds, classLoader));
            }
        }
    }
    return results;
}
 
Example 8
Source File: ServerSentEventHttpMessageReader.java    From java-technology-stack with MIT License 5 votes vote down vote up
@Override
public Flux<Object> read(
		ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {

	boolean shouldWrap = isServerSentEvent(elementType);
	ResolvableType valueType = (shouldWrap ? elementType.getGeneric() : elementType);

	return stringDecoder.decode(message.getBody(), STRING_TYPE, null, hints)
			.bufferUntil(line -> line.equals(""))
			.concatMap(lines -> buildEvent(lines, valueType, shouldWrap, hints));
}
 
Example 9
Source File: ServerSentEventHttpMessageReader.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@Override
public Flux<Object> read(
		ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {

	boolean shouldWrap = isServerSentEvent(elementType);
	ResolvableType valueType = (shouldWrap ? elementType.getGeneric() : elementType);

	return stringDecoder.decode(message.getBody(), STRING_TYPE, null, hints)
			.bufferUntil(line -> line.equals(""))
			.concatMap(lines -> Mono.justOrEmpty(buildEvent(lines, valueType, shouldWrap, hints)));
}
 
Example 10
Source File: AbstractEncoderMethodReturnValueHandler.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@SuppressWarnings("unchecked")
private Flux<DataBuffer> encodeContent(
		@Nullable Object content, MethodParameter returnType, DataBufferFactory bufferFactory,
		@Nullable MimeType mimeType, Map<String, Object> hints) {

	ResolvableType returnValueType = ResolvableType.forMethodParameter(returnType);
	ReactiveAdapter adapter = getAdapterRegistry().getAdapter(returnValueType.resolve(), content);

	Publisher<?> publisher;
	ResolvableType elementType;
	if (adapter != null) {
		publisher = adapter.toPublisher(content);
		boolean isUnwrapped = KotlinDetector.isKotlinReflectPresent() &&
				KotlinDetector.isKotlinType(returnType.getContainingClass()) &&
				KotlinDelegate.isSuspend(returnType.getMethod()) &&
				!COROUTINES_FLOW_CLASS_NAME.equals(returnValueType.toClass().getName());
		ResolvableType genericType = isUnwrapped ? returnValueType : returnValueType.getGeneric();
		elementType = getElementType(adapter, genericType);
	}
	else {
		publisher = Mono.justOrEmpty(content);
		elementType = (returnValueType.toClass() == Object.class && content != null ?
				ResolvableType.forInstance(content) : returnValueType);
	}

	if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
		return Flux.from(publisher).cast(DataBuffer.class);
	}

	Encoder<?> encoder = getEncoder(elementType, mimeType);
	return Flux.from((Publisher) publisher).map(value ->
			encodeValue(value, elementType, encoder, bufferFactory, mimeType, hints));
}
 
Example 11
Source File: AbstractMessageWriterResultHandler.java    From java-technology-stack with MIT License 4 votes vote down vote up
/**
 * Write a given body to the response with {@link HttpMessageWriter}.
 * @param body the object to write
 * @param bodyParameter the {@link MethodParameter} of the body to write
 * @param actualParam the actual return type of the method that returned the value;
 * could be different from {@code bodyParameter} when processing {@code HttpEntity}
 * for example
 * @param exchange the current exchange
 * @return indicates completion or error
 * @since 5.0.2
 */
@SuppressWarnings({"unchecked", "rawtypes"})
protected Mono<Void> writeBody(@Nullable Object body, MethodParameter bodyParameter,
		@Nullable MethodParameter actualParam, ServerWebExchange exchange) {

	ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);
	ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
	ReactiveAdapter adapter = getAdapterRegistry().getAdapter(bodyType.resolve(), body);

	Publisher<?> publisher;
	ResolvableType elementType;
	if (adapter != null) {
		publisher = adapter.toPublisher(body);
		ResolvableType genericType = bodyType.getGeneric();
		elementType = getElementType(adapter, genericType);
	}
	else {
		publisher = Mono.justOrEmpty(body);
		elementType = (bodyType.toClass() == Object.class && body != null ?
				ResolvableType.forInstance(body) : bodyType);
	}

	if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
		return Mono.from((Publisher<Void>) publisher);
	}

	ServerHttpRequest request = exchange.getRequest();
	ServerHttpResponse response = exchange.getResponse();
	MediaType bestMediaType = selectMediaType(exchange, () -> getMediaTypesFor(elementType));
	if (bestMediaType != null) {
		String logPrefix = exchange.getLogPrefix();
		if (logger.isDebugEnabled()) {
			logger.debug(logPrefix +
					(publisher instanceof Mono ? "0..1" : "0..N") + " [" + elementType + "]");
		}
		for (HttpMessageWriter<?> writer : getMessageWriters()) {
			if (writer.canWrite(elementType, bestMediaType)) {
				return writer.write((Publisher) publisher, actualType, elementType, bestMediaType,
						request, response, Hints.from(Hints.LOG_PREFIX_HINT, logPrefix));
			}
		}
	}
	else {
		if (getMediaTypesFor(elementType).isEmpty()) {
			return Mono.error(new IllegalStateException("No writer for : " + elementType));
		}
	}

	return Mono.error(new NotAcceptableStatusException(getMediaTypesFor(elementType)));
}
 
Example 12
Source File: PayloadMethodArgumentResolver.java    From spring-analysis-note with MIT License 4 votes vote down vote up
private Mono<Object> decodeContent(MethodParameter parameter, Message<?> message,
		boolean isContentRequired, Flux<DataBuffer> content, MimeType mimeType) {

	ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
	Class<?> resolvedType = targetType.resolve();
	ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
	ResolvableType elementType = (adapter != null ? targetType.getGeneric() : targetType);
	isContentRequired = isContentRequired || (adapter != null && !adapter.supportsEmpty());
	Consumer<Object> validator = getValidator(message, parameter);

	Map<String, Object> hints = Collections.emptyMap();

	for (Decoder<?> decoder : this.decoders) {
		if (decoder.canDecode(elementType, mimeType)) {
			if (adapter != null && adapter.isMultiValue()) {
				Flux<?> flux = content
						.map(buffer -> decoder.decode(buffer, elementType, mimeType, hints))
						.onErrorResume(ex -> Flux.error(handleReadError(parameter, message, ex)));
				if (isContentRequired) {
					flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(parameter, message)));
				}
				if (validator != null) {
					flux = flux.doOnNext(validator);
				}
				return Mono.just(adapter.fromPublisher(flux));
			}
			else {
				// Single-value (with or without reactive type wrapper)
				Mono<?> mono = content.next()
						.map(buffer -> decoder.decode(buffer, elementType, mimeType, hints))
						.onErrorResume(ex -> Mono.error(handleReadError(parameter, message, ex)));
				if (isContentRequired) {
					mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(parameter, message)));
				}
				if (validator != null) {
					mono = mono.doOnNext(validator);
				}
				return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
			}
		}
	}

	return Mono.error(new MethodArgumentResolutionException(
			message, parameter, "Cannot decode to [" + targetType + "]" + message));
}
 
Example 13
Source File: GenericApplicationListenerAdapter.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
	ResolvableType resolvableType = ResolvableType.forClass(listenerType).as(ApplicationListener.class);
	return (resolvableType.hasGenerics() ? resolvableType.getGeneric() : null);
}
 
Example 14
Source File: AbstractMessageReaderArgumentResolver.java    From java-technology-stack with MIT License 4 votes vote down vote up
/**
 * Read the body from a method argument with {@link HttpMessageReader}.
 * @param bodyParam represents the element type for the body
 * @param actualParam the actual method argument type; possibly different
 * from {@code bodyParam}, e.g. for an {@code HttpEntity} argument
 * @param isBodyRequired true if the body is required
 * @param bindingContext the binding context to use
 * @param exchange the current exchange
 * @return a Mono with the value to use for the method argument
 * @since 5.0.2
 */
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam,
		boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) {

	ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
	ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
	Class<?> resolvedType = bodyType.resolve();
	ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
	ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType);
	isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty());

	ServerHttpRequest request = exchange.getRequest();
	ServerHttpResponse response = exchange.getResponse();

	MediaType contentType = request.getHeaders().getContentType();
	MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
	Object[] hints = extractValidationHints(bodyParam);

	if (logger.isDebugEnabled()) {
		logger.debug(exchange.getLogPrefix() + (contentType != null ?
				"Content-Type:" + contentType :
				"No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
	}

	for (HttpMessageReader<?> reader : getMessageReaders()) {
		if (reader.canRead(elementType, mediaType)) {
			Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
			if (adapter != null && adapter.isMultiValue()) {
				if (logger.isDebugEnabled()) {
					logger.debug(exchange.getLogPrefix() + "0..N [" + elementType + "]");
				}
				Flux<?> flux = reader.read(actualType, elementType, request, response, readHints);
				flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex)));
				if (isBodyRequired) {
					flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam)));
				}
				if (hints != null) {
					flux = flux.doOnNext(target ->
							validate(target, hints, bodyParam, bindingContext, exchange));
				}
				return Mono.just(adapter.fromPublisher(flux));
			}
			else {
				// Single-value (with or without reactive type wrapper)
				if (logger.isDebugEnabled()) {
					logger.debug(exchange.getLogPrefix() + "0..1 [" + elementType + "]");
				}
				Mono<?> mono = reader.readMono(actualType, elementType, request, response, readHints);
				mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex)));
				if (isBodyRequired) {
					mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
				}
				if (hints != null) {
					mono = mono.doOnNext(target ->
							validate(target, hints, bodyParam, bindingContext, exchange));
				}
				return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
			}
		}
	}

	// No compatible reader but body may be empty..

	HttpMethod method = request.getMethod();
	if (contentType == null && method != null && SUPPORTED_METHODS.contains(method)) {
		Flux<DataBuffer> body = request.getBody().doOnNext(o -> {
			// Body not empty, back to 415..
			throw new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType);
		});
		if (isBodyRequired) {
			body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
		}
		return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
	}

	return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType));
}
 
Example 15
Source File: KafkaStreamsBindableProxyFactory.java    From spring-cloud-stream-binder-kafka with Apache License 2.0 4 votes vote down vote up
@Override
public void afterPropertiesSet() {
	Assert.notEmpty(KafkaStreamsBindableProxyFactory.this.bindingTargetFactories,
			"'bindingTargetFactories' cannot be empty");

	int resolvableTypeDepthCounter = 0;
	ResolvableType argument = this.type.getGeneric(resolvableTypeDepthCounter++);
	List<String> inputBindings = buildInputBindings();
	Iterator<String> iterator = inputBindings.iterator();
	String next = iterator.next();
	bindInput(argument, next);

	if (this.type.getRawClass() != null &&
			(this.type.getRawClass().isAssignableFrom(BiFunction.class) ||
			this.type.getRawClass().isAssignableFrom(BiConsumer.class))) {
		argument = this.type.getGeneric(resolvableTypeDepthCounter++);
		next = iterator.next();
		bindInput(argument, next);
	}
	ResolvableType outboundArgument = this.type.getGeneric(resolvableTypeDepthCounter);

	while (isAnotherFunctionOrConsumerFound(outboundArgument)) {
		//The function is a curried function. We should introspect the partial function chain hierarchy.
		argument = outboundArgument.getGeneric(0);
		String next1 = iterator.next();
		bindInput(argument, next1);
		outboundArgument = outboundArgument.getGeneric(1);
	}

	//Introspect output for binding.
	if (outboundArgument != null &&  outboundArgument.getRawClass() != null && (!outboundArgument.isArray() &&
			outboundArgument.getRawClass().isAssignableFrom(KStream.class))) {
		// if the type is array, we need to do a late binding as we don't know the number of
		// output bindings at this point in the flow.

		List<String> outputBindings = streamFunctionProperties.getOutputBindings(this.functionName);
		String outputBinding = null;

		if (!CollectionUtils.isEmpty(outputBindings)) {
			Iterator<String> outputBindingsIter = outputBindings.iterator();
			if (outputBindingsIter.hasNext()) {
				outputBinding = outputBindingsIter.next();
			}

		}
		else {
			outputBinding = String.format("%s-%s-0", this.functionName, FunctionConstants.DEFAULT_OUTPUT_SUFFIX);
		}
		Assert.isTrue(outputBinding != null, "output binding is not inferred.");
		KafkaStreamsBindableProxyFactory.this.outputHolders.put(outputBinding,
				new BoundTargetHolder(getBindingTargetFactory(KStream.class)
						.createOutput(outputBinding), true));
		String outputBinding1 = outputBinding;
		RootBeanDefinition rootBeanDefinition1 = new RootBeanDefinition();
		rootBeanDefinition1.setInstanceSupplier(() -> outputHolders.get(outputBinding1).getBoundTarget());
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		registry.registerBeanDefinition(outputBinding1, rootBeanDefinition1);
	}
}
 
Example 16
Source File: AbstractMessageWriterResultHandler.java    From spring-analysis-note with MIT License 4 votes vote down vote up
/**
 * Write a given body to the response with {@link HttpMessageWriter}.
 * @param body the object to write
 * @param bodyParameter the {@link MethodParameter} of the body to write
 * @param actualParam the actual return type of the method that returned the value;
 * could be different from {@code bodyParameter} when processing {@code HttpEntity}
 * for example
 * @param exchange the current exchange
 * @return indicates completion or error
 * @since 5.0.2
 */
@SuppressWarnings({"unchecked", "rawtypes", "ConstantConditions"})
protected Mono<Void> writeBody(@Nullable Object body, MethodParameter bodyParameter,
		@Nullable MethodParameter actualParam, ServerWebExchange exchange) {

	ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);
	ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
	ReactiveAdapter adapter = getAdapterRegistry().getAdapter(bodyType.resolve(), body);

	Publisher<?> publisher;
	ResolvableType elementType;
	ResolvableType actualElementType;
	if (adapter != null) {
		publisher = adapter.toPublisher(body);
		boolean isUnwrapped = KotlinDetector.isKotlinReflectPresent() &&
				KotlinDetector.isKotlinType(bodyParameter.getContainingClass()) &&
				KotlinDelegate.isSuspend(bodyParameter.getMethod()) &&
				!COROUTINES_FLOW_CLASS_NAME.equals(bodyType.toClass().getName());
		ResolvableType genericType = isUnwrapped ? bodyType : bodyType.getGeneric();
		elementType = getElementType(adapter, genericType);
		actualElementType = elementType;
	}
	else {
		publisher = Mono.justOrEmpty(body);
		actualElementType = body != null ? ResolvableType.forInstance(body) : bodyType;
		elementType = (bodyType.toClass() == Object.class && body != null ? actualElementType : bodyType);
	}

	if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
		return Mono.from((Publisher<Void>) publisher);
	}

	MediaType bestMediaType = selectMediaType(exchange, () -> getMediaTypesFor(elementType));
	if (bestMediaType != null) {
		String logPrefix = exchange.getLogPrefix();
		if (logger.isDebugEnabled()) {
			logger.debug(logPrefix +
					(publisher instanceof Mono ? "0..1" : "0..N") + " [" + elementType + "]");
		}
		for (HttpMessageWriter<?> writer : getMessageWriters()) {
			if (writer.canWrite(actualElementType, bestMediaType)) {
				return writer.write((Publisher) publisher, actualType, elementType,
						bestMediaType, exchange.getRequest(), exchange.getResponse(),
						Hints.from(Hints.LOG_PREFIX_HINT, logPrefix));
			}
		}
	}

	List<MediaType> mediaTypes = getMediaTypesFor(elementType);
	if (bestMediaType == null && mediaTypes.isEmpty()) {
		return Mono.error(new IllegalStateException("No HttpMessageWriter for " + elementType));
	}
	return Mono.error(new NotAcceptableStatusException(mediaTypes));
}
 
Example 17
Source File: AbstractMessageReaderArgumentResolver.java    From spring-analysis-note with MIT License 4 votes vote down vote up
/**
 * Read the body from a method argument with {@link HttpMessageReader}.
 * @param bodyParam represents the element type for the body
 * @param actualParam the actual method argument type; possibly different
 * from {@code bodyParam}, e.g. for an {@code HttpEntity} argument
 * @param isBodyRequired true if the body is required
 * @param bindingContext the binding context to use
 * @param exchange the current exchange
 * @return a Mono with the value to use for the method argument
 * @since 5.0.2
 */
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam,
		boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) {

	ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
	ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
	Class<?> resolvedType = bodyType.resolve();
	ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
	ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType);
	isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty());

	ServerHttpRequest request = exchange.getRequest();
	ServerHttpResponse response = exchange.getResponse();

	MediaType contentType = request.getHeaders().getContentType();
	MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
	Object[] hints = extractValidationHints(bodyParam);

	if (mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
		return Mono.error(new IllegalStateException(
				"In a WebFlux application, form data is accessed via ServerWebExchange.getFormData()."));
	}

	if (logger.isDebugEnabled()) {
		logger.debug(exchange.getLogPrefix() + (contentType != null ?
				"Content-Type:" + contentType :
				"No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
	}

	for (HttpMessageReader<?> reader : getMessageReaders()) {
		if (reader.canRead(elementType, mediaType)) {
			Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
			if (adapter != null && adapter.isMultiValue()) {
				if (logger.isDebugEnabled()) {
					logger.debug(exchange.getLogPrefix() + "0..N [" + elementType + "]");
				}
				Flux<?> flux = reader.read(actualType, elementType, request, response, readHints);
				flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex)));
				if (isBodyRequired) {
					flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam)));
				}
				if (hints != null) {
					flux = flux.doOnNext(target ->
							validate(target, hints, bodyParam, bindingContext, exchange));
				}
				return Mono.just(adapter.fromPublisher(flux));
			}
			else {
				// Single-value (with or without reactive type wrapper)
				if (logger.isDebugEnabled()) {
					logger.debug(exchange.getLogPrefix() + "0..1 [" + elementType + "]");
				}
				Mono<?> mono = reader.readMono(actualType, elementType, request, response, readHints);
				mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex)));
				if (isBodyRequired) {
					mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
				}
				if (hints != null) {
					mono = mono.doOnNext(target ->
							validate(target, hints, bodyParam, bindingContext, exchange));
				}
				return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
			}
		}
	}

	// No compatible reader but body may be empty..

	HttpMethod method = request.getMethod();
	if (contentType == null && method != null && SUPPORTED_METHODS.contains(method)) {
		Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
			DataBufferUtils.release(buffer);
			// Body not empty, back to 415..
			throw new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType);
		});
		if (isBodyRequired) {
			body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
		}
		return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
	}

	return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType));
}
 
Example 18
Source File: KafkaStreamsFunctionProcessor.java    From spring-cloud-stream-binder-kafka with Apache License 2.0 4 votes vote down vote up
private Map<String, ResolvableType> buildTypeMap(ResolvableType resolvableType,
												KafkaStreamsBindableProxyFactory kafkaStreamsBindableProxyFactory) {
	Map<String, ResolvableType> resolvableTypeMap = new LinkedHashMap<>();
	if (resolvableType != null && resolvableType.getRawClass() != null) {
		int inputCount = 1;

		ResolvableType currentOutputGeneric;
		if (resolvableType.getRawClass().isAssignableFrom(BiFunction.class) ||
				resolvableType.getRawClass().isAssignableFrom(BiConsumer.class)) {
			inputCount = 2;
			currentOutputGeneric = resolvableType.getGeneric(2);
		}
		else {
			currentOutputGeneric = resolvableType.getGeneric(1);
		}
		while (currentOutputGeneric.getRawClass() != null && functionOrConsumerFound(currentOutputGeneric)) {
			inputCount++;
			currentOutputGeneric = currentOutputGeneric.getGeneric(1);
		}
		final Set<String> inputs = new LinkedHashSet<>(kafkaStreamsBindableProxyFactory.getInputs());

		final Iterator<String> iterator = inputs.iterator();

		popuateResolvableTypeMap(resolvableType, resolvableTypeMap, iterator);

		ResolvableType iterableResType = resolvableType;
		int i = resolvableType.getRawClass().isAssignableFrom(BiFunction.class) ||
				resolvableType.getRawClass().isAssignableFrom(BiConsumer.class) ? 2 : 1;
		ResolvableType outboundResolvableType;
		if (i == inputCount) {
			outboundResolvableType = iterableResType.getGeneric(i);
		}
		else {
			while (i < inputCount && iterator.hasNext()) {
				iterableResType = iterableResType.getGeneric(1);
				if (iterableResType.getRawClass() != null &&
						functionOrConsumerFound(iterableResType)) {
					popuateResolvableTypeMap(iterableResType, resolvableTypeMap, iterator);
				}
				i++;
			}
			outboundResolvableType = iterableResType.getGeneric(1);
		}
		resolvableTypeMap.put(OUTBOUND, outboundResolvableType);
	}
	return resolvableTypeMap;
}