【问题标题】:Adding Post Parameter in Spring-Integration outbound-gateway在 Spring-Integration outbound-gateway 中添加 Post 参数
【发布时间】:2015-12-12 22:04:05
【问题描述】:

我已经参考了这些示例来使用出站网关发送 POST 参数。

  1. https://github.com/spring-projects/spring-integration-samples/tree/master/intermediate/multipart-http

  2. Spring Integration - how to send POST parameters with http outbound-gateway

但是我遇到了异常

网关接口

import org.springframework.http.HttpStatus;
import java.util.Map;

public interface MultipartRequestGateway {
        HttpStatus postMultipartRequest(Map<String, Object> multipartRequest);
}

测试

public class TestClient {    
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
                "/META-INF/spring/integration/http-outbound-config.xml");
        Map<String, Object> requestMap = new HashMap<String, Object>();
        requestMap.put("cardNo", "4444333322221111");
        requestMap.put("currencyCode", "USD");
        requestMap.put("amount", "10.00");
        MultipartRequestGateway requestGateway = context.getBean("requestGateway", MultipartRequestGateway.class);
        HttpStatus httpStatus = requestGateway.postMultipartRequest(requestMap);
    }
}

用于 HTTPS 的自定义 HTTP 客户端

public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {

    @Override
    public Class<?> getObjectType() {
        return HttpClient.class;
    }

    @Override
    protected HttpClient createInstance() throws Exception {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        TrustStrategy allTrust = new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        };

        SSLContext sslcontext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, allTrust).build();

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        return httpClient;
    }
}

配置

<!--REQUEST CHANNELS-->
<int:channel id="PaymentAuthRequestChannel"/>

<!--ROUTING CHANNELS-->
<int:channel id="PaymentAuthRoutingChannel"/>

<!--ERROR CHANNEL-->
<int:channel id="ErrorChannel"/>

<!--GATEWAY-->
<int:gateway id="requestGateway"
             service-interface="org.springframework.integration.samples.http.MultipartRequestGateway"
             default-request-channel="PaymentAuthRoutingChannel">
    <int:default-header name="Api-Key" value="XYZ" />
    <int:default-header name="Accept" value="application/json; v=3"/>
    <int:default-header name="Content-Type" value="application/x-www-form-urlencoded"/>
</int:gateway>

<!--ROUTERS-->
<int:recipient-list-router id="paymentAuthRouter" input-channel="PaymentAuthRoutingChannel" default-output-channel="ErrorChannel">
    <int:recipient selector-expression="true" channel="PaymentAuthRequestChannel"/>
</int:recipient-list-router>

<!--PAYMENT-->
<int-http:outbound-gateway
        id="Auth Outbound Gateway"
        request-channel="PaymentAuthRequestChannel"
        reply-channel="PaymentAuthReplyChannel"
        request-factory="sslFactory"
        header-mapper="headerMapper"
        url="https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz"
        http-method="POST"
        expected-response-type="org.springframework.http.HttpStatus"
        extract-request-payload="true">
</int-http:outbound-gateway>

<!--TRANSFORMER-->
<int:transformer input-channel="PaymentAuthRequestChannel"
                 output-channel="PaymentAuthReplyChannel"
                 expression="payload.statusCode"/>

<!--SSL-->
<bean id="sslFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
    <constructor-arg ref="httpClient"/>
</bean>

<bean id="httpClient" class="org.springframework.integration.samples.http.HttpClientFactory" />

<bean id="httpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
    <constructor-arg ref="httpClient"/>
</bean>

<!--HEADER MAPPERS-->
<bean id="headerMapper"
      class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
            <property name="inboundHeaderNames" value="*" />
            <property name="outboundHeaderNames" value="Api-Key, Accept, Content-Type" />
            <property name="userDefinedHeaderPrefix" value="" />
</bean>

Stacktrace-1:java.lang.String 无法转换为 java.util.Map

