Fix Sonar smells for HTTP & WebFlux modules (#2810)
* Fix Sonar smells for HTTP & WebFlux modules * * Fix more HTTP Sonar smells * * Remove unused import * Fix complexity in the `IntegrationMBeanExporter.enhanceSourceMonitor()` * * Remove unused `IntegrationMBeanExporter.getField()` method * * Remove unused import in the `IntegrationMBeanExporter`
This commit is contained in:
committed by
Gary Russell
parent
3751505823
commit
8f86ef918c
@@ -28,7 +28,6 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.integration.context.OrderlyShutdownCapable;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
@@ -51,20 +50,20 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
public class BaseHttpInboundEndpoint extends MessagingGatewaySupport implements OrderlyShutdownCapable {
|
||||
|
||||
protected static final boolean jaxb2Present = // NOSONAR lower case static
|
||||
protected static final boolean JAXB_PRESENT =
|
||||
ClassUtils.isPresent("javax.xml.bind.Binder",
|
||||
BaseHttpInboundEndpoint.class.getClassLoader());
|
||||
|
||||
protected static final boolean romeToolsPresent = // NOSONAR lower case static
|
||||
protected static final boolean ROME_TOOLS_PRESENT =
|
||||
ClassUtils.isPresent("com.rometools.rome.feed.atom.Feed",
|
||||
BaseHttpInboundEndpoint.class.getClassLoader());
|
||||
|
||||
protected static final List<HttpMethod> nonReadableBodyHttpMethods = // NOSONAR lower case static
|
||||
protected static final List<HttpMethod> NON_READABLE_BODY_HTTP_METHODS =
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS);
|
||||
|
||||
protected final boolean expectReply;
|
||||
protected final AtomicInteger activeCount = new AtomicInteger(); // NOSONAR
|
||||
|
||||
protected final AtomicInteger activeCount = new AtomicInteger();
|
||||
private final boolean expectReply;
|
||||
|
||||
private ResolvableType requestPayloadType = null;
|
||||
|
||||
@@ -268,13 +267,12 @@ public class BaseHttpInboundEndpoint extends MessagingGatewaySupport implements
|
||||
}
|
||||
|
||||
private void validateSupportedMethods() {
|
||||
if (this.requestPayloadType != null
|
||||
&& CollectionUtils.containsAny(nonReadableBodyHttpMethods,
|
||||
Arrays.asList(getRequestMapping().getMethods()))) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("The 'requestPayloadType' attribute will have no relevance for one " +
|
||||
"of the specified HTTP methods '" + nonReadableBodyHttpMethods + "'");
|
||||
}
|
||||
if (this.requestPayloadType != null && logger.isWarnEnabled() &&
|
||||
CollectionUtils.containsAny(NON_READABLE_BODY_HTTP_METHODS,
|
||||
Arrays.asList(getRequestMapping().getMethods()))) {
|
||||
|
||||
logger.warn("The 'requestPayloadType' attribute will have no relevance for one " +
|
||||
"of the specified HTTP methods '" + NON_READABLE_BODY_HTTP_METHODS + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,11 +327,11 @@ public class BaseHttpInboundEndpoint extends MessagingGatewaySupport implements
|
||||
|
||||
/**
|
||||
* Checks if the request has a readable body (not a GET, HEAD, or OPTIONS request).
|
||||
* @param request the HTTP request to check the method
|
||||
* @param httpMethod the HTTP method to check
|
||||
* @return true or false if HTTP request can contain the body
|
||||
*/
|
||||
protected boolean isReadable(HttpRequest request) {
|
||||
return !(CollectionUtils.containsInstance(nonReadableBodyHttpMethods, request.getMethod()));
|
||||
protected boolean isReadable(HttpMethod httpMethod) {
|
||||
return !(CollectionUtils.containsInstance(NON_READABLE_BODY_HTTP_METHODS, httpMethod));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -45,9 +45,9 @@ import org.springframework.web.servlet.mvc.Controller;
|
||||
* <p>
|
||||
* This endpoint will have request/reply behavior by default. That can be overridden by passing <code>false</code> to
|
||||
* the constructor. In the request/reply case, the core map will be passed to the view, and it will contain either the
|
||||
* reply Message or payload depending on the value of {@link #extractReplyPayload} (true by default, meaning just the
|
||||
* payload). The corresponding key in the map is determined by the {@link #replyKey} property (with a default of
|
||||
* "reply").
|
||||
* reply Message or payload depending on the value of {@link #setExtractReplyPayload(boolean)}
|
||||
* (true by default, meaning just the payload).
|
||||
* The corresponding key in the map is determined by the {@link #replyKey} property (with a default of "reply").
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
@@ -72,15 +72,15 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
*/
|
||||
public static final String DEFAULT_ERRORS_KEY = "errors";
|
||||
|
||||
private volatile Expression viewExpression;
|
||||
private Expression viewExpression;
|
||||
|
||||
private volatile StandardEvaluationContext evaluationContext;
|
||||
private StandardEvaluationContext evaluationContext;
|
||||
|
||||
private volatile String replyKey = DEFAULT_REPLY_KEY;
|
||||
private String replyKey = DEFAULT_REPLY_KEY;
|
||||
|
||||
private volatile String errorsKey = DEFAULT_ERRORS_KEY;
|
||||
private String errorsKey = DEFAULT_ERRORS_KEY;
|
||||
|
||||
private volatile String errorCode = DEFAULT_ERROR_CODE;
|
||||
private String errorCode = DEFAULT_ERROR_CODE;
|
||||
|
||||
public HttpRequestHandlingController() {
|
||||
this(true);
|
||||
@@ -157,7 +157,7 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
|
||||
RequestEntity<Object> httpEntity = prepareRequestEntity(request);
|
||||
|
||||
Message<?> replyMessage = doHandleRequest(servletRequest, httpEntity, servletResponse);
|
||||
Message<?> replyMessage = doHandleRequest(servletRequest, httpEntity);
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
if (replyMessage != null) {
|
||||
Object reply = setupResponseAndConvertReply(response, replyMessage);
|
||||
|
||||
@@ -19,20 +19,19 @@ package org.springframework.integration.http.inbound;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -53,11 +52,14 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.integration.MessageTimeoutException;
|
||||
import org.springframework.integration.expression.ExpressionEvalMap;
|
||||
import org.springframework.integration.http.HttpHeaders;
|
||||
import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter;
|
||||
import org.springframework.integration.http.multipart.MultipartHttpInputMessage;
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonPresent;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -109,21 +111,21 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
|
||||
private final List<HttpMessageConverter<?>> defaultMessageConverters = new ArrayList<>();
|
||||
|
||||
private volatile List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
|
||||
private List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
|
||||
|
||||
private volatile boolean convertersMerged;
|
||||
private boolean convertersMerged;
|
||||
|
||||
private volatile boolean mergeWithDefaultConverters = false;
|
||||
private boolean mergeWithDefaultConverters = false;
|
||||
|
||||
private volatile MultipartResolver multipartResolver;
|
||||
private MultipartResolver multipartResolver;
|
||||
|
||||
/**
|
||||
* Construct a gateway that will wait for the {@link #setReplyTimeout(long)
|
||||
* replyTimeout} for a reply; if the timeout is exceeded a '500 Internal Server Error'
|
||||
* status code is returned. This can be modified using the
|
||||
* {@link #setStatusCodeExpression(Expression) statusCodeExpression}.
|
||||
* {@link #setStatusCodeExpression statusCodeExpression}.
|
||||
* @see #setReplyTimeout(long)
|
||||
* @see #setStatusCodeExpression(Expression)
|
||||
* @see #setStatusCodeExpression
|
||||
*/
|
||||
public HttpRequestHandlingEndpointSupport() {
|
||||
this(true);
|
||||
@@ -133,12 +135,12 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
* Construct a gateway. If 'expectReply' is true it will wait for the
|
||||
* {@link #setReplyTimeout(long) replyTimeout} for a reply; if the timeout is exceeded
|
||||
* a '500 Internal Server Error' status code is returned. This can be modified using
|
||||
* the {@link #setStatusCodeExpression(Expression) statusCodeExpression}.
|
||||
* the {@link #setStatusCodeExpression statusCodeExpression}.
|
||||
* If 'false', a 200 OK status will be returned; this can also be modified using
|
||||
* {@link #setStatusCodeExpression(Expression) statusCodeExpression}.
|
||||
* {@link #setStatusCodeExpression statusCodeExpression}.
|
||||
* @param expectReply true if a reply is expected from the downstream flow.
|
||||
* @see #setReplyTimeout(long)
|
||||
* @see #setStatusCodeExpression(Expression)
|
||||
* @see #setStatusCodeExpression
|
||||
*/
|
||||
public HttpRequestHandlingEndpointSupport(boolean expectReply) {
|
||||
super(expectReply);
|
||||
@@ -150,7 +152,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
this.defaultMessageConverters.add(new ResourceHttpMessageConverter());
|
||||
SourceHttpMessageConverter<Source> sourceConverter = new SourceHttpMessageConverter<>();
|
||||
this.defaultMessageConverters.add(sourceConverter);
|
||||
if (jaxb2Present) {
|
||||
if (JAXB_PRESENT) {
|
||||
this.defaultMessageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
logger.debug("'Jaxb2RootElementHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
@@ -158,7 +160,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
this.defaultMessageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
logger.debug("'MappingJackson2HttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
if (romeToolsPresent) {
|
||||
if (ROME_TOOLS_PRESENT) {
|
||||
this.defaultMessageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new RssChannelHttpMessageConverter());
|
||||
logger.debug("'AtomFeedHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
@@ -244,63 +246,24 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
* 'expectReply' property is true, it will also generate a response from the reply Message once received.
|
||||
* @param servletRequest The servlet request.
|
||||
* @param httpEntity the request entity to use.
|
||||
* @param servletResponse The servlet response.
|
||||
* @return The response Message.
|
||||
*/
|
||||
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, RequestEntity<?> httpEntity,
|
||||
HttpServletResponse servletResponse) {
|
||||
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, RequestEntity<?> httpEntity) {
|
||||
if (isRunning()) {
|
||||
return actualDoHandleRequest(servletRequest, httpEntity, servletResponse);
|
||||
return actualDoHandleRequest(servletRequest, httpEntity);
|
||||
}
|
||||
else {
|
||||
return createServiceUnavailableResponse();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Message<?> actualDoHandleRequest(HttpServletRequest servletRequest, RequestEntity<?> httpEntity,
|
||||
HttpServletResponse servletResponse) {
|
||||
|
||||
private Message<?> actualDoHandleRequest(HttpServletRequest servletRequest, RequestEntity<?> httpEntity) {
|
||||
this.activeCount.incrementAndGet();
|
||||
try {
|
||||
StandardEvaluationContext evaluationContext = createEvaluationContext();
|
||||
evaluationContext.setRootObject(httpEntity);
|
||||
|
||||
evaluationContext.setVariable("requestAttributes", RequestContextHolder.currentRequestAttributes());
|
||||
|
||||
MultiValueMap<String, String> requestParams = convertParameterMap(servletRequest.getParameterMap());
|
||||
evaluationContext.setVariable("requestParams", requestParams);
|
||||
evaluationContext.setVariable("requestHeaders", new ServletServerHttpRequest(servletRequest).getHeaders());
|
||||
|
||||
Cookie[] requestCookies = servletRequest.getCookies();
|
||||
if (!ObjectUtils.isEmpty(requestCookies)) {
|
||||
Map<String, Cookie> cookies = new HashMap<>(requestCookies.length);
|
||||
for (Cookie requestCookie : requestCookies) {
|
||||
cookies.put(requestCookie.getName(), requestCookie);
|
||||
}
|
||||
evaluationContext.setVariable("cookies", cookies);
|
||||
}
|
||||
|
||||
Map<String, String> pathVariables =
|
||||
(Map<String, String>) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(pathVariables)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped path variables: " + pathVariables);
|
||||
}
|
||||
evaluationContext.setVariable("pathVariables", pathVariables);
|
||||
}
|
||||
|
||||
Map<String, MultiValueMap<String, String>> matrixVariables =
|
||||
(Map<String, MultiValueMap<String, String>>) servletRequest
|
||||
.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(matrixVariables)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped matrix variables: " + matrixVariables);
|
||||
}
|
||||
evaluationContext.setVariable("matrixVariables", matrixVariables);
|
||||
}
|
||||
StandardEvaluationContext evaluationContext =
|
||||
prepareEvaluationContext(servletRequest, httpEntity, requestParams);
|
||||
|
||||
Map<String, Object> headers = getHeaderMapper().toHeaders(httpEntity.getHeaders());
|
||||
Object payload = null;
|
||||
@@ -308,15 +271,12 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
// create payload based on SpEL
|
||||
payload = getPayloadExpression().getValue(evaluationContext);
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(getHeaderExpressions())) {
|
||||
for (Entry<String, Expression> entry : getHeaderExpressions().entrySet()) {
|
||||
String headerName = entry.getKey();
|
||||
Expression headerExpression = entry.getValue();
|
||||
Object headerValue = headerExpression.getValue(evaluationContext);
|
||||
if (headerValue != null) {
|
||||
headers.put(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
headers.putAll(
|
||||
ExpressionEvalMap.from(getHeaderExpressions())
|
||||
.usingEvaluationContext(evaluationContext)
|
||||
.build());
|
||||
}
|
||||
|
||||
if (payload == null) {
|
||||
@@ -328,36 +288,10 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
}
|
||||
}
|
||||
|
||||
AbstractIntegrationMessageBuilder<?> messageBuilder = null;
|
||||
|
||||
if (payload instanceof Message<?>) {
|
||||
messageBuilder =
|
||||
getMessageBuilderFactory()
|
||||
.fromMessage((Message<?>) payload)
|
||||
.copyHeadersIfAbsent(headers);
|
||||
}
|
||||
else {
|
||||
Assert.state(payload != null, "payload cannot be null");
|
||||
messageBuilder = getMessageBuilderFactory()
|
||||
.withPayload(payload)
|
||||
.copyHeaders(headers);
|
||||
}
|
||||
|
||||
HttpMethod method = httpEntity.getMethod();
|
||||
if (method != null) {
|
||||
messageBuilder.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_METHOD,
|
||||
method.toString());
|
||||
}
|
||||
|
||||
Message<?> message = messageBuilder
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_URL,
|
||||
httpEntity.getUrl().toString())
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL,
|
||||
servletRequest.getUserPrincipal())
|
||||
.build();
|
||||
Message<?> message = prepareRequestMessage(servletRequest, httpEntity, headers, payload);
|
||||
|
||||
Message<?> reply = null;
|
||||
if (this.expectReply) {
|
||||
if (isExpectReply()) {
|
||||
try {
|
||||
reply = sendAndReceiveMessage(message);
|
||||
}
|
||||
@@ -365,8 +299,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
reply =
|
||||
getMessageBuilderFactory()
|
||||
.withPayload(e.getMessage())
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE,
|
||||
evaluateHttpStatus(httpEntity))
|
||||
.setHeader(HttpHeaders.STATUS_CODE, evaluateHttpStatus(httpEntity))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -381,13 +314,82 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
}
|
||||
}
|
||||
|
||||
private Message<?> prepareRequestMessage(HttpServletRequest servletRequest, RequestEntity<?> httpEntity,
|
||||
Map<String, Object> headers, Object payload) {
|
||||
|
||||
AbstractIntegrationMessageBuilder<?> messageBuilder;
|
||||
|
||||
if (payload instanceof Message<?>) {
|
||||
messageBuilder =
|
||||
getMessageBuilderFactory()
|
||||
.fromMessage((Message<?>) payload)
|
||||
.copyHeadersIfAbsent(headers);
|
||||
}
|
||||
else {
|
||||
Assert.state(payload != null, "payload cannot be null");
|
||||
messageBuilder = getMessageBuilderFactory()
|
||||
.withPayload(payload)
|
||||
.copyHeaders(headers);
|
||||
}
|
||||
|
||||
HttpMethod method = httpEntity.getMethod();
|
||||
if (method != null) {
|
||||
messageBuilder.setHeader(HttpHeaders.REQUEST_METHOD, method.toString());
|
||||
}
|
||||
|
||||
return messageBuilder
|
||||
.setHeader(HttpHeaders.REQUEST_URL, httpEntity.getUrl().toString())
|
||||
.setHeader(HttpHeaders.USER_PRINCIPAL, servletRequest.getUserPrincipal())
|
||||
.build();
|
||||
}
|
||||
|
||||
private StandardEvaluationContext prepareEvaluationContext(HttpServletRequest servletRequest,
|
||||
RequestEntity<?> httpEntity, MultiValueMap<String, String> requestParams) {
|
||||
|
||||
StandardEvaluationContext evaluationContext = createEvaluationContext();
|
||||
evaluationContext.setRootObject(httpEntity);
|
||||
|
||||
evaluationContext.setVariable("requestAttributes", RequestContextHolder.currentRequestAttributes());
|
||||
|
||||
evaluationContext.setVariable("requestParams", requestParams);
|
||||
evaluationContext.setVariable("requestHeaders", new ServletServerHttpRequest(servletRequest).getHeaders());
|
||||
|
||||
Cookie[] requestCookies = servletRequest.getCookies();
|
||||
if (!ObjectUtils.isEmpty(requestCookies)) {
|
||||
Map<String, Cookie> cookies =
|
||||
Arrays.stream(requestCookies)
|
||||
.collect(Collectors.toMap(Cookie::getName, Function.identity()));
|
||||
evaluationContext.setVariable("cookies", cookies);
|
||||
}
|
||||
|
||||
Map<?, ?> pathVariables =
|
||||
(Map<?, ?>) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(pathVariables)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped path variables: " + pathVariables);
|
||||
}
|
||||
evaluationContext.setVariable("pathVariables", pathVariables);
|
||||
}
|
||||
|
||||
Map<?, ?> matrixVariables = (Map<?, ?>) servletRequest.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(matrixVariables)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped matrix variables: " + matrixVariables);
|
||||
}
|
||||
evaluationContext.setVariable("matrixVariables", matrixVariables);
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
private Message<?> createServiceUnavailableResponse() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Endpoint is stopped; returning status " + HttpStatus.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
return getMessageBuilderFactory()
|
||||
.withPayload("Endpoint is stopped")
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE, HttpStatus.SERVICE_UNAVAILABLE)
|
||||
.setHeader(HttpHeaders.STATUS_CODE, HttpStatus.SERVICE_UNAVAILABLE)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -399,8 +401,9 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
* @return The message payload (if {@code extractReplyPayload}) otherwise the message.
|
||||
*/
|
||||
protected final Object setupResponseAndConvertReply(ServletServerHttpResponse response, Message<?> replyMessage) {
|
||||
getHeaderMapper().fromHeaders(replyMessage.getHeaders(), response.getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(replyMessage.getHeaders());
|
||||
MessageHeaders replyMessageHeaders = replyMessage.getHeaders();
|
||||
getHeaderMapper().fromHeaders(replyMessageHeaders, response.getHeaders());
|
||||
HttpStatus httpStatus = resolveHttpStatusFromHeaders(replyMessageHeaders);
|
||||
if (httpStatus != null) {
|
||||
response.setStatusCode(httpStatus);
|
||||
}
|
||||
@@ -468,7 +471,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
|
||||
protected RequestEntity<Object> prepareRequestEntity(ServletServerHttpRequest request) throws IOException {
|
||||
Object requestBody = null;
|
||||
if (isReadable(request)) {
|
||||
if (isReadable(request.getMethod())) {
|
||||
requestBody = extractRequestBody(request);
|
||||
}
|
||||
|
||||
@@ -499,8 +502,8 @@ public abstract class HttpRequestHandlingEndpointSupport extends BaseHttpInbound
|
||||
? (GenericHttpMessageConverter<?>) converter
|
||||
: null;
|
||||
if (genericConverter != null
|
||||
? genericConverter.canRead(targetType, null, contentType) :
|
||||
(converter.canRead(targetClass, contentType))) {
|
||||
? genericConverter.canRead(targetType, null, contentType)
|
||||
: (converter.canRead(targetClass, contentType))) {
|
||||
|
||||
if (genericConverter != null) {
|
||||
return genericConverter.read(targetType, null, request);
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.web.HttpRequestHandler;
|
||||
/**
|
||||
* Inbound Messaging Gateway that handles HTTP Requests. May be configured as a bean in the Application Context and
|
||||
* delegated to from a simple HttpRequestHandlerServlet in <code>web.xml</code> where the servlet and bean both have the
|
||||
* same name. If the {@link #expectReply} property is set to true, a response can generated from a reply Message.
|
||||
* same name. If the {@link #isExpectReply()} property is set to true, a response can generated from a reply Message.
|
||||
* Otherwise, the gateway will play the role of a unidirectional Channel Adapter with a simple status-based response
|
||||
* (e.g. 200 OK).
|
||||
* <p>
|
||||
@@ -109,14 +109,15 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
RequestEntity<Object> httpEntity = prepareRequestEntity(request);
|
||||
|
||||
try {
|
||||
responseMessage = doHandleRequest(servletRequest, httpEntity, servletResponse);
|
||||
responseMessage = doHandleRequest(servletRequest, httpEntity);
|
||||
if (responseMessage != null) {
|
||||
responseContent = setupResponseAndConvertReply(response, responseMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
responseContent = handleExceptionInternal(e);
|
||||
catch (Exception ex) {
|
||||
responseContent = handleExceptionInternal(ex);
|
||||
}
|
||||
|
||||
if (responseContent != null) {
|
||||
|
||||
if (responseContent instanceof HttpStatus) {
|
||||
@@ -131,11 +132,10 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
HttpHeaders outputHeaders = response.getHeaders();
|
||||
HttpHeaders entityHeaders = responseEntity.getHeaders();
|
||||
|
||||
if (!entityHeaders.isEmpty()) {
|
||||
entityHeaders.entrySet().stream()
|
||||
.filter(entry -> !outputHeaders.containsKey(entry.getKey()))
|
||||
.forEach(entry -> outputHeaders.put(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
entityHeaders.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> !outputHeaders.containsKey(entry.getKey()))
|
||||
.forEach(entry -> outputHeaders.put(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
if (responseContent != null) {
|
||||
@@ -151,24 +151,23 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
}
|
||||
}
|
||||
|
||||
private Object handleExceptionInternal(Exception e) throws IOException {
|
||||
private Object handleExceptionInternal(Exception ex) throws IOException {
|
||||
if (this.convertExceptions && isExpectReply()) {
|
||||
return e;
|
||||
return ex;
|
||||
}
|
||||
else {
|
||||
if (e instanceof IOException) {
|
||||
throw (IOException) e;
|
||||
if (ex instanceof IOException) {
|
||||
throw (IOException) ex;
|
||||
}
|
||||
else if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
else if (ex instanceof RuntimeException) {
|
||||
throw (RuntimeException) ex;
|
||||
}
|
||||
else {
|
||||
throw new MessagingException("error occurred handling HTTP request", e);
|
||||
throw new MessagingException("error occurred handling HTTP request", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void writeResponse(Object content, ServletServerHttpResponse response, List<MediaType> acceptTypesArg)
|
||||
throws IOException {
|
||||
|
||||
@@ -176,10 +175,12 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
if (CollectionUtils.isEmpty(acceptTypes)) {
|
||||
acceptTypes = Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
for (HttpMessageConverter converter : getMessageConverters()) {
|
||||
for (HttpMessageConverter<?> converter : getMessageConverters()) {
|
||||
for (MediaType acceptType : acceptTypes) {
|
||||
if (converter.canWrite(content.getClass(), acceptType)) {
|
||||
converter.write(content, acceptType, response);
|
||||
@SuppressWarnings("unchecked")
|
||||
HttpMessageConverter<Object> converterToUse = (HttpMessageConverter<Object>) converter;
|
||||
converterToUse.write(content, acceptType, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
|
||||
|
||||
RequestEntity<Object> httpEntity = prepareRequestEntity(body, new ServletServerHttpRequest(request));
|
||||
|
||||
Object result = gateway.doHandleRequest(request, httpEntity, response);
|
||||
Object result = gateway.doHandleRequest(request, httpEntity);
|
||||
assertThat(result).isInstanceOf(Message.class);
|
||||
assertThat(((Message<?>) result).getPayload()).isEqualTo("hello");
|
||||
|
||||
@@ -96,8 +96,6 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
|
||||
replyChannel.send(message);
|
||||
});
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
request.setMethod("POST");
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
@@ -127,7 +125,7 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
|
||||
|
||||
RequestEntity<Object> httpEntity = prepareRequestEntity(body, new ServletServerHttpRequest(request));
|
||||
|
||||
Object result = gateway.doHandleRequest(request, httpEntity, response);
|
||||
Object result = gateway.doHandleRequest(request, httpEntity);
|
||||
assertThat(result).isInstanceOf(Message.class);
|
||||
assertThat(((Message<?>) result).getPayload()).isEqualTo("bill");
|
||||
}
|
||||
@@ -173,12 +171,12 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests extends Abs
|
||||
|
||||
RequestEntity<Object> httpEntity = prepareRequestEntity(body, new ServletServerHttpRequest(request));
|
||||
|
||||
Object result = gateway.doHandleRequest(request, httpEntity, response);
|
||||
Object result = gateway.doHandleRequest(request, httpEntity);
|
||||
assertThat(result).isInstanceOf(Message.class);
|
||||
assertThat(((Map<String, Object>) ((Message<?>) result).getPayload()).get("f")).isEqualTo("bill");
|
||||
}
|
||||
|
||||
private static RequestEntity<Object> prepareRequestEntity(Object body, ServletServerHttpRequest request) throws IOException {
|
||||
private static RequestEntity<Object> prepareRequestEntity(Object body, ServletServerHttpRequest request) {
|
||||
return new RequestEntity<>(body, request.getHeaders(), request.getMethod(), request.getURI());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.integration.monitor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -78,6 +77,7 @@ import org.springframework.jmx.export.UnableToRegisterMBeanException;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedMetric;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
|
||||
import org.springframework.jmx.support.MetricType;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -114,7 +114,7 @@ import org.springframework.util.StringValueResolver;
|
||||
* @author Artem Bilan
|
||||
* @author Meherzad Lahewala
|
||||
*/
|
||||
@org.springframework.jmx.export.annotation.ManagedResource
|
||||
@ManagedResource
|
||||
public class IntegrationMBeanExporter extends MBeanExporter implements ApplicationContextAware,
|
||||
EmbeddedValueResolverAware, DestructionAwareBeanPostProcessor {
|
||||
|
||||
@@ -1036,32 +1036,21 @@ public class IntegrationMBeanExporter extends MBeanExporter implements Applicati
|
||||
return monitor;
|
||||
}
|
||||
|
||||
// Assignment algorithm and bean id, with bean id pulled reflectively out of enclosing endpoint if possible
|
||||
String[] names = this.applicationContext.getBeanNamesForType(AbstractEndpoint.class);
|
||||
|
||||
String name = null;
|
||||
String endpointName = null;
|
||||
String source = "endpoint";
|
||||
Object endpoint = null;
|
||||
|
||||
String[] names = this.applicationContext.getBeanNamesForType(AbstractEndpoint.class);
|
||||
for (String beanName : names) {
|
||||
endpoint = this.applicationContext.getBean(beanName);
|
||||
Object field = null;
|
||||
Object target = null;
|
||||
if (monitor instanceof MessagingGatewaySupport && endpoint.equals(monitor)) {
|
||||
field = monitor;
|
||||
target = monitor;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
field = extractTarget(getField(endpoint, "source"));
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.trace("Could not get source from bean = " + beanName);
|
||||
endpoint = null;
|
||||
}
|
||||
else if (endpoint instanceof SourcePollingChannelAdapter) {
|
||||
target = ((SourcePollingChannelAdapter) endpoint).getMessageSource();
|
||||
}
|
||||
|
||||
if (monitor.equals(field)) {
|
||||
name = beanName;
|
||||
if (monitor.equals(target)) {
|
||||
endpointName = beanName;
|
||||
break;
|
||||
}
|
||||
@@ -1070,12 +1059,13 @@ public class IntegrationMBeanExporter extends MBeanExporter implements Applicati
|
||||
if (endpointName == null) {
|
||||
endpoint = null;
|
||||
}
|
||||
if (name != null && name.startsWith('_' + SI_PACKAGE)) {
|
||||
name = getInternalComponentName(name);
|
||||
if (endpointName != null && endpointName.startsWith('_' + SI_PACKAGE)) {
|
||||
endpointName = getInternalComponentName(endpointName);
|
||||
source = "internal";
|
||||
}
|
||||
|
||||
MessageSourceMetrics messageSourceMetrics = buildMessageSourceMetricsIfAny(monitor, name, source, endpoint);
|
||||
MessageSourceMetrics messageSourceMetrics =
|
||||
buildMessageSourceMetricsIfAny(monitor, endpointName, source, endpoint);
|
||||
if (endpointName != null) {
|
||||
this.endpointsByMonitor.put(messageSourceMetrics, endpointName);
|
||||
}
|
||||
@@ -1155,18 +1145,4 @@ public class IntegrationMBeanExporter extends MBeanExporter implements Applicati
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object getField(Object target, String name) {
|
||||
Assert.notNull(target, "Target object must not be null");
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Could not find field [" + name + "] on target [" + target + "]");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Getting field [" + name + "] from target [" + target + "]");
|
||||
}
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
* Copyright 2017-2019 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.
|
||||
@@ -34,7 +34,6 @@ import org.springframework.core.ReactiveAdapter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -47,6 +46,7 @@ import org.springframework.http.codec.HttpMessageWriter;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.integration.expression.ExpressionEvalMap;
|
||||
import org.springframework.integration.http.inbound.BaseHttpInboundEndpoint;
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -81,8 +81,6 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
|
||||
private static final MediaType MEDIA_TYPE_APPLICATION_ALL = new MediaType("application");
|
||||
|
||||
private static final String UNCHECKED = "unchecked";
|
||||
|
||||
private static final List<HttpMethod> SAFE_METHODS = Arrays.asList(HttpMethod.GET, HttpMethod.HEAD);
|
||||
|
||||
private ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create();
|
||||
@@ -155,7 +153,7 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
exchange.getRequest().getMethod(), exchange.getRequest().getURI()))
|
||||
.flatMap(entity -> buildMessage(entity, exchange))
|
||||
.flatMap(requestTuple -> {
|
||||
if (this.expectReply) {
|
||||
if (isExpectReply()) {
|
||||
return sendAndReceiveMessageReactive(requestTuple.getT1())
|
||||
.flatMap(replyMessage -> populateResponse(exchange, replyMessage));
|
||||
}
|
||||
@@ -169,7 +167,7 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
}
|
||||
|
||||
private Mono<?> extractRequestBody(ServerWebExchange exchange) {
|
||||
if (isReadable(exchange.getRequest())) {
|
||||
if (isReadable(exchange.getRequest().getMethod())) {
|
||||
return extractReadableRequestBody(exchange);
|
||||
}
|
||||
else {
|
||||
@@ -242,7 +240,6 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings(UNCHECKED)
|
||||
private Mono<Tuple2<Message<Object>, RequestEntity<?>>> buildMessage(RequestEntity<?> httpEntity,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
@@ -260,20 +257,32 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
|
||||
Map<String, Object> headers = getHeaderMapper().toHeaders(request.getHeaders());
|
||||
if (!CollectionUtils.isEmpty(getHeaderExpressions())) {
|
||||
for (Map.Entry<String, Expression> entry : getHeaderExpressions().entrySet()) {
|
||||
String headerName = entry.getKey();
|
||||
Expression headerExpression = entry.getValue();
|
||||
Object headerValue = headerExpression.getValue(evaluationContext);
|
||||
if (headerValue != null) {
|
||||
headers.put(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
headers.putAll(
|
||||
ExpressionEvalMap.from(getHeaderExpressions())
|
||||
.usingEvaluationContext(evaluationContext)
|
||||
.build());
|
||||
}
|
||||
|
||||
if (payload == null) {
|
||||
payload = requestParams;
|
||||
}
|
||||
|
||||
AbstractIntegrationMessageBuilder<Object> messageBuilder =
|
||||
prepareRequestMessageBuilder(request, payload, headers);
|
||||
|
||||
return exchange.getPrincipal()
|
||||
.map(principal ->
|
||||
messageBuilder
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL, principal))
|
||||
.defaultIfEmpty(messageBuilder)
|
||||
.map(AbstractIntegrationMessageBuilder::build)
|
||||
.zipWith(Mono.just(httpEntity));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private AbstractIntegrationMessageBuilder<Object> prepareRequestMessageBuilder(ServerHttpRequest request,
|
||||
Object payload, Map<String, Object> headers) {
|
||||
|
||||
AbstractIntegrationMessageBuilder<Object> messageBuilder;
|
||||
|
||||
if (payload instanceof Message<?>) {
|
||||
@@ -296,17 +305,9 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
messageBuilder.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_METHOD,
|
||||
httpMethod.toString());
|
||||
}
|
||||
|
||||
return exchange.getPrincipal()
|
||||
.map(principal ->
|
||||
messageBuilder
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL, principal))
|
||||
.defaultIfEmpty(messageBuilder)
|
||||
.map(AbstractIntegrationMessageBuilder::build)
|
||||
.zipWith(Mono.just(httpEntity));
|
||||
return messageBuilder;
|
||||
}
|
||||
|
||||
@SuppressWarnings(UNCHECKED)
|
||||
private EvaluationContext buildEvaluationContext(RequestEntity<?> httpEntity, ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
HttpHeaders requestHeaders = request.getHeaders();
|
||||
@@ -322,16 +323,13 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
evaluationContext.setVariable("cookies", request.getCookies());
|
||||
}
|
||||
|
||||
Map<String, String> pathVariables =
|
||||
(Map<String, String>) exchangeAttributes.get(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
Map<?, ?> pathVariables = (Map<?, ?>) exchangeAttributes.get(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(pathVariables)) {
|
||||
evaluationContext.setVariable("pathVariables", pathVariables);
|
||||
}
|
||||
|
||||
Map<String, MultiValueMap<String, String>> matrixVariables =
|
||||
(Map<String, MultiValueMap<String, String>>) exchangeAttributes
|
||||
.get(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);
|
||||
Map<?, ?> matrixVariables = (Map<?, ?>) exchangeAttributes.get(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(matrixVariables)) {
|
||||
evaluationContext.setVariable("matrixVariables", matrixVariables);
|
||||
@@ -396,7 +394,7 @@ public class WebFluxInboundEndpoint extends BaseHttpInboundEndpoint implements W
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings(UNCHECKED)
|
||||
@SuppressWarnings("unchecked")
|
||||
private Mono<Void> writeResponseBody(ServerWebExchange exchange, Object body) {
|
||||
ResolvableType bodyType = ResolvableType.forInstance(body);
|
||||
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(bodyType.resolve(), body);
|
||||
|
||||
Reference in New Issue
Block a user