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:
Artem Bilan
2019-03-18 10:08:37 -04:00
committed by Gary Russell
parent 3751505823
commit 8f86ef918c
7 changed files with 194 additions and 220 deletions

View File

@@ -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));
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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());
}

View File

@@ -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);
}
}

View File

@@ -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);