16:36:30.913 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] started Post Payments Outbound Gateway
16:36:30.913 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] Adding {http:outbound-gateway:Auth Outbound Gateway} as a subscriber to the 'PaymentAuthRequestChannel' channel
16:36:30.914 INFO  [main][org.springframework.integration.channel.DirectChannel] Channel 'org.springframework.context.support.ClassPathXmlApplicationContext@7960847b.PaymentAuthRequestChannel' has 1 subscriber(s).
16:36:30.914 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] started Auth Outbound Gateway
16:36:30.914 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
16:36:30.914 INFO  [main][org.springframework.integration.channel.PublishSubscribeChannel] Channel 'org.springframework.context.support.ClassPathXmlApplicationContext@7960847b.errorChannel' has 1 subscriber(s).
16:36:30.914 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] started _org.springframework.integration.errorLogger
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.createHttpEntityFromPayload(HttpRequestExecutingMessageHandler.java:461)
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.generateHttpRequest(HttpRequestExecutingMessageHandler.java:437)
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:370)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)

更新堆栈跟踪

Stacktrace-2:415 不支持的媒体类型

12:06:19.246 DEBUG [main][org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'integrationEvaluationContext'
12:06:19.248 DEBUG [main][org.springframework.integration.channel.DirectChannel] preSend on channel 'PaymentAuthRequestChannel', message: GenericMessage [payload={currencyCode=USD, paymentAmount=100.00, cardNumber=4791247299592081}, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6253c26, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6253c26, Accept=application/json; v=3, id=3ddeae24-ae0a-33c0-55b9-7d8039cc8db1, Api-Key=XYZ, Content-Type=application/x-www-form-urlencoded, timestamp=1450026379245}]
12:06:19.248 DEBUG [main][org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler] org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler#0 received message: GenericMessage [payload={currencyCode=USD, paymentAmount=100.00, cardNumber=4791247299592081}, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6253c26, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6253c26, Accept=application/json; v=3, id=3ddeae24-ae0a-33c0-55b9-7d8039cc8db1, Api-Key=XYZ, Content-Type=application/x-www-form-urlencoded, timestamp=1450026379245}]
12:06:19.249 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] outboundHeaderNames=[Api-Key, Accept, Content-Type]
12:06:19.249 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[replychannel] WILL NOT be mapped
12:06:19.249 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[errorchannel] WILL NOT be mapped
12:06:19.249 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[accept] WILL be mapped, matched pattern=accept
12:06:19.249 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Accept], value=application/json; v=3
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[id] WILL NOT be mapped
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[api-key] WILL be mapped, matched pattern=api-key
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Api-Key], value=XYZ
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[content-type] WILL be mapped, matched pattern=content-type
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Content-Type], value=application/x-www-form-urlencoded
12:06:19.250 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[timestamp] WILL NOT be mapped
12:06:19.270 DEBUG [main][org.springframework.web.client.RestTemplate] Created POST request for "https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz"
12:06:19.271 DEBUG [main][org.springframework.web.client.RestTemplate] Setting request Accept header to [text/plain, */ *]
12:06:19.272 DEBUG [main][org.springframework.web.client.RestTemplate] Writing [{currencyCode=[USD], paymentAmount=[100.00], cardNumber=[4444333322221111]}] as "application/x-www-form-urlencoded" using [org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@4145bad8]
12:06:19.692 DEBUG [main][org.springframework.web.client.RestTemplate] POST request for "https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz" resulted in 415 (Unsupported Media Type); invoking error handler
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
12:06:19.694 DEBUG [main][org.springframework.integration.gateway.GatewayProxyFactoryBean$MethodInvocationGateway] failure occurred in gateway sendAndReceive: HTTP request execution failed for URI [https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz]; nested exception is org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:636)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:592)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:567)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:488)
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:382)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)

注意: 在我的 spring-integration 配置 xml 中,如果我将内容类型从 application/x-www-form-urlencoded 更改为 application/json 即

<int:default-header name="Content-Type" value="application/json"/>

Stacktrace-3:找不到适合请求类型 [java.util.HashMap]

