INT-4156: Merge HTTP Java DSL and Some Refinements

JIRA: https://jira.spring.io/browse/INT-4156

* Copy `Http` Java DSL from with some fixes to the `HttpMessageHandlerSpec` and Java 8 style
* Port `HttpDslTests` and "de-Boot" it with the Mock MVC
* Upgrade to Spring Security 4.2.0
* Make `spring-integration-security` as a dependency for HTTP module for better test coverage for Security from SI Web perspective

No need in `AuthenticationManager` bean

JavaDocs for HTTP DSL components and some JavaDocs improvements for `HttpRequestHandlingEndpointSupport` and `HttpRequestExecutingMessageHandler`

Restore optional ROME dependency for proper HTTP module compilation

Add missed JavaDoc and mark all HTTP tests with `@DirtiesContext`

Add JavaDocs for `Http` factory methods
This commit is contained in:
Artem Bilan
2016-11-10 14:10:01 -05:00
committed by Gary Russell
parent 803d9f0875
commit 6c4d9b2111
18 changed files with 1476 additions and 23 deletions

View File

@@ -10,7 +10,7 @@ buildscript {
}
plugins {
id 'org.sonarqube' version '1.2'
id 'org.sonarqube' version '2.1'
}
description = 'Spring Integration'
@@ -127,7 +127,7 @@ subprojects { subproject ->
springDataMongoVersion = '1.10.0.BUILD-SNAPSHOT'
springDataRedisVersion = '1.8.0.BUILD-SNAPSHOT'
springGemfireVersion = '1.9.0.BUILD-SNAPSHOT'
springSecurityVersion = '4.1.2.RELEASE'
springSecurityVersion = '4.2.0.RELEASE'
springSocialTwitterVersion = '1.1.2.RELEASE'
springRetryVersion = '1.2.0.RC1'
springVersion = project.hasProperty('springVersion') ? project.springVersion : '5.0.0.BUILD-SNAPSHOT'
@@ -380,8 +380,12 @@ project('spring-integration-http') {
dependencies {
compile project(":spring-integration-core")
compile "org.springframework:spring-webmvc:$springVersion"
compile("com.rometools:rome:$romeToolsVersion", optional)
compile("javax.servlet:javax.servlet-api:$servletApiVersion", provided)
compile ("javax.servlet:javax.servlet-api:$servletApiVersion", provided)
compile ("com.rometools:rome:$romeToolsVersion", optional)
testCompile project(":spring-integration-security")
testCompile "org.springframework.security:spring-security-config:$springSecurityVersion"
testCompile "org.springframework.security:spring-security-test:$springSecurityVersion"
}
}

View File

@@ -0,0 +1,468 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.springframework.expression.Expression;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessagingGatewaySpec;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.http.inbound.CrossOrigin;
import org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport;
import org.springframework.integration.http.inbound.RequestMapping;
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.mapping.HeaderMapper;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartResolver;
/**
* A base {@link MessagingGatewaySpec} for the {@link HttpRequestHandlingEndpointSupport} implementations.
*
* @param <S> the target {@link BaseHttpInboundEndpointSpec} implementation type.
* @param <E> the target {@link HttpRequestHandlingEndpointSupport} implementation type.
*
* @author Artem Bilan
*
* @since 5.0
*/
public abstract class BaseHttpInboundEndpointSpec<S extends BaseHttpInboundEndpointSpec<S, E>,
E extends HttpRequestHandlingEndpointSupport>
extends MessagingGatewaySpec<S, E> implements ComponentsRegistration {
private final RequestMapping requestMapping = new RequestMapping();
private final Map<String, Expression> headerExpressions = new HashMap<>();
private final HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.inboundMapper();
private HeaderMapper<HttpHeaders> explicitHeaderMapper;
BaseHttpInboundEndpointSpec(E endpoint, String... path) {
super(endpoint);
this.requestMapping.setPathPatterns(path);
this.target.setRequestMapping(this.requestMapping);
this.target.setHeaderExpressions(this.headerExpressions);
this.target.setHeaderMapper(this.headerMapper);
}
/**
* Provide a {@link Consumer} for configuring {@link RequestMapping} via {@link RequestMappingSpec}
* @param requestMapping the {@link Consumer} to configure {@link RequestMappingSpec}.
* @return the spec
* @see RequestMapping
*/
public S requestMapping(Consumer<RequestMappingSpec> requestMapping) {
requestMapping.accept(new RequestMappingSpec(this.requestMapping));
return _this();
}
/**
* Provide a {@link Consumer} for configuring {@link CrossOrigin} via {@link CrossOriginSpec}
* @param crossOrigin the {@link Consumer} to configure {@link CrossOriginSpec}.
* @return the spec
* @see CrossOrigin
*/
public S crossOrigin(Consumer<CrossOriginSpec> crossOrigin) {
CrossOriginSpec originSpec = new CrossOriginSpec();
crossOrigin.accept(originSpec);
this.target.setCrossOrigin(originSpec.crossOrigin);
return _this();
}
/**
* Specify a SpEL expression to evaluate in order to generate the Message payload.
* @param payloadExpression The payload expression.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setPayloadExpression(Expression)
*/
public S payloadExpression(String payloadExpression) {
return payloadExpression(PARSER.parseExpression(payloadExpression));
}
/**
* Specify a SpEL expression to evaluate in order to generate the Message payload.
* @param payloadExpression The payload expression.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setPayloadExpression(Expression)
*/
public S payloadExpression(Expression payloadExpression) {
this.target.setPayloadExpression(payloadExpression);
return _this();
}
/**
* Specify a {@link Function} to evaluate in order to generate the Message payload.
* @param payloadFunction The payload {@link Function}.
* @param <P> the expected HTTP request body type.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setPayloadExpression(Expression)
*/
public <P> S payloadFunction(Function<HttpEntity<P>, ?> payloadFunction) {
return payloadExpression(new FunctionExpression<>(payloadFunction));
}
/**
* Specify a Map of SpEL expressions to evaluate in order to generate the Message headers.
* @param headerExpressions The {@link Map} of SpEL expressions for headers.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setHeaderExpressions(Map)
*/
public S headerExpressions(Map<String, Expression> headerExpressions) {
Assert.notNull(headerExpressions, "'headerExpressions' must not be null");
this.headerExpressions.clear();
this.headerExpressions.putAll(headerExpressions);
return _this();
}
/**
* Specify SpEL expression for provided header to populate.
* @param header the header name to populate.
* @param expression the SpEL expression for the header.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setHeaderExpressions(Map)
*/
public S headerExpression(String header, String expression) {
return headerExpression(header, PARSER.parseExpression(expression));
}
/**
* Specify SpEL expression for provided header to populate.
* @param header the header name to populate.
* @param expression the SpEL expression for the header.
* @return the spec
* @see HttpRequestHandlingEndpointSupport#setHeaderExpressions(Map)
*/
public S headerExpression(String header, Expression expression) {
this.headerExpressions.put(header, expression);
return _this();
}
/**
* Specify a {@link Function} for provided header to populate.
* @param header the header name to add.
* @param headerFunction the function to evaluate the header value against {@link HttpEntity}.
* @param <P> the expected HTTP body type.
* @return the current Spec.
* @see HttpRequestHandlingEndpointSupport#setHeaderExpressions(Map)
*/
public <P> S headerFunction(String header, Function<HttpEntity<P>, ?> headerFunction) {
return headerExpression(header, new FunctionExpression<>(headerFunction));
}
/**
* Set the message body converters to use.
* These converters are used to convert from and to HTTP requests and responses.
* @param messageConverters The message converters.
* @return the current Spec.
*/
public S messageConverters(HttpMessageConverter<?>... messageConverters) {
this.target.setMessageConverters(Arrays.asList(messageConverters));
return _this();
}
/**
* Flag which determines if the default converters should be available after custom converters.
* @param mergeWithDefaultConverters true to merge, false to replace.
* @return the current Spec.
*/
public S mergeWithDefaultConverters(boolean mergeWithDefaultConverters) {
this.target.setMergeWithDefaultConverters(mergeWithDefaultConverters);
return _this();
}
/**
* Set the {@link HeaderMapper} to use when mapping between HTTP headers and MessageHeaders.
* @param headerMapper The header mapper.
* @return the current Spec.
*/
public S headerMapper(HeaderMapper<HttpHeaders> headerMapper) {
this.target.setHeaderMapper(headerMapper);
this.explicitHeaderMapper = headerMapper;
return _this();
}
/**
* Provide the pattern array for request headers to map.
* @param patterns the patterns for request headers to map.
* @return the current Spec.
* @see DefaultHttpHeaderMapper#setOutboundHeaderNames(String[])
*/
public S mappedRequestHeaders(String... patterns) {
Assert.isNull(this.explicitHeaderMapper,
"The 'mappedRequestHeaders' must be specified on the provided 'headerMapper': "
+ this.explicitHeaderMapper);
((DefaultHttpHeaderMapper) this.headerMapper).setOutboundHeaderNames(patterns);
return _this();
}
/**
* Provide the pattern array for response headers to map.
* @param patterns the patterns for response headers to map.
* @return the current Spec.
* @see DefaultHttpHeaderMapper#setInboundHeaderNames(String[])
*/
public S mappedResponseHeaders(String... patterns) {
Assert.isNull(this.explicitHeaderMapper,
"The 'mappedRequestHeaders' must be specified on the provided 'headerMapper': "
+ this.explicitHeaderMapper);
((DefaultHttpHeaderMapper) this.headerMapper).setInboundHeaderNames(patterns);
return _this();
}
/**
* Specify the type of payload to be generated when the inbound HTTP request content is read by the
* {@link HttpMessageConverter}s.
* By default this value is null which means at runtime any "text" Content-Type will
* result in String while all others default to <code>byte[].class</code>.
* @param requestPayloadType The payload type.
* @return the current Spec.
*/
public S requestPayloadType(Class<?> requestPayloadType) {
this.target.setRequestPayloadType(requestPayloadType);
return _this();
}
/**
* Specify whether only the reply Message's payload should be passed in the response.
* If this is set to {@code false}, the entire Message will be used to generate the response.
* The default is {@code true}.
* @param extractReplyPayload true to extract the reply payload.
* @return the current Spec.
*/
public S extractReplyPayload(boolean extractReplyPayload) {
this.target.setExtractReplyPayload(extractReplyPayload);
return _this();
}
/**
* Specify the {@link MultipartResolver} to use when checking requests.
* @param multipartResolver The multipart resolver.
* @return the current Spec.
*/
public S multipartResolver(MultipartResolver multipartResolver) {
this.target.setMultipartResolver(multipartResolver);
return _this();
}
/**
* Specify the {@link Expression} to resolve a status code for Response to override
* the default '200 OK' or '500 Internal Server Error' for a timeout.
* @param statusCodeExpression The status code Expression.
* @return the current Spec.
* @see HttpRequestHandlingEndpointSupport#setStatusCodeExpression(Expression)
*/
public S statusCodeExpression(String statusCodeExpression) {
this.target.setStatusCodeExpressionString(statusCodeExpression);
return _this();
}
/**
* Specify the {@link Expression} to resolve a status code for Response to override
* the default '200 OK' or '500 Internal Server Error' for a timeout.
* @param statusCodeExpression The status code Expression.
* @return the current Spec.
* @see HttpRequestHandlingEndpointSupport#setStatusCodeExpression(Expression)
*/
public S statusCodeExpression(Expression statusCodeExpression) {
this.target.setStatusCodeExpression(statusCodeExpression);
return _this();
}
/**
* Specify the {@link Function} to resolve a status code for Response to override
* the default '200 OK' or '500 Internal Server Error' for a timeout.
* @param statusCodeFunction The status code {@link Function}.
* @return the current Spec.
* @see HttpRequestHandlingEndpointSupport#setStatusCodeExpression(Expression)
*/
public S statusCodeFunction(Function<Void, ?> statusCodeFunction) {
return statusCodeExpression(new FunctionExpression<>(statusCodeFunction));
}
@Override
public Collection<Object> getComponentsToRegister() {
HeaderMapper<HttpHeaders> headerMapperToRegister =
(this.explicitHeaderMapper != null ? this.explicitHeaderMapper : this.headerMapper);
return Collections.singletonList(headerMapperToRegister);
}
/**
* A fluent API for the {@link RequestMapping}.
*/
public static final class RequestMappingSpec {
private final RequestMapping requestMapping;
RequestMappingSpec(RequestMapping requestMapping) {
this.requestMapping = requestMapping;
}
/**
* The HTTP request methods to map to, narrowing the primary mapping:
* GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
* @param supportedMethods the {@link HttpMethod}s to use.
* @return the spec
*/
public RequestMappingSpec methods(HttpMethod... supportedMethods) {
this.requestMapping.setMethods(supportedMethods);
return this;
}
/**
* The parameters of the mapped request, narrowing the primary mapping.
* @param params the request params to map to.
* @return the spec
*/
public RequestMappingSpec params(String... params) {
this.requestMapping.setParams(params);
return this;
}
/**
* The headers of the mapped request, narrowing the primary mapping.
* @param headers the request headers to map to.
* @return the spec
*/
public RequestMappingSpec headers(String... headers) {
this.requestMapping.setHeaders(headers);
return this;
}
/**
* The consumable media types of the mapped request, narrowing the primary mapping.
* @param consumes the the media types for {@code Content-Type} header.
* @return the spec
*/
public RequestMappingSpec consumes(String... consumes) {
this.requestMapping.setConsumes(consumes);
return this;
}
/**
* The producible media types of the mapped request, narrowing the primary mapping.
* @param produces the the media types for {@code Accept} header.
* @return the spec
*/
public RequestMappingSpec produces(String... produces) {
this.requestMapping.setProduces(produces);
return this;
}
}
/**
* A fluent API for the {@link CrossOrigin}.
*/
public static final class CrossOriginSpec {
private final CrossOrigin crossOrigin = new CrossOrigin();
CrossOriginSpec() {
super();
}
/**
* List of allowed origins, e.g. {@code "http://domain1.com"}.
* <p>These values are placed in the {@code Access-Control-Allow-Origin}
* header of both the pre-flight response and the actual response.
* {@code "*"} means that all origins are allowed.
* <p>If undefined, all origins are allowed.
* @param origin the list of allowed origins.
* @return the spec
*/
public CrossOriginSpec origin(String... origin) {
this.crossOrigin.setOrigin(origin);
return this;
}
/**
* List of request headers that can be used during the actual request.
* <p>This property controls the value of the pre-flight response's
* {@code Access-Control-Allow-Headers} header.
* {@code "*"} means that all headers requested by the client are allowed.
* @param allowedHeaders the list of request headers.
* @return the spec
*/
public CrossOriginSpec allowedHeaders(String... allowedHeaders) {
this.crossOrigin.setAllowedHeaders(allowedHeaders);
return this;
}
/**
* List of response headers that the user-agent will allow the client to access.
* <p>This property controls the value of actual response's
* {@code Access-Control-Expose-Headers} header.
* @param exposedHeaders the list of response headers.
* @return the spec
*/
public CrossOriginSpec exposedHeaders(String... exposedHeaders) {
this.crossOrigin.setExposedHeaders(exposedHeaders);
return this;
}
/**
* List of supported HTTP request methods, e.g.
* {@code "{RequestMethod.GET, RequestMethod.POST}"}.
* <p>Methods specified here override those specified via {@code RequestMapping}.
* @param method the list of supported HTTP request methods
* @return the spec
*/
public CrossOriginSpec method(RequestMethod... method) {
this.crossOrigin.setMethod(method);
return this;
}
/**
* Whether the browser should include any cookies associated with the
* domain of the request being annotated.
* <p>Set to {@code "false"} if such cookies should not included.
* @param allowCredentials the {@code boolean} flag to include
* {@code Access-Control-Allow-Credentials=true} in pre-flight response or not
* @return the spec
*/
public CrossOriginSpec allowCredentials(Boolean allowCredentials) {
this.crossOrigin.setAllowCredentials(allowCredentials);
return this;
}
/**
* The maximum age (in seconds) of the cache duration for pre-flight responses.
* <p>This property controls the value of the {@code Access-Control-Max-Age}
* header in the pre-flight response.
* @param maxAge the maximum age (in seconds) of the cache duration for pre-flight responses.
* @return the spec
*/
public CrossOriginSpec maxAge(long maxAge) {
this.crossOrigin.setMaxAge(maxAge);
return this;
}
}
}

View File

@@ -0,0 +1,290 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import java.net.URI;
import java.util.function.Function;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.http.inbound.HttpRequestHandlingController;
import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
/**
* The HTTP components Factory.
*
* @author Artem Bilan
*
* @since 5.0
*/
public final class Http {
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter based on provided {@link URI}.
* @param uri the {@link URI} to send requests.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri) {
return outboundChannelAdapter(uri, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter based on provided {@code uri}.
* @param uri the {@code uri} to send requests.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(String uri) {
return outboundChannelAdapter(uri, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter based on provided {@code Function}
* to evaluate target {@code uri} against request message.
* @param uriFunction the {@code Function} to evaluate {@code uri} at runtime.
* @param <P> the expected payload type.
* @return the HttpMessageHandlerSpec instance
*/
public static <P> HttpMessageHandlerSpec outboundChannelAdapter(Function<Message<P>, ?> uriFunction) {
return outboundChannelAdapter(new FunctionExpression<>(uriFunction));
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter based on provided SpEL {@link Expression}
* to evaluate target {@code uri} against request message.
* @param uriExpression the SpEL {@link Expression} to evaluate {@code uri} at runtime.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(Expression uriExpression) {
return outboundChannelAdapter(uriExpression, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter
* based on provided {@link URI} and {@link RestTemplate}.
* @param uri the {@link URI} to send requests.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uri, restTemplate).expectReply(false);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter
* based on provided {@code uri} and {@link RestTemplate}.
* @param uri the {@code uri} to send requests.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uri, restTemplate).expectReply(false);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter
* based on provided {@code Function} to evaluate target {@code uri} against request message
* and {@link RestTemplate} for HTTP exchanges.
* @param uriFunction the {@code Function} to evaluate {@code uri} at runtime.
* @param restTemplate {@link RestTemplate} to use.
* @param <P> the expected payload type.
* @return the HttpMessageHandlerSpec instance
*/
public static <P> HttpMessageHandlerSpec outboundChannelAdapter(Function<Message<P>, ?> uriFunction,
RestTemplate restTemplate) {
return outboundChannelAdapter(new FunctionExpression<>(uriFunction), restTemplate);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for one-way adapter
* based on provided SpEL {@link Expression} to evaluate target {@code uri}
* against request message and {@link RestTemplate} for HTTP exchanges.
* @param uriExpression the SpEL {@link Expression} to evaluate {@code uri} at runtime.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundChannelAdapter(Expression uriExpression, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uriExpression, restTemplate).expectReply(false);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway based on provided {@link URI}.
* @param uri the {@link URI} to send requests.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(URI uri) {
return outboundGateway(uri, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway based on provided {@code uri}.
* @param uri the {@code uri} to send requests.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(String uri) {
return outboundGateway(uri, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided {@code Function} to evaluate target {@code uri} against request message.
* @param uriFunction the {@code Function} to evaluate {@code uri} at runtime.
* @param <P> the expected payload type.
* @return the HttpMessageHandlerSpec instance
*/
public static <P> HttpMessageHandlerSpec outboundGateway(Function<Message<P>, ?> uriFunction) {
return outboundGateway(new FunctionExpression<>(uriFunction));
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided SpEL {@link Expression} to evaluate target {@code uri} against request message.
* @param uriExpression the SpEL {@link Expression} to evaluate {@code uri} at runtime.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(Expression uriExpression) {
return outboundGateway(uriExpression, null);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided {@link URI} and {@link RestTemplate}.
* @param uri the {@link URI} to send requests.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(URI uri, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uri, restTemplate);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided {@code uri} and {@link RestTemplate}.
* @param uri the {@code uri} to send requests.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(String uri, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uri, restTemplate);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided {@code Function} to evaluate target {@code uri} against request message
* and {@link RestTemplate} for HTTP exchanges.
* @param uriFunction the {@code Function} to evaluate {@code uri} at runtime.
* @param restTemplate {@link RestTemplate} to use.
* @param <P> the expected payload type.
* @return the HttpMessageHandlerSpec instance
*/
public static <P> HttpMessageHandlerSpec outboundGateway(Function<Message<P>, ?> uriFunction,
RestTemplate restTemplate) {
return outboundGateway(new FunctionExpression<>(uriFunction), restTemplate);
}
/**
* Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway
* based on provided SpEL {@link Expression} to evaluate target {@code uri}
* against request message and {@link RestTemplate} for HTTP exchanges.
* @param uriExpression the SpEL {@link Expression} to evaluate {@code uri} at runtime.
* @param restTemplate {@link RestTemplate} to use.
* @return the HttpMessageHandlerSpec instance
*/
public static HttpMessageHandlerSpec outboundGateway(Expression uriExpression, RestTemplate restTemplate) {
return new HttpMessageHandlerSpec(uriExpression, restTemplate);
}
/**
* Create an {@link HttpControllerEndpointSpec} builder for one-way adapter
* based on the provided MVC {@code viewName} and {@code path} array for mapping.
* @param viewName the MVC view name to build in the end of request.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpControllerEndpointSpec instance
*/
public static HttpControllerEndpointSpec inboundControllerAdapter(String viewName, String... path) {
Assert.isTrue(StringUtils.hasText(viewName), "View name must not be empty");
return inboundControllerAdapter(new LiteralExpression(viewName), path);
}
/**
* Create an {@link HttpControllerEndpointSpec} builder for one-way adapter
* based on the provided SpEL expression and {@code path} array for mapping.
* @param viewExpression the SpEL expression to evaluate MVC view name to build in the end of request.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpControllerEndpointSpec instance
*/
public static HttpControllerEndpointSpec inboundControllerAdapter(Expression viewExpression, String... path) {
HttpRequestHandlingController controller = new HttpRequestHandlingController(false);
controller.setViewExpression(viewExpression);
return new HttpControllerEndpointSpec(controller, path);
}
/**
* Create an {@link HttpControllerEndpointSpec} builder for request-reply gateway
* based on the provided MVC {@code viewName} and {@code path} array for mapping.
* @param viewName the MVC view name to build in the end of request.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpControllerEndpointSpec instance
*/
public static HttpControllerEndpointSpec inboundControllerGateway(String viewName, String... path) {
Assert.isTrue(StringUtils.hasText(viewName), "View name must not be empty");
return inboundControllerGateway(new LiteralExpression(viewName), path);
}
/**
* Create an {@link HttpControllerEndpointSpec} builder for request-reply gateway
* based on the provided SpEL expression and {@code path} array for mapping.
* @param viewExpression the SpEL expression to evaluate MVC view name to build in the end of request.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpControllerEndpointSpec instance
*/
public static HttpControllerEndpointSpec inboundControllerGateway(Expression viewExpression, String... path) {
HttpRequestHandlingController controller = new HttpRequestHandlingController();
controller.setViewExpression(viewExpression);
return new HttpControllerEndpointSpec(controller, path);
}
/**
* Create an {@link HttpRequestHandlerEndpointSpec} builder for one-way adapter
* based on the provided {@code path} array for mapping.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpRequestHandlerEndpointSpec instance
*/
public static HttpRequestHandlerEndpointSpec inboundChannelAdapter(String... path) {
HttpRequestHandlingMessagingGateway httpInboundChannelAdapter = new HttpRequestHandlingMessagingGateway(false);
return new HttpRequestHandlerEndpointSpec(httpInboundChannelAdapter, path);
}
/**
* Create an {@link HttpRequestHandlerEndpointSpec} builder for request-reply gateway
* based on the provided {@code path} array for mapping.
* @param path the path mapping URIs (e.g. "/myPath.do").
* @return the HttpRequestHandlerEndpointSpec instance
*/
public static HttpRequestHandlerEndpointSpec inboundGateway(String... path) {
return new HttpRequestHandlerEndpointSpec(new HttpRequestHandlingMessagingGateway(), path);
}
private Http() {
super();
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import org.springframework.integration.http.inbound.HttpRequestHandlingController;
/**
* The {@link BaseHttpInboundEndpointSpec} implementation for the {@link HttpRequestHandlingController}.
*
* @author Artem Bilan
*
* @since 5.0
*
* @see HttpRequestHandlingController
*/
public class HttpControllerEndpointSpec
extends BaseHttpInboundEndpointSpec<HttpControllerEndpointSpec, HttpRequestHandlingController> {
HttpControllerEndpointSpec(HttpRequestHandlingController controller, String... path) {
super(controller, path);
}
/**
* Specify the key to be used when adding the reply Message or payload to the core map
* (will be payload only unless the value
* of {@link HttpRequestHandlingController#setExtractReplyPayload(boolean)} is <code>false</code>).
* The default key is {@code reply}.
* @param replyKey The reply key.
* @return the spec
* @see HttpRequestHandlingController#setReplyKey(String)
*/
public HttpControllerEndpointSpec replyKey(String replyKey) {
this.target.setReplyKey(replyKey);
return this;
}
/**
* The key used to expose {@link org.springframework.validation.Errors} in the core,
* in the case that message handling fails.
* Defaults to {@code errors}.
* @param errorsKey The key value to set.
* @return the spec
* @see HttpRequestHandlingController#setErrorsKey(String)
*/
public HttpControllerEndpointSpec errorsKey(String errorsKey) {
this.target.setErrorsKey(errorsKey);
return this;
}
/**
* The error code to use to signal an error in the message handling.
* @param errorCode The error code to set.
* @return the spec
* @see HttpRequestHandlingController#setErrorCode(String)
*/
public HttpControllerEndpointSpec errorCode(String errorCode) {
this.target.setErrorCode(errorCode);
return this;
}
}

View File

@@ -0,0 +1,368 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.expression.ValueExpression;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.mapping.HeaderMapper;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
/**
* The {@link MessageHandlerSpec} implementation for the {@link HttpRequestExecutingMessageHandler}.
*
* @author Artem Bilan
*
* @since 5.0
*
* @see HttpRequestExecutingMessageHandler
*/
public class HttpMessageHandlerSpec
extends MessageHandlerSpec<HttpMessageHandlerSpec, HttpRequestExecutingMessageHandler>
implements ComponentsRegistration {
private final RestTemplate restTemplate;
private final Map<String, Expression> uriVariableExpressions = new HashMap<>();
private HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.outboundMapper();
private boolean headerMapperExplicitlySet;
HttpMessageHandlerSpec(URI uri, RestTemplate restTemplate) {
this(new ValueExpression<>(uri), restTemplate);
}
HttpMessageHandlerSpec(String uri, RestTemplate restTemplate) {
this(new LiteralExpression(uri), restTemplate);
}
HttpMessageHandlerSpec(Expression uriExpression, RestTemplate restTemplate) {
this.target = new HttpRequestExecutingMessageHandler(uriExpression, restTemplate);
this.target.setUriVariableExpressions(this.uriVariableExpressions);
this.target.setHeaderMapper(this.headerMapper);
this.restTemplate = restTemplate;
}
HttpMessageHandlerSpec expectReply(boolean expectReply) {
this.target.setExpectReply(expectReply);
return this;
}
/**
* Specify whether the real URI should be encoded after <code>uriVariables</code>
* expanding and before send request via {@link RestTemplate}. The default value is <code>true</code>.
* @param encodeUri true if the URI should be encoded.
* @return the spec
*/
public HttpMessageHandlerSpec encodeUri(boolean encodeUri) {
this.target.setEncodeUri(encodeUri);
return this;
}
/**
* Specify the SpEL {@link Expression} to determine {@link HttpMethod} at runtime.
* @param httpMethodExpression The method expression.
* @return the spec
*/
public HttpMessageHandlerSpec httpMethodExpression(Expression httpMethodExpression) {
this.target.setHttpMethodExpression(httpMethodExpression);
return this;
}
/**
* Specify a {@link Function} to determine {@link HttpMethod} at runtime.
* @param httpMethodFunction The HTTP method {@link Function}.
* @param <P> the payload type.
* @return the spec
*/
public <P> HttpMessageHandlerSpec httpMethodFunction(Function<Message<P>, ?> httpMethodFunction) {
return httpMethodExpression(new FunctionExpression<>(httpMethodFunction));
}
/**
* Specify the {@link HttpMethod} for requests.
* The default method is {@code POST}.
* @param httpMethod the {@link HttpMethod} to use.
* @return the spec
*/
public HttpMessageHandlerSpec httpMethod(HttpMethod httpMethod) {
this.target.setHttpMethod(httpMethod);
return this;
}
/**
* Specify whether the outbound message's payload should be extracted
* when preparing the request body.
* Otherwise the Message instance itself is serialized.
* The default value is {@code true}.
* @param extractPayload true if the payload should be extracted.
* @return the spec
*/
public HttpMessageHandlerSpec extractPayload(boolean extractPayload) {
this.target.setExtractPayload(extractPayload);
return this;
}
/**
* Specify the charset name to use for converting String-typed payloads to bytes.
* The default is {@code UTF-8}.
* @param charset The charset.
* @return the spec
*/
public HttpMessageHandlerSpec charset(String charset) {
this.target.setCharset(charset);
return this;
}
/**
* Specify the expected response type for the REST request.
* @param expectedResponseType The expected type.
* @return the spec
*/
public HttpMessageHandlerSpec expectedResponseType(Class<?> expectedResponseType) {
this.target.setExpectedResponseType(expectedResponseType);
return this;
}
/**
* Specify a {@link ParameterizedTypeReference} for the expected response type for the REST request.
* @param expectedResponseType The {@link ParameterizedTypeReference} for expected type.
* @return the spec
*/
public HttpMessageHandlerSpec expectedResponseType(ParameterizedTypeReference<?> expectedResponseType) {
return expectedResponseTypeExpression(new ValueExpression<ParameterizedTypeReference<?>>(expectedResponseType));
}
/**
* Specify a SpEL {@link Expression} to determine the type for the expected response
* The returned value of the expression could be an instance of {@link Class} or
* {@link String} representing a fully qualified class name.
* @param expectedResponseTypeExpression The expected response type expression.
* @return the spec
*/
public HttpMessageHandlerSpec expectedResponseTypeExpression(Expression expectedResponseTypeExpression) {
this.target.setExpectedResponseTypeExpression(expectedResponseTypeExpression);
return this;
}
/**
* Specify a {@link Function} to determine the type for the expected response
* The returned value of the expression could be an instance of {@link Class} or
* {@link String} representing a fully qualified class name.
* @param expectedResponseTypeFunction The expected response type {@link Function}.
* @param <P> the payload type.
* @return the spec
*/
public <P> HttpMessageHandlerSpec expectedResponseTypeFunction(
Function<Message<P>, ?> expectedResponseTypeFunction) {
return expectedResponseTypeExpression(new FunctionExpression<>(expectedResponseTypeFunction));
}
/**
* Set the {@link ResponseErrorHandler} for the underlying {@link RestTemplate}.
* @param errorHandler The error handler.
* @return the spec
*/
public HttpMessageHandlerSpec errorHandler(ResponseErrorHandler errorHandler) {
Assert.isNull(this.restTemplate,
"the 'errorHandler' must be specified on the provided 'restTemplate': " + this.restTemplate);
this.target.setErrorHandler(errorHandler);
return this;
}
/**
* Set a list of {@link HttpMessageConverter}s to be used by the underlying {@link RestTemplate}.
* Converters configured via this method will override the default converters.
* @param messageConverters The message converters.
* @return the spec
*/
public HttpMessageHandlerSpec messageConverters(HttpMessageConverter<?>... messageConverters) {
Assert.isNull(this.restTemplate,
"the 'messageConverters' must be specified on the provided 'restTemplate': " + this.restTemplate);
this.target.setMessageConverters(Arrays.asList(messageConverters));
return this;
}
/**
* Set the {@link ClientHttpRequestFactory} for the underlying {@link RestTemplate}.
* @param requestFactory The request factory.
* @return the spec
*/
public HttpMessageHandlerSpec requestFactory(ClientHttpRequestFactory requestFactory) {
Assert.isNull(this.restTemplate,
"the 'requestFactory' must be specified on the provided 'restTemplate': " + this.restTemplate);
this.target.setRequestFactory(requestFactory);
return this;
}
/**
* Set the {@link HeaderMapper} to use when mapping between HTTP headers and {@code MessageHeaders}.
* @param headerMapper The header mapper.
* @return the spec
*/
public HttpMessageHandlerSpec headerMapper(HeaderMapper<HttpHeaders> headerMapper) {
this.headerMapper = headerMapper;
this.target.setHeaderMapper(this.headerMapper);
this.headerMapperExplicitlySet = true;
return this;
}
/**
* Provide the pattern array for request headers to map.
* @param patterns the patterns for request headers to map.
* @return the spec
* @see DefaultHttpHeaderMapper#setOutboundHeaderNames(String[])
*/
public HttpMessageHandlerSpec mappedRequestHeaders(String... patterns) {
Assert.isTrue(!this.headerMapperExplicitlySet,
"The 'mappedRequestHeaders' must be specified on the provided 'headerMapper': " + this.headerMapper);
((DefaultHttpHeaderMapper) this.headerMapper).setOutboundHeaderNames(patterns);
return this;
}
/**
* Provide the pattern array for response headers to map.
* @param patterns the patterns for response headers to map.
* @return the current Spec.
* @see DefaultHttpHeaderMapper#setInboundHeaderNames(String[])
*/
public HttpMessageHandlerSpec mappedResponseHeaders(String... patterns) {
Assert.isTrue(!this.headerMapperExplicitlySet,
"The 'mappedResponseHeaders' must be specified on the provided 'headerMapper': " + this.headerMapper);
((DefaultHttpHeaderMapper) this.headerMapper).setInboundHeaderNames(patterns);
return this;
}
/**
* Set the Map of URI variable expressions to evaluate against the outbound message
* when replacing the variable placeholders in a URI template.
* @param uriVariableExpressions The URI variable expressions.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariableExpressions(Map)
*/
public HttpMessageHandlerSpec uriVariableExpressions(Map<String, Expression> uriVariableExpressions) {
this.uriVariableExpressions.clear();
this.uriVariableExpressions.putAll(uriVariableExpressions);
return this;
}
/**
* Specify a SpEL expression to evaluate a value for the uri template variable.
* @param variable the uri template variable.
* @param value the expression to evaluate value for te uri template variable.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariableExpressions(Map)
*/
public HttpMessageHandlerSpec uriVariable(String variable, Expression value) {
this.uriVariableExpressions.put(variable, value);
return this;
}
/**
* Specify a value for the uri template variable.
* @param variable the uri template variable.
* @param value the expression to evaluate value for te uri template variable.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariableExpressions(Map)
*/
public HttpMessageHandlerSpec uriVariable(String variable, String value) {
return uriVariable(variable, PARSER.parseExpression(value));
}
/**
* Specify a {@link Function} to evaluate a value for the uri template variable.
* @param variable the uri template variable.
* @param valueFunction the {@link Function} to evaluate a value for the uri template variable.
* @param <P> the payload type.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariableExpressions(Map)
*/
public <P> HttpMessageHandlerSpec uriVariable(String variable, Function<Message<P>, ?> valueFunction) {
return uriVariable(variable, new FunctionExpression<>(valueFunction));
}
/**
* Specify a SpEL expression to evaluate a {@link Map} of URI variables at runtime against request message.
* @param uriVariablesExpression to use.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariablesExpression(Expression)
*/
public HttpMessageHandlerSpec uriVariablesExpression(String uriVariablesExpression) {
return uriVariablesExpression(PARSER.parseExpression(uriVariablesExpression));
}
/**
* Specify a SpEL expression to evaluate a {@link Map} of URI variables at runtime against request message.
* @param uriVariablesExpression to use.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariablesExpression(Expression)
*/
public HttpMessageHandlerSpec uriVariablesExpression(Expression uriVariablesExpression) {
this.target.setUriVariablesExpression(uriVariablesExpression);
return this;
}
/**
* Specify a {@link Function} to evaluate a {@link Map} of URI variables at runtime against request message.
* @param uriVariablesFunction the {@link Function} to use.
* @param <P> the payload type.
* @return the current Spec.
* @see HttpRequestExecutingMessageHandler#setUriVariablesExpression(Expression)
*/
public <P> HttpMessageHandlerSpec uriVariablesFunction(Function<Message<P>, Map<String, ?>> uriVariablesFunction) {
return uriVariablesExpression(new FunctionExpression<>(uriVariablesFunction));
}
/**
* Set to {@code true} if you wish {@code Set-Cookie} header in response to be
* transferred as {@code Cookie} header in subsequent interaction for a message.
* @param transferCookies the transferCookies to set.
* @return the current Spec.
*/
public HttpMessageHandlerSpec transferCookies(boolean transferCookies) {
this.target.setTransferCookies(transferCookies);
return this;
}
@Override
public Collection<Object> getComponentsToRegister() {
return Collections.singletonList(this.headerMapper);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway;
/**
* The {@link BaseHttpInboundEndpointSpec} implementation for the {@link HttpRequestHandlingMessagingGateway}.
*
* @author Artem Bilan
*
* @since 5.0
*
* @see HttpRequestHandlingMessagingGateway
*/
public class HttpRequestHandlerEndpointSpec
extends BaseHttpInboundEndpointSpec<HttpRequestHandlerEndpointSpec, HttpRequestHandlingMessagingGateway> {
HttpRequestHandlerEndpointSpec(HttpRequestHandlingMessagingGateway endpoint, String... path) {
super(endpoint, path);
}
/**
* Flag to determine if conversion and writing out of message handling exceptions should be attempted.
* @param convertExceptions the flag to set
* @return the spec
*/
public HttpRequestHandlerEndpointSpec convertExceptions(boolean convertExceptions) {
this.target.setConvertExceptions(convertExceptions);
return this;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Provides HTTP Components support for Spring Integration Java DSL.
*/
package org.springframework.integration.http.dsl;

View File

@@ -347,6 +347,16 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
public void setMultipartResolver(MultipartResolver multipartResolver) {
this.multipartResolver = multipartResolver;
}
/**
* Specify the {@link Expression} to resolve a status code for Response to override
* the default '200 OK' or '500 Internal Server Error' for a timeout.
* @param statusCodeExpression The status code Expression.
* @since 5.0
* @see #setStatusCodeExpression(Expression)
*/
public void setStatusCodeExpressionString(String statusCodeExpression) {
setStatusCodeExpression(EXPRESSION_PARSER.parseExpression(statusCodeExpression));
}
/**
* Specify the {@link Expression} to resolve a status code for Response to override

View File

@@ -83,7 +83,7 @@ import org.springframework.web.util.UriComponentsBuilder;
*/
public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMessageHandler {
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final Map<String, Expression> uriVariableExpressions = new HashMap<>();
private final RestTemplate restTemplate;
@@ -93,7 +93,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
private volatile boolean encodeUri = true;
private volatile Expression httpMethodExpression = new ValueExpression<HttpMethod>(HttpMethod.POST);
private volatile Expression httpMethodExpression = new ValueExpression<>(HttpMethod.POST);
private volatile boolean expectReply = true;
@@ -180,8 +180,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
/**
* Specify the SpEL {@link Expression} to determine {@link HttpMethod} dynamically
*
* Specify the SpEL {@link Expression} to determine {@link HttpMethod} at runtime.
* @param httpMethodExpression The method expression.
*/
public void setHttpMethodExpression(Expression httpMethodExpression) {
@@ -190,8 +189,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
/**
* Specify the {@link HttpMethod} for requests. The default method will be POST.
*
* Specify the {@link HttpMethod} for requests.
* The default method is {@code POST}.
* @param httpMethod The method.
*/
public void setHttpMethod(HttpMethod httpMethod) {
@@ -201,9 +200,9 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
/**
* Specify whether the outbound message's payload should be extracted
* when preparing the request body. Otherwise the Message instance itself
* will be serialized. The default value is <code>true</code>.
*
* when preparing the request body.
* Otherwise the Message instance itself is serialized.
* The default value is {@code true}.
* @param extractPayload true if the payload should be extracted.
*/
public void setExtractPayload(boolean extractPayload) {
@@ -212,9 +211,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
/**
* Specify the charset name to use for converting String-typed payloads to
* bytes. The default is 'UTF-8'.
*
* Specify the charset name to use for converting String-typed payloads to bytes.
* The default is {@code UTF-8}.
* @param charset The charset.
*/
public void setCharset(String charset) {
@@ -251,7 +249,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
/**
* Specify the {@link Expression} to determine the type for the expected response
* The returned value of the expression could be an instance of {@link Class} or
* {@link String} representing a fully qualified class name
* {@link String} representing a fully qualified class name.
* @param expectedResponseTypeExpression The expected response type expression.
* Also see {@link #setExpectedResponseType}
*/
@@ -283,9 +281,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
/**
* @param headerMapper The header mapper.
*
* Set the {@link HeaderMapper} to use when mapping between HTTP headers and MessageHeaders.
* @param headerMapper The header mapper.
*/
public void setHeaderMapper(HeaderMapper<HttpHeaders> headerMapper) {
Assert.notNull(headerMapper, "headerMapper must not be null");

View File

@@ -74,6 +74,7 @@ import org.springframework.web.servlet.HandlerMapping;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
public class HttpInboundChannelAdapterParserTests extends AbstractHttpInboundTests {
@Autowired

View File

@@ -74,6 +74,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
public class HttpInboundGatewayParserTests {
@Autowired

View File

@@ -52,6 +52,7 @@ import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
@@ -67,6 +68,7 @@ import org.springframework.web.client.RestTemplate;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
public class HttpOutboundChannelAdapterParserTests {
@Autowired @Qualifier("minimalConfig")

View File

@@ -52,6 +52,7 @@ import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
@@ -65,6 +66,7 @@ import org.springframework.web.client.ResponseErrorHandler;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
public class HttpOutboundGatewayParserTests {
@Autowired @Qualifier("minimalConfig")

View File

@@ -46,6 +46,7 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.client.MockRestServiceServer;
@@ -62,6 +63,7 @@ import org.springframework.web.client.RestTemplate;
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class OutboundResponseTypeTests {
@Autowired

View File

@@ -0,0 +1,178 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.http.dsl;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
import org.springframework.integration.security.channel.SecuredChannel;
import org.springframework.messaging.MessageChannel;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Artem Bilan
*
* @since 5.0
*/
@RunWith(SpringRunner.class)
@WebAppConfiguration
@DirtiesContext
public class HttpDslTests {
@Autowired
private WebApplicationContext wac;
@Autowired
private HttpRequestExecutingMessageHandler serviceInternalGatewayHandler;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc =
MockMvcBuilders.webAppContextSetup(this.wac)
.apply(springSecurity())
.build();
}
@Test
public void testHttpProxyFlow() throws Exception {
RestTemplate mockMvcRestTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(this.mockMvc));
new DirectFieldAccessor(this.serviceInternalGatewayHandler)
.setPropertyValue("restTemplate", mockMvcRestTemplate);
this.mockMvc.perform(
get("/service")
.with(httpBasic("guest", "guest"))
.param("name", "foo"))
.andExpect(
content()
.string("FOO"));
}
@Configuration
@EnableWebMvc
@EnableWebSecurity
@EnableIntegration
public static class ContextConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("guest")
.password("guest")
.roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic()
.and()
.csrf().disable()
.anonymous().disable();
}
@Bean
@SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = "ROLE_ADMIN")
public MessageChannel transformSecuredChannel() {
return new DirectChannel();
}
@Bean
public IntegrationFlow httpInternalServiceFlow() {
return IntegrationFlows
.from(Http.inboundGateway("/service/internal")
.requestMapping(r -> r.params("name"))
.payloadExpression("#requestParams.name"))
.channel(transformSecuredChannel())
.<List<String>, String>transform(p -> p.get(0).toUpperCase())
.get();
}
@Bean
public IntegrationFlow httpProxyFlow() {
return IntegrationFlows
.from(Http.inboundGateway("/service")
.requestMapping(r -> r.params("name"))
.payloadFunction(httpEntity ->
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest()
.getQueryString()))
.handle(Http.outboundGateway(m -> "/service/internal?" + m.getPayload())
.expectedResponseType(String.class),
e -> e.id("serviceInternalGateway"))
.get();
}
@Bean
public AccessDecisionManager accessDecisionManager() {
return new AffirmativeBased(Collections.singletonList(new RoleVoter()));
}
@Bean
public ChannelSecurityInterceptor channelSecurityInterceptor(AccessDecisionManager accessDecisionManager)
throws Exception {
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor();
channelSecurityInterceptor.setAuthenticationManager(authenticationManager());
channelSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
return channelSecurityInterceptor;
}
}
}

View File

@@ -40,6 +40,7 @@ import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.MultiValueMap;
@@ -59,6 +60,7 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
//INT-2312
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext
public class Int2312RequestMappingIntegrationTests extends AbstractHttpInboundTests {
public static final String TEST_PATH = "/test/{value}";

View File

@@ -46,9 +46,9 @@ import org.springframework.integration.config.EnableIntegrationManagement;
import org.springframework.integration.http.config.EnableIntegrationGraphController;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@@ -66,10 +66,10 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
* @author Gary Russell
* @since 4.3
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@RunWith(SpringRunner.class)
@WebAppConfiguration
@TestPropertySource(properties = "spring.application.name:testApplication")
@DirtiesContext
public class IntegrationGraphControllerTests {
@Autowired

View File

@@ -46,6 +46,7 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -58,6 +59,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class CookieTests {
@Autowired