Refactored outbound HTTP support to include HttpRequest and HttpRequestExecutor (formerly HttpExchanger). Also refactored existing RequestMapper to InboundRequestMapper, and added OutboundRequestMapper.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Base class for {@link HttpRequestExecutor} implementations.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public abstract class AbstractHttpRequestExecutor implements HttpRequestExecutor {
|
||||
|
||||
protected static final String HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
|
||||
|
||||
protected static final String HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
||||
|
||||
protected static final String ENCODING_GZIP = "gzip";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private boolean acceptGzipEncoding = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to accept GZIP encoding, that is, whether to
|
||||
* send the HTTP "Accept-Encoding" header with "gzip" as value.
|
||||
* <p>Default is "true". Turn this flag off if you do not want
|
||||
* GZIP response compression even if enabled on the HTTP server.
|
||||
*/
|
||||
public void setAcceptGzipEncoding(boolean acceptGzipEncoding) {
|
||||
this.acceptGzipEncoding = acceptGzipEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to accept GZIP encoding, that is, whether to
|
||||
* send the HTTP "Accept-Encoding" header with "gzip" as its value.
|
||||
*/
|
||||
public boolean isAcceptGzipEncoding() {
|
||||
return this.acceptGzipEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a request to send its content to its target URL.
|
||||
* @param request the request to execute
|
||||
* @return the InputStream result
|
||||
* @throws IOException if thrown by I/O operations
|
||||
* @throws Exception in case of general errors
|
||||
*/
|
||||
public final InputStream executeRequest(HttpRequest request) throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
StringBuilder sb = new StringBuilder("Sending HTTP request to [" + request.getTargetUrl() + "]");
|
||||
Integer contentLength = request.getContentLength();
|
||||
if (contentLength != null) {
|
||||
sb.append(", with size " + contentLength);
|
||||
}
|
||||
logger.debug(sb.toString());
|
||||
}
|
||||
return doExecuteRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to execute the request.
|
||||
*/
|
||||
protected abstract InputStream doExecuteRequest(HttpRequest request) throws Exception;
|
||||
|
||||
}
|
||||
@@ -32,18 +32,18 @@ import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.servlet.handler.DispatcherServletWebRequest;
|
||||
|
||||
/**
|
||||
* RequestMapper implementation that binds the request parameter map to a
|
||||
* target instance. The target instance may be a non-singleton bean as
|
||||
* InboundRequestMapper implementation that binds the request parameter map to
|
||||
* a target instance. The target instance may be a non-singleton bean as
|
||||
* specified by the {@link #setTargetBeanName(String) 'targetBeanName'}
|
||||
* property. Otherwise, this transformer's target type must provide a
|
||||
* default no-arg constructor.
|
||||
* property. Otherwise, this mapper's target type must provide a default,
|
||||
* no-arg constructor.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class DataBindingRequestMapper implements RequestMapper, BeanFactoryAware, InitializingBean {
|
||||
public class DataBindingInboundRequestMapper implements InboundRequestMapper, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private final Class<?> targetType;
|
||||
private volatile Class<?> targetType = Object.class;
|
||||
|
||||
private volatile String targetBeanName;
|
||||
|
||||
@@ -54,12 +54,20 @@ public class DataBindingRequestMapper implements RequestMapper, BeanFactoryAware
|
||||
private volatile boolean validated;
|
||||
|
||||
|
||||
public DataBindingRequestMapper(Class<?> targetType) {
|
||||
public DataBindingInboundRequestMapper() {
|
||||
this.targetType = Object.class;
|
||||
}
|
||||
|
||||
public DataBindingInboundRequestMapper(Class<?> targetType) {
|
||||
Assert.notNull(targetType, "targetType must not be null");
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the name of a bean definition to use when creating the target
|
||||
* instance. The bean must <em>not</em> be a singleton, and it must be
|
||||
@@ -89,6 +97,10 @@ public class DataBindingRequestMapper implements RequestMapper, BeanFactoryAware
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() {
|
||||
if (this.targetBeanName == null && Object.class.equals(this.targetType)) {
|
||||
throw new IllegalArgumentException(
|
||||
"When no 'targetBeanName' is provided, the 'targetType' must be more specific than Object.");
|
||||
}
|
||||
this.validateTargetBeanIfNecessary();
|
||||
}
|
||||
|
||||
@@ -98,12 +110,16 @@ public class DataBindingRequestMapper implements RequestMapper, BeanFactoryAware
|
||||
if (this.beanFactory.isSingleton(this.targetBeanName)) {
|
||||
throw new IllegalArgumentException("binding target bean must not be a singleton");
|
||||
}
|
||||
Class<?> beanType = this.beanFactory.getType(this.targetBeanName);
|
||||
if (beanType != null) {
|
||||
Assert.isAssignable(this.targetType, beanType);
|
||||
}
|
||||
this.validated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Message<?> mapRequest(HttpServletRequest request) throws Exception {
|
||||
public Message<?> toMessage(HttpServletRequest request) throws Exception {
|
||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(getTarget());
|
||||
this.initBinder(binder, request);
|
||||
binder.bind(request);
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.integration.http;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.ArrayList;
|
||||
@@ -39,7 +38,7 @@ import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link RequestMapper} for inbound HttpServletRequests.
|
||||
* Default implementation of {@link InboundRequestMapper} for inbound HttpServletRequests.
|
||||
* The request will be mapped according to the following rules:
|
||||
* <ul>
|
||||
* <li>For a GET request, the parameter Map will be copied as the payload.
|
||||
@@ -64,16 +63,16 @@ import org.springframework.integration.message.MessageBuilder;
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class DefaultRequestMapper implements RequestMapper {
|
||||
public class DefaultInboundRequestMapper implements InboundRequestMapper {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
public Message<?> mapRequest(HttpServletRequest request) throws ServletException, IOException, ResponseStatusCodeException {
|
||||
public Message<?> toMessage(HttpServletRequest request) throws Exception {
|
||||
Message<?> message = null;
|
||||
String contentType = request.getContentType();
|
||||
if (request.getMethod().equals("GET")) {
|
||||
message = this.mapGetRequest(request);
|
||||
message = this.createMessageFromGetRequest(request);
|
||||
}
|
||||
else {
|
||||
Object payload = null;
|
||||
@@ -121,7 +120,7 @@ public class DefaultRequestMapper implements RequestMapper {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Message<?> mapGetRequest(HttpServletRequest request) {
|
||||
private Message<?> createMessageFromGetRequest(HttpServletRequest request) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("received GET request, using parameter map as payload");
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link OutboundRequestMapper}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class DefaultOutboundRequestMapper implements OutboundRequestMapper {
|
||||
|
||||
private final URL defaultUrl;
|
||||
|
||||
private volatile String charset = "UTF-8";
|
||||
|
||||
|
||||
public DefaultOutboundRequestMapper(URL defaultUrl) {
|
||||
Assert.notNull(defaultUrl, "default URL must not be null");
|
||||
this.defaultUrl = defaultUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify the charset name to use for converting String-typed payloads to
|
||||
* bytes. The default is 'UTF-8'.
|
||||
*/
|
||||
public void setCharset(String charset) {
|
||||
Assert.isTrue(Charset.isSupported(charset), "unsupported charset '" + charset + "'");
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
public HttpRequest fromMessage(Message<?> message) throws Exception {
|
||||
Assert.notNull(message, "message must not be null");
|
||||
Object payload = message.getPayload();
|
||||
Assert.notNull(payload, "payload must not be null");
|
||||
String contentType = null;
|
||||
byte[] bytes = null;
|
||||
if (payload instanceof byte[]) {
|
||||
bytes = (byte[]) payload;
|
||||
}
|
||||
else if (payload instanceof String) {
|
||||
bytes = ((String) payload).getBytes(this.charset);
|
||||
contentType = "text/plain";
|
||||
}
|
||||
else if (payload instanceof Serializable) {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
|
||||
objectStream.writeObject(payload);
|
||||
objectStream.flush();
|
||||
objectStream.close();
|
||||
bytes = byteStream.toByteArray();
|
||||
contentType = "application/x-java-serialized-object";
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"payload must be a byte array, String, or Serializable object");
|
||||
}
|
||||
URL url = this.resolveUrl(message);
|
||||
String method = "POST"; // TODO: support GET for Map payload
|
||||
return new DefaultHttpRequest(url, method, bytes, contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the request URL for the given Message. This implementation
|
||||
* simply returns the default URL as provided to the constructor.
|
||||
*/
|
||||
protected URL resolveUrl(Message<?> message) {
|
||||
return this.defaultUrl;
|
||||
}
|
||||
|
||||
|
||||
class DefaultHttpRequest implements HttpRequest {
|
||||
|
||||
private final URL targetUrl;
|
||||
|
||||
private final String requestMethod;
|
||||
|
||||
private final ByteArrayOutputStream requestBody;
|
||||
|
||||
private final String contentType;
|
||||
|
||||
|
||||
DefaultHttpRequest(URL targetUrl, String requestMethod, byte[] content, String contentType) throws IOException {
|
||||
Assert.notNull(targetUrl, "target url must not be null");
|
||||
this.targetUrl = targetUrl;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
baos.write(content);
|
||||
this.requestBody = baos;
|
||||
this.contentType = contentType;
|
||||
this.requestMethod = (requestMethod != null) ? requestMethod : "POST";
|
||||
}
|
||||
|
||||
public URL getTargetUrl() {
|
||||
return this.targetUrl;
|
||||
}
|
||||
|
||||
public String getRequestMethod() {
|
||||
return this.requestMethod;
|
||||
}
|
||||
|
||||
public ByteArrayOutputStream getBody() {
|
||||
return this.requestBody;
|
||||
}
|
||||
|
||||
public Integer getContentLength() {
|
||||
return this.requestBody.size();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.springframework.integration.http;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Strategy that will allow a http request response exchange a with a remote
|
||||
* server.
|
||||
*
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
*
|
||||
*/
|
||||
public interface HttpExchanger {
|
||||
|
||||
InputStream exchange(ByteArrayOutputStream requestBody) throws IOException;
|
||||
|
||||
void setContentType(String contentType);
|
||||
|
||||
}
|
||||
@@ -42,11 +42,11 @@ import org.springframework.web.servlet.View;
|
||||
* By default GET and POST requests are accepted, but the 'supportedMethods'
|
||||
* property may be set to include others or limit the options (e.g. POST only).
|
||||
* By default the request will be converted to a Message payload according to
|
||||
* the rules of the {@link DefaultRequestMapper}.
|
||||
* the rules of the {@link DefaultInboundRequestMapper}.
|
||||
* <p/>
|
||||
* To customize the mapping of the request to the Message payload, provide
|
||||
* a reference to a {@link RequestMapper} implementation to the
|
||||
* {@link #setRequestMapper(RequestMapper)} method.
|
||||
* a reference to an {@link InboundRequestMapper} implementation to the
|
||||
* {@link #setRequestMapper(InboundRequestMapper)} method.
|
||||
* <p/>
|
||||
* The value for {@link #expectReply} is <code>false</code> by default.
|
||||
* This means that as soon as the Message is created and passed to the
|
||||
@@ -87,7 +87,7 @@ public class HttpInboundEndpoint extends SimpleMessagingGateway implements HttpR
|
||||
|
||||
private volatile boolean expectReply;
|
||||
|
||||
private volatile RequestMapper requestMapper = new DefaultRequestMapper();
|
||||
private volatile InboundRequestMapper requestMapper = new DefaultInboundRequestMapper();
|
||||
|
||||
private volatile boolean extractReplyPayload = true;
|
||||
|
||||
@@ -120,11 +120,11 @@ public class HttpInboundEndpoint extends SimpleMessagingGateway implements HttpR
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a {@link RequestMapper} implementation to map from the
|
||||
* Specify a {@link InboundRequestMapper} implementation to map from the
|
||||
* inbound HTTP request to a Message. The default implementation
|
||||
* is {@link DefaultRequestMapper}.
|
||||
* is {@link DefaultInboundRequestMapper}.
|
||||
*/
|
||||
public void setRequestMapper(RequestMapper requestMapper) {
|
||||
public void setRequestMapper(InboundRequestMapper requestMapper) {
|
||||
Assert.notNull(requestMapper, "requestMapper must not be null");
|
||||
this.requestMapper = requestMapper;
|
||||
}
|
||||
@@ -178,7 +178,7 @@ public class HttpInboundEndpoint extends SimpleMessagingGateway implements HttpR
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Message<?> requestMessage = this.requestMapper.mapRequest(request);
|
||||
Message<?> requestMessage = this.requestMapper.toMessage(request);
|
||||
Object reply = this.handleRequestMessage(requestMessage);
|
||||
this.generateResponse(requestMessage, reply, request, response);
|
||||
}
|
||||
|
||||
@@ -17,112 +17,47 @@
|
||||
package org.springframework.integration.http;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.net.URL;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.handler.ReplyMessageHolder;
|
||||
import org.springframework.integration.message.MessageHandlingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* An outbound endpoint for executing an HTTP request and mapping the response
|
||||
* to a reply Message.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Iwein Fuld
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class HttpOutboundEndpoint extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
private volatile String charset = "UTF-8";
|
||||
private final OutboundRequestMapper requestMapper;
|
||||
|
||||
private volatile boolean acceptGzipEncoding = true;
|
||||
private volatile HttpRequestExecutor requestExecutor;
|
||||
|
||||
private volatile HttpExchanger exchanger;
|
||||
|
||||
public HttpOutboundEndpoint(String url) {
|
||||
this.exchanger = new SimpleHttpExchanger(url);
|
||||
public HttpOutboundEndpoint(URL url) {
|
||||
this.requestMapper = new DefaultOutboundRequestMapper(url);
|
||||
this.requestExecutor = new SimpleHttpRequestExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the charset name to use for converting String-typed payloads to
|
||||
* bytes. The default is 'UTF-8'.
|
||||
*/
|
||||
public void setCharset(String charset) {
|
||||
Assert.isTrue(Charset.isSupported(charset), "unsupported charset '"
|
||||
+ charset + "'");
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the content type to use for sending HTTP requests.
|
||||
* <p>
|
||||
* Default is "application/x-java-serialized-object".
|
||||
*/
|
||||
public void setContentType(String contentType) {
|
||||
Assert.notNull(contentType, "'contentType' must not be null");
|
||||
this.exchanger.setContentType(contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to accept GZIP encoding, that is, whether to send the HTTP
|
||||
* "Accept-Encoding" header with "gzip" as value.
|
||||
* <p>
|
||||
* Default is "true". Turn this flag off if you do not want GZIP response
|
||||
* compression even if enabled on the HTTP server.
|
||||
*/
|
||||
public void setAcceptGzipEncoding(boolean acceptGzipEncoding) {
|
||||
this.acceptGzipEncoding = acceptGzipEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to accept GZIP encoding, that is, whether to send the HTTP
|
||||
* "Accept-Encoding" header with "gzip" as value.
|
||||
*/
|
||||
public boolean isAcceptGzipEncoding() {
|
||||
return this.acceptGzipEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleRequestMessage(Message<?> requestMessage,
|
||||
ReplyMessageHolder replyMessageHolder) {
|
||||
Object payload = requestMessage.getPayload();
|
||||
byte[] bytes = null;
|
||||
protected void handleRequestMessage(Message<?> requestMessage, ReplyMessageHolder replyMessageHolder) {
|
||||
try {
|
||||
if (payload instanceof byte[]) {
|
||||
bytes = (byte[]) payload;
|
||||
}
|
||||
else if (payload instanceof String) {
|
||||
bytes = ((String) payload).getBytes(this.charset);
|
||||
}
|
||||
else if (payload instanceof Serializable) {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
ObjectOutputStream objectStream = new ObjectOutputStream(
|
||||
byteStream);
|
||||
objectStream.writeObject(payload);
|
||||
objectStream.flush();
|
||||
objectStream.close();
|
||||
bytes = byteStream.toByteArray();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"payload must be a byte array, String, or Serializable object");
|
||||
}
|
||||
ByteArrayOutputStream requestByteStream = new ByteArrayOutputStream();
|
||||
requestByteStream.write(bytes);
|
||||
|
||||
HttpRequest request = this.requestMapper.fromMessage(requestMessage);
|
||||
InputStream responseBody = this.requestExecutor.executeRequest(request);
|
||||
ByteArrayOutputStream responseByteStream = new ByteArrayOutputStream();
|
||||
InputStream responseBody = exchanger.exchange(requestByteStream);
|
||||
FileCopyUtils.copy(responseBody, responseByteStream);
|
||||
replyMessageHolder.set(responseByteStream.toByteArray());
|
||||
}
|
||||
catch (IOException e) {
|
||||
catch (Exception e) {
|
||||
throw new MessageHandlingException(requestMessage,
|
||||
"failed to send HTTP request", e);
|
||||
"failed to execute HTTP request", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Representation of an HTTP request to be executed by an implementation of
|
||||
* the {@link HttpRequestExecutor} strategy.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface HttpRequest {
|
||||
|
||||
/**
|
||||
* Return the target URL for this request.
|
||||
*/
|
||||
URL getTargetUrl();
|
||||
|
||||
/**
|
||||
* Return the request method ("GET", "POST", etc).
|
||||
*/
|
||||
String getRequestMethod();
|
||||
|
||||
/**
|
||||
* Return the content type for requests.
|
||||
*/
|
||||
String getContentType();
|
||||
|
||||
/**
|
||||
* Return the content length if known, else <code>null</code>.
|
||||
*/
|
||||
Integer getContentLength();
|
||||
|
||||
/**
|
||||
* Return the request body as a {@link ByteArrayOutputStream}.
|
||||
*/
|
||||
ByteArrayOutputStream getBody();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Strategy that will allow a http request response exchange with a remote
|
||||
* server.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface HttpRequestExecutor {
|
||||
|
||||
InputStream executeRequest(HttpRequest request) throws Exception;
|
||||
|
||||
}
|
||||
@@ -18,16 +18,15 @@ package org.springframework.integration.http;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.InboundMessageMapper;
|
||||
|
||||
/**
|
||||
* Strategy interface for mapping from an inbound {@link HttpServletRequest}
|
||||
* to a Message.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface RequestMapper {
|
||||
|
||||
Message<?> mapRequest(HttpServletRequest request) throws Exception;
|
||||
public interface InboundRequestMapper extends InboundMessageMapper<HttpServletRequest> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import org.springframework.integration.message.OutboundMessageMapper;
|
||||
|
||||
/**
|
||||
* Strategy for mapping to an {@link HttpRequest} from a message.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public interface OutboundRequestMapper extends OutboundMessageMapper<HttpRequest> {
|
||||
|
||||
}
|
||||
@@ -18,9 +18,10 @@ package org.springframework.integration.http;
|
||||
|
||||
/**
|
||||
* Exception that provides a response status code. This can be used by
|
||||
* {@link RequestMapper} implementations to indicate an error.
|
||||
* {@link InboundRequestMapper} implementations to indicate an error.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ResponseStatusCodeException extends Exception {
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
package org.springframework.integration.http;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class SimpleHttpExchanger implements HttpExchanger {
|
||||
|
||||
/**
|
||||
* Default content type: "application/x-java-serialized-object"
|
||||
*/
|
||||
public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object";
|
||||
|
||||
protected static final String HTTP_METHOD_POST = "POST";
|
||||
|
||||
protected static final String HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
|
||||
|
||||
protected static final String HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
protected static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
||||
|
||||
protected static final String ENCODING_GZIP = "gzip";
|
||||
|
||||
private volatile String contentType = CONTENT_TYPE_SERIALIZED_OBJECT;
|
||||
|
||||
private final URL url;
|
||||
|
||||
private volatile boolean acceptGzipEncoding = true;
|
||||
|
||||
public SimpleHttpExchanger(String url) {
|
||||
Assert.notNull(url, "url must not be null");
|
||||
try {
|
||||
this.url = new URL(url);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the content type to use for sending HTTP requests.
|
||||
* <p>
|
||||
* Default is "application/x-java-serialized-object".
|
||||
*/
|
||||
public void setContentType(String contentType) {
|
||||
Assert.notNull(contentType, "'contentType' must not be null");
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content type used for sending HTTP requests.
|
||||
*/
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to accept GZIP encoding, that is, whether to send the HTTP
|
||||
* "Accept-Encoding" header with "gzip" as value.
|
||||
* <p>
|
||||
* Default is "true". Turn this flag off if you do not want GZIP response
|
||||
* compression even if enabled on the HTTP server.
|
||||
*/
|
||||
public void setAcceptGzipEncoding(boolean acceptGzipEncoding) {
|
||||
this.acceptGzipEncoding = acceptGzipEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to accept GZIP encoding, that is, whether to send the HTTP
|
||||
* "Accept-Encoding" header with "gzip" as value.
|
||||
*/
|
||||
public boolean isAcceptGzipEncoding() {
|
||||
return this.acceptGzipEncoding;
|
||||
}
|
||||
|
||||
public InputStream exchange(ByteArrayOutputStream requestBody) throws IOException {
|
||||
HttpURLConnection connection = this.openConnection();
|
||||
this.prepareConnection(connection, requestBody.size());
|
||||
this.writeRequestBody(connection, requestBody);
|
||||
this.validateResponse(connection);
|
||||
return this.readResponseBody(connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an HttpURLConnection for this gateway's URL.
|
||||
* @return the HttpURLConnection for the given request
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @see java.net.URL#openConnection()
|
||||
*/
|
||||
private HttpURLConnection openConnection() throws IOException {
|
||||
URLConnection con = this.url.openConnection();
|
||||
if (!(con instanceof HttpURLConnection)) {
|
||||
throw new IOException("Service URL [" + this.url
|
||||
+ "] is not an HTTP URL");
|
||||
}
|
||||
return (HttpURLConnection) con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given HTTP connection.
|
||||
* <p>
|
||||
* This implementation specifies POST as method,
|
||||
* "application/x-java-serialized-object" as "Content-Type" header, and the
|
||||
* given content length as "Content-Length" header.
|
||||
* @param con the HTTP connection to prepare
|
||||
* @param contentLength the length of the content to send
|
||||
* @throws IOException if thrown by HttpURLConnection methods
|
||||
* @see java.net.HttpURLConnection#setRequestMethod
|
||||
* @see java.net.HttpURLConnection#setRequestProperty
|
||||
*/
|
||||
private void prepareConnection(HttpURLConnection con, int contentLength)
|
||||
throws IOException {
|
||||
con.setDoOutput(true);
|
||||
con.setRequestMethod(HTTP_METHOD_POST);
|
||||
con.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType());
|
||||
con.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer
|
||||
.toString(contentLength));
|
||||
LocaleContext locale = LocaleContextHolder.getLocaleContext();
|
||||
if (locale != null) {
|
||||
con.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils
|
||||
.toLanguageTag(locale.getLocale()));
|
||||
}
|
||||
if (isAcceptGzipEncoding()) {
|
||||
con.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeRequestBody(HttpURLConnection con,
|
||||
ByteArrayOutputStream baos) throws IOException {
|
||||
baos.writeTo(con.getOutputStream());
|
||||
}
|
||||
|
||||
private void validateResponse(HttpURLConnection con) throws IOException {
|
||||
if (con.getResponseCode() >= 300) {
|
||||
throw new IOException(
|
||||
"Did not receive successful HTTP response: status code = "
|
||||
+ con.getResponseCode() + ", status message = ["
|
||||
+ con.getResponseMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the response body from the given executed remote invocation
|
||||
* request.
|
||||
* <p>
|
||||
* This implementation simply reads the serialized invocation from the
|
||||
* HttpURLConnection's InputStream. If the response is recognized as GZIP
|
||||
* response, the InputStream will get wrapped in a GZIPInputStream.
|
||||
* @param config the HTTP invoker configuration that specifies the target
|
||||
* service
|
||||
* @param con the HttpURLConnection to read the response body from
|
||||
* @return an InputStream for the response body
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @see #isGzipResponse
|
||||
* @see java.util.zip.GZIPInputStream
|
||||
* @see java.net.HttpURLConnection#getInputStream()
|
||||
* @see java.net.HttpURLConnection#getHeaderField(int)
|
||||
* @see java.net.HttpURLConnection#getHeaderFieldKey(int)
|
||||
*/
|
||||
private InputStream readResponseBody(HttpURLConnection con)
|
||||
throws IOException {
|
||||
if (isGzipResponse(con)) {
|
||||
// GZIP response found - need to unzip.
|
||||
return new GZIPInputStream(con.getInputStream());
|
||||
}
|
||||
else {
|
||||
// Plain response found.
|
||||
return con.getInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given response is a GZIP response.
|
||||
* <p>
|
||||
* This implementation checks whether the HTTP "Content-Encoding" header
|
||||
* contains "gzip" (in any casing).
|
||||
* @param con the HttpURLConnection to check
|
||||
*/
|
||||
private boolean isGzipResponse(HttpURLConnection con) {
|
||||
String encodingHeader = con
|
||||
.getHeaderField(HTTP_HEADER_CONTENT_ENCODING);
|
||||
return (encodingHeader != null && encodingHeader.toLowerCase().indexOf(
|
||||
ENCODING_GZIP) != -1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link HttpRequestExecutor} that uses {@link HttpURLConnection}
|
||||
* directly. This version has limited functionality but no additional dependencies.
|
||||
* For more features, see {@link CommonsHttpRequestExecutor}. (TODO)
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class SimpleHttpRequestExecutor extends AbstractHttpRequestExecutor {
|
||||
|
||||
@Override
|
||||
protected InputStream doExecuteRequest(HttpRequest request) throws Exception {
|
||||
HttpURLConnection connection = this.openConnection(request.getTargetUrl());
|
||||
this.prepareConnection(connection, request);
|
||||
this.writeRequestBody(connection, request.getBody());
|
||||
this.validateResponse(connection);
|
||||
return this.readResponseBody(connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an HttpURLConnection for the given request URL.
|
||||
* @return the HttpURLConnection for the given request
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @see java.net.URL#openConnection()
|
||||
*/
|
||||
private HttpURLConnection openConnection(URL url) throws IOException {
|
||||
URLConnection con = url.openConnection();
|
||||
if (!(con instanceof HttpURLConnection)) {
|
||||
throw new IOException("target URL [" + url + "] is not an HTTP URL");
|
||||
}
|
||||
return (HttpURLConnection) con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given HTTP connection.
|
||||
* <p>
|
||||
* The request method (e.g. "POST), "Content-Type" header, and content
|
||||
* length will be determined from the provided {@link HttpRequest}.
|
||||
* @param request HttpRequest for which the connection should be prepared
|
||||
* @throws IOException if thrown by HttpURLConnection methods
|
||||
* @see java.net.HttpURLConnection#setRequestMethod
|
||||
* @see java.net.HttpURLConnection#setRequestProperty
|
||||
*/
|
||||
private void prepareConnection(HttpURLConnection con, HttpRequest request) throws IOException {
|
||||
con.setDoOutput(true);
|
||||
con.setRequestMethod(request.getRequestMethod());
|
||||
String contentType = request.getContentType();
|
||||
if (contentType != null) {
|
||||
con.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, contentType);
|
||||
}
|
||||
Integer contentLength = request.getContentLength();
|
||||
if (contentLength != null) {
|
||||
con.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, contentLength.toString());
|
||||
}
|
||||
LocaleContext locale = LocaleContextHolder.getLocaleContext();
|
||||
if (locale != null) {
|
||||
con.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE,
|
||||
StringUtils.toLanguageTag(locale.getLocale()));
|
||||
}
|
||||
if (isAcceptGzipEncoding()) {
|
||||
con.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeRequestBody(HttpURLConnection con, ByteArrayOutputStream baos) throws IOException {
|
||||
baos.writeTo(con.getOutputStream());
|
||||
}
|
||||
|
||||
private void validateResponse(HttpURLConnection con) throws IOException {
|
||||
if (con.getResponseCode() >= 300) {
|
||||
throw new IOException(
|
||||
"Did not receive successful HTTP response: status code = "
|
||||
+ con.getResponseCode() + ", status message = ["
|
||||
+ con.getResponseMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the response body from the connection after the request has
|
||||
* been successfully executed.
|
||||
* <p>
|
||||
* This implementation simply reads the HttpURLConnection's InputStream.
|
||||
* If the response is recognized as GZIP response, the InputStream will be
|
||||
* wrapped in a GZIPInputStream.
|
||||
* @param con the HttpURLConnection to read the response body from
|
||||
* @return an InputStream for the response body
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @see #isGzipResponse
|
||||
* @see java.util.zip.GZIPInputStream
|
||||
* @see java.net.HttpURLConnection#getInputStream()
|
||||
*/
|
||||
private InputStream readResponseBody(HttpURLConnection con) throws IOException {
|
||||
if (isGzipResponse(con)) {
|
||||
// GZIP response found - need to unzip.
|
||||
return new GZIPInputStream(con.getInputStream());
|
||||
}
|
||||
else {
|
||||
// Plain response found.
|
||||
return con.getInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given response is a GZIP response.
|
||||
* <p>
|
||||
* This implementation checks whether the HTTP "Content-Encoding" header
|
||||
* contains "gzip" (in any casing).
|
||||
* @param con the HttpURLConnection to check
|
||||
*/
|
||||
private boolean isGzipResponse(HttpURLConnection con) {
|
||||
String encodingHeader = con.getHeaderField(HTTP_HEADER_CONTENT_ENCODING);
|
||||
return (encodingHeader != null
|
||||
&& encodingHeader.toLowerCase().indexOf(ENCODING_GZIP) != -1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -157,8 +157,8 @@ public class HttpInboundEndpointTests {
|
||||
@Test
|
||||
public void handleRequest_withCustomRequestMapper_requestObjectIsInPayload()
|
||||
throws ServletException, IOException {
|
||||
endpoint.setRequestMapper(new RequestMapper() {
|
||||
public Message<?> mapRequest(HttpServletRequest request) throws Exception {
|
||||
endpoint.setRequestMapper(new InboundRequestMapper() {
|
||||
public Message<?> toMessage(HttpServletRequest request) throws Exception {
|
||||
return new StringMessage(request.getRequestURI());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,22 +24,22 @@ import org.junit.Test;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.http.DataBindingRequestMapper;
|
||||
import org.springframework.integration.http.DataBindingInboundRequestMapper;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DataBindingRequestMapperTests {
|
||||
public class DataBindingInboundRequestMapperTests {
|
||||
|
||||
@Test
|
||||
public void bindToType() throws Exception {
|
||||
DataBindingRequestMapper mapper = new DataBindingRequestMapper(TestBean.class);
|
||||
DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("name", "testBean");
|
||||
request.setParameter("age", "42");
|
||||
Message<?> result = mapper.mapRequest(request);
|
||||
Message<?> result = mapper.toMessage(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(TestBean.class, result.getPayload().getClass());
|
||||
TestBean payload = (TestBean) result.getPayload();
|
||||
@@ -49,14 +49,14 @@ public class DataBindingRequestMapperTests {
|
||||
|
||||
@Test
|
||||
public void bindToTypeWithBindingInitializer() throws Exception {
|
||||
DataBindingRequestMapper mapper = new DataBindingRequestMapper(TestBean.class);
|
||||
DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class);
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setDirectFieldAccess(true);
|
||||
mapper.setWebBindingInitializer(initializer);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("name", "testBean");
|
||||
request.setParameter("age", "42");
|
||||
Message<?> result = mapper.mapRequest(request);
|
||||
Message<?> result = mapper.toMessage(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(TestBean.class, result.getPayload().getClass());
|
||||
TestBean payload = (TestBean) result.getPayload();
|
||||
@@ -70,12 +70,12 @@ public class DataBindingRequestMapperTests {
|
||||
MutablePropertyValues properties = new MutablePropertyValues();
|
||||
properties.addPropertyValue("name", "prototype");
|
||||
context.registerPrototype("prototypeTarget", TestBean.class, properties);
|
||||
DataBindingRequestMapper mapper = new DataBindingRequestMapper(TestBean.class);
|
||||
DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class);
|
||||
mapper.setTargetBeanName("prototypeTarget");
|
||||
mapper.setBeanFactory(context);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("age", "42");
|
||||
Message<?> result = mapper.mapRequest(request);
|
||||
Message<?> result = mapper.toMessage(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(TestBean.class, result.getPayload().getClass());
|
||||
TestBean payload = (TestBean) result.getPayload();
|
||||
Reference in New Issue
Block a user