的 HttpMessageConverter
13:32:29.670 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] outboundHeaderNames=[Api-Key, Accept, Content-Type]
13:32:29.670 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[replychannel] WILL NOT be mapped
13:32:29.670 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[errorchannel] WILL NOT be mapped
13:32:29.670 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[accept] WILL be mapped, matched pattern=accept
13:32:29.670 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Accept], value=application/json; v=3
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[id] WILL NOT be mapped
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[api-key] WILL be mapped, matched pattern=api-key
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Api-Key], value=XYZ
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[content-type] WILL be mapped, matched pattern=content-type
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Content-Type], value=application/json
13:32:29.671 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[timestamp] WILL NOT be mapped
Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/json]
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:806)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:589)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:567)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:488)
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:382)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105)
    at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:166)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)13:32:29.686 DEBUG [main][org.springframework.web.client.RestTemplate] Created POST request for "https://XX.XX.XX.XXXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz"
13:32:29.686 DEBUG [main][org.springframework.web.client.RestTemplate] Setting request Accept header to [text/plain, */*]
13:32:29.688 DEBUG [main][org.springframework.integration.gateway.GatewayProxyFactoryBean$MethodInvocationGateway] failure occurred in gateway sendAndReceive: HTTP request execution failed for URI [https://XX.XX.XX.XXXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz]; nested exception is org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/json]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)

Stacktrace-4:找不到能够从 org.springframework.http.ResponseEntity 类型转换为 java.lang.String 类型的转换器

4:49:48.639 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[timestamp] WILL NOT be mapped
14:49:48.663 DEBUG [main][org.springframework.web.client.RestTemplate] Created POST request for "https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz"
14:49:48.666 DEBUG [main][org.springframework.web.client.RestTemplate] Setting request Accept header to [text/plain, application/json, application/*+json, */*]
14:49:48.680 DEBUG [main][org.springframework.web.client.RestTemplate] Writing [{currencyCode=USD, paymentAmount=100.00, cardNumber=4444333322221111}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7b7fdc8]
14:49:49.758 DEBUG [main][org.springframework.web.client.RestTemplate] POST request for "https://XX.XX.XX.XXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/xyz" resulted in 201 (Created)
14:49:49.759 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] inboundHeaderNames=[*]
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[set-cookie] WILL be mapped, matched pattern=*
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Set-Cookie], value=[JSESSIONID=9F2928189B07D0E3F54D83EA28C36C67; Path=/int-tsys-cc-payment-auth-web/; Secure; HttpOnly]
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[x-content-type-options] WILL be mapped, matched pattern=*
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[X-Content-Type-Options], value=[nosniff]
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[x-xss-protection] WILL be mapped, matched pattern=*
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[X-XSS-Protection], value=[1; mode=block]
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[cache-control] WILL be mapped, matched pattern=*
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Cache-Control], value=no-cache, no-store, max-age=0, must-revalidate
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[pragma] WILL be mapped, matched pattern=*
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Pragma], value=no-cache
14:49:49.760 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[expires] WILL be mapped, matched pattern=*
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[strict-transport-security] WILL be mapped, matched pattern=*
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Strict-Transport-Security], value=[max-age=31536000 ; includeSubDomains]
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[x-frame-options] WILL be mapped, matched pattern=*
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[X-Frame-Options], value=[DENY]
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[accept] WILL be mapped, matched pattern=*
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Accept], value=[application/json;v=3]
14:49:49.761 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[content-length] WILL be mapped, matched pattern=*
14:49:49.762 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Content-Length], value=0
14:49:49.762 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[date] WILL be mapped, matched pattern=*
14:49:49.763 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Date], value=1,450,036,189,000
14:49:49.763 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] headerName=[server] WILL be mapped, matched pattern=*
14:49:49.763 DEBUG [main][org.springframework.integration.http.support.DefaultHttpHeaderMapper] setting headerName=[Server], value=[XYZ]
14:49:49.764 DEBUG [main][org.springframework.integration.channel.DirectChannel] postSend (sent=true) on channel 'PaymentAuthRequestChannel', message: GenericMessage [payload={currencyCode=USD, paymentAmount=100.00, cardNumber=4444333322221111}, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@51bd8b5c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@51bd8b5c, Accept=application/json; v=3, id=ca7b5634-3721-6a1b-9f20-439ceab25831, Api-Key=XYZ, Content-Type=application/json, timestamp=1450036188634}]
14:49:49.764 DEBUG [main][org.springframework.integration.channel.DirectChannel] postSend (sent=true) on channel 'PaymentAuthRoutingChannel', message: GenericMessage [payload={currencyCode=USD, paymentAmount=100.00, cardNumber=4444333322221111}, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@51bd8b5c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@51bd8b5c, Accept=application/json; v=3, id=ca7b5634-3721-6a1b-9f20-439ceab25831, Api-Key=XYZ, Content-Type=application/json, timestamp=1450036188634}]
14:49:49.764 DEBUG [main][org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'integrationConversionService'
Exception in thread "main" org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type org.springframework.http.ResponseEntity<?> to type java.lang.String
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:313)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.convert(GatewayProxyFactoryBean.java:593)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:429)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:382)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:373)
    at org.springframework.integration.gateway.GatewayCompletableFutureProxyFactoryBean.invoke(GatewayCompletableFutureProxyFactoryBean.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy6.echo(Unknown Source)
    at org.springframework.integration.samples.http.RTFAOrchestrationTest.main(RTFAOrchestrationTest.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Process finished with exit code 1

Stacktrace-5(添加 Transformer 后)

15:42:38.771 DEBUG [main][org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'integrationEvaluationContext'
15:42:38.772 DEBUG [main][org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'integrationConversionService'
15:42:38.775 DEBUG [main][org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor] SpEL Expression evaluation failed with EvaluationException.
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 8): Property or field 'statusCode' cannot be found on object of type 'java.util.HashMap' - maybe not public?
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)

验证 API 适用于来自 SOAP-UI for REST 的以下 REST 请求

POST https://XX.XX.XX.XXXX:11210/int-tsys-cc-payment-auth-web/integration/tsys/credit-cards/payments/fadsfsad HTTP/1.1
Accept-Encoding: gzip,deflate
Api-Key: XYZ
Accept: application/json;v=3
Content-Type: application/json
Content-Length: 84
Host: XX.XX.XX.XXXX:11210
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

{
"cardNumber":"4444333322221111",
"currencyCode":"USD",
"paymentAmount":"12.00" 
}

【问题讨论】:

  • 最好能看到更多的堆栈跟踪...
  • @ArtemBilan 请找到更新的堆栈跟踪,急切地等待您对此的想法

标签: spring spring-integration


【解决方案1】:

似乎Map 正在以某种方式转换为String;目前尚不清楚您显示的配置如何可能发生这种情况。第一步(始终)是打开org.springframework.integration 的调试日志记录。您应该会看到消息 preSend on channel 'requestChannel...HttpRequestExecutingMessageHandler#0 received message ...,中间没有任何内容。

【讨论】:

  • 之前我发布了我的代码的简化版本,但现在我简化了我的代码本身并更新了上面的相同配置。我还启用了调试模式。现在我看到了不同的例外。请找到我添加到问题中的两个新堆栈跟踪。
  • 根据您的测试用例,您的应用似乎需要application/json,而不是multipart/x-www-form-urlencoded。要将 Map 转换为 JSON,请确保在类路径中有 Jackson 并使用 &lt;int:default-header name="Content-Type" value="application/json"/&gt;。出站适配器会自动将 Map 转换为 JSON。 Multipart 用于发送文件等,如示例中所示。
  • com.fasterxml.jackson.core:jackson-databind:2.5.1 添加到您的类路径中,框架将自动配置一个 JSON 消息转换器。 ...databind 有其他依赖项,如果您使用 maven 或 gradle 进行依赖项管理,这些依赖项将自动引入。
  • 添加杰克逊依赖后,我可以看到 POST 请求返回 201,但是我仍然得到 ConverterNotFoundException 并且无法解析响应。请查看问题中的 Stacktrace-4。谢谢!
  • 请求网关中正在尝试转换;看来您已将返回类型从 HttpStatus 更改为 String。将返回类型改为ResponseEntity,或者改为HttpStatus并在http出站网关后添加&lt;transformer ... expression="payload.statusCode" /&gt;
猜你喜欢
  • 2015-08-10
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多