복붙노트

[SPRING] 응답을 추출 할 수 없습니다 : 응답 유형에 적합한 HttpMessageConverter가 없습니다.

SPRING

응답을 추출 할 수 없습니다 : 응답 유형에 적합한 HttpMessageConverter가 없습니다.

나는 봄 통합과 새로운 봄 요구 사항에 대한 봄 통합 http 모듈에서 일하고있다. HTTP 클라이언트로 아웃 바운드 게이트웨이에서 요청을 보내고 있습니다. 서버에 대한 요청을 시작하려고하는데 서버가 설정 값으로 메시지 페이로드를 반환해야합니다. JSON으로 개체를 변환하여 서버로 보내고 있습니다. 아래에 표시된 클라이언트 (HttpClientDemo)에서 서버 측에있는 인바운드 게이트웨이에 요청을 보내고 있습니다. 이를 위해 객체를 JSON으로 변환 한 다음 JSON 문자열로 변환하여 클라이언트 측에서 객체로 변환 한 다음 간단한 작업을 수행하고 클라이언트 (HttpClientDemo)로 다시 보냅니다. 그러나이 전에는 예외가 발생했습니다. 아래의 HttpMessageConverter :

Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.mycompany.MyChannel.model.FFSampleResponseHttp] and content type [text/plain;charset=UTF-8]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:108)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:784)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:769)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:549)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:517)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:462)
    at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:421)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
    at org.springframework.integration.channel.AbstractSubscribablMyChannel.doSend(AbstractSubscribablMyChannel.java:77)
    at org.springframework.integration.channel.AbstractMessagMyChannel.send(AbstractMessagMyChannel.java:255)
    at org.springframework.integration.channel.AbstractMessagMyChannel.send(AbstractMessagMyChannel.java:223)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)

아래에서 관련 코드를 찾으십시오.

고객 측 코드 : HttpClientDemo.java

public class HttpClientDemo {

    private static Logger logger = Logger.getLogger(HttpClientDemo.class);
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/integration/http-outbound-config.xml");
RequestGateway requestGateway = context.getBean("requestGateway", RequestGateway.class);        
        FFSampleRequestHttp FFSampleRequesthttp = new FFSampleRequestHttp();
        FFSampleRequesthttp.setMyChannelID("1");
        FFSampleRequesthttp.setMyNumber("88");
        FFSampleRequesthttp.setReferenceID("9I");
        FFSampleRequesthttp.setTemplateType(1);
        FFSampleRequesthttp.setTimestamp("today");
        FFSampleResponseHttp  reply = requestGateway.FFSampleResponsegatway(FFSampleRequesthttp);
            logger.info("Replied with: " + reply);
    }

}

내 요청 게이트웨이는 다음과 같습니다 : RequestGateway.java

public interface RequestGateway {


    FFSampleResponseHttp FFSampleResponsegatway(FFSampleRequestHttp request);

}

http-outbound-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-http="http://www.springframework.org/schema/integration/http"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

    <int:gateway id="requestGateway" 
                 service-interface="com.mycompany.MyChannel.Common.RequestGateway"
                 default-request-channel="requestChannel"/>

    <int:channel id="requestChannel"/>
    <int:channel id="requestChannel1"/>


<!--    com.mycompany.MyChannel.model.FFSampleResponseHttp -->

    <int-http:outbound-gateway request-channel="requestChannel1" reply-channel="replyChannel1" url="http://localhost:8080/MyChannel_prj-1.0.0.BUILD-SNAPSHOT/receiveGateway"  http-method="POST"  extract-request-payload="true" expected-response-type="com.mycompany.MyChannel.model.FFSampleResponseHttp"/>

   <int:object-to-json-transformer  input-channel="requestChannel" output-channel="requestChannel1" content-type="application/json"  result-type="STRING"/>



   <bean id="FFSampleRequestHttp" class="com.mycompany.MyChannel.model.FFSampleRequestHttp"></bean>


</beans>

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


<servlet>
    <servlet-name>MyChannel-http</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/servlet-config.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyChannel-http</servlet-name>
    <url-pattern>/receiveGateway</url-pattern>
   </servlet-mapping>


    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>

servlet-config.xml

    <int:channel id="receivMyChannel"/>

<int-http:inbound-gateway request-channel="receivMyChannel" path="/receiveGateway" supported-methods="POST"/>

    <int:service-activator input-channel="receivMyChannel">
        <bean class="com.mycompany.MyChannel.serviceImpl.FFSampleHttpImpl">
        <constructor-arg ref = "FFSampleRequestHttp"></constructor-arg>
        </bean>
        </int:service-activator>


     <bean id="FFSampleRequestHttp" class="com.mycompany.MyChannel.model.FFSampleRequestHttp"></bean>
     <bean id="FFSampleResponseHttp" class="com.mycompany.MyChannel.model.FFSampleResponseHttp"></bean>

    </beans> 



public class FFSampleHttpImpl{

    private static org.apache.log4j.Logger log = Logger
            .getLogger(FFSampleImpl.class);

    @Autowired
    FFSampleRequestHttp request;
    public FFSampleHttpImpl() {
    }

    public FFSampleHttpImpl(FFSampleRequestHttp request) {
        super();
        this.request = request;
    }





    public String issueResponseFor(String str) throws JsonParseException, JsonMappingException, IOException {

        ObjectMapper mapper = new ObjectMapper();

        FFSampleRequestHttp FFSampleRequestHttp = mapper.readValue(new String(str), FFSampleRequestHttp.class);

        FFSampleRequestHttp.setReferenceID("Hi My Number");

        String  strs = new String();

        strs = mapper.writeValueAsString(FFSampleRequestHttp);

            return strs;

        }

}

FFSampleRequestHttp.java

public class FFSampleRequestHttp {
    protected String MyNumber;  
    protected String referenceID;   
    protected String myChannelID;
    protected String timestamp;
    protected int templateType;
    public String getMyNumber() {
        return MyNumber;
    }
    public void setMyNumber(String MyNumber) {
        this.MyNumber = MyNumber;
    }
    public String getReferenceID() {
        return referenceID;
    }
    public void setReferenceID(String referenceID) {
        this.referenceID = referenceID;
    }
    public String getMyChannelID() {
        return myChannelID;
    }
    public void setMyChannelID(String myChannelID) {
        this.myChannelID = myChannelID;
    }
    public String getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }
    public int getTemplateType() {
        return templateType;
    }
    public void setTemplateType(int templateType) {
        this.templateType = templateType;
    }
    }

FFSampleResponseHttp.java

public class FFSampleResponseHttp {
    protected String MyNumber;
    protected String referenceID;
    protected String myChannelID;
    protected String timestamp;
    protected int templateType;

    public String getMyNumber() {
        return MyNumber;
    }
    public void setMyNumber(String MyNumber) {
        this.MyNumber = MyNumber;
    }
    public String getReferenceID() {
        return referenceID;
    }
    public void setReferenceID(String referenceID) {
        this.referenceID = referenceID;
    }
    public String getMyChannelID() {
        return myChannelID;
    }
    public void setMyChannelID(String myChannelID) {
        this.myChannelID = myChannelID;
    }
    public String getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }
    public int getTemplateType() {
        return templateType;
    }
    public void setTemplateType(int templateType) {
        this.templateType = templateType;
    }
    }

위의 코드를 실행하면 다음 오류가 발생합니다.

16:55:46.843 [main] DEBUG o.s.web.client.RestTemplate - Writing [{"MyNumber":"88","referenceID":"9I","myChannelID":"1","timestamp":"today","templateType":1}] as "text/plain;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@7d31a3e2]
16:55:46.988 [main] DEBUG o.s.web.client.RestTemplate - POST request for "http://localhost:8080/MyChannel_prj-1.0.0.BUILD-SNAPSHOT/receiveGateway" resulted in 200 (OK)
Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.mycompany.MyChannel.model.FFSampleResponseHttp] and content type [text/plain;charset=UTF-8]
    at org.springframework.web.client.HttpMessageConverterExtractor. 

참조 용 스프링 통합 기본 샘플 코드를 사용했습니다. 귀하의 의견을 제공하십시오. JSON을 사용하여 구성 파일에서 스프링 객체 매퍼를 사용하여 객체 변압기로 시도했지만 HttpMessageConverter에 대한 시뮬레이터 문제가 발생했습니다. 귀중한 의견 / 제안을 도와 주시고 스프링 통합 http 객체 매퍼에 제한이 있다면 알려 주시기 바랍니다.

안녕 Artem, 답장을 보내 주셔서 감사합니다. 나는 아직도 아래에 언급 된 몇 가지 도전에 직면 해있다. 나는 귀하의 제안에 따라 구성 파일을 변경했습니다. Jackson2JsonObjectMapper를 사용할 때 문제가 발생하여 도움이 더 필요합니다. 문제 설명 아래에서 찾으십시오.

내 파일을 변경했는데 파일이 아래와 같습니다. 내 서블릿 - Config.xml 파일 내용은 다음과 같습니다.

<int:channel id="channel1" /> 
<int:channel id="channel2" /> 
<int:channel id="channel3" /> 
<int-http:inbound-gateway request-channel="channel1" supported-methods="POST" path="/receiveGateway" /> 
- <int:service-activator input-channel="channel2"> 
- <bean class="com.myCompany.myChannel.serviceImpl.FFSampleHttpImpl"> 
<constructor-arg ref="ffSampleRequestHttp" /> 
</bean> 
</int:service-activator> 

<int:json-to-object-transformer input-channel="channel1" output-channel="channel2" type="com.myCompany.myChannel.model.FFSampleRequestHttp" object-mapper="jackson2JsonObjectMapper" /> 

<bean id="jackson2JsonObjectMapper" class="org.springframework.integration.support.json.Jackson2JsonObjectMapper" /> 
<bean id="ffSampleRequestHttp" class="com.myCompany.myChannel.model.FFSampleRequestHttp" /> 
<bean id="ffSampleResponseHttp" class="com.myCompany.myChannel.model.FFSampleResponseHttp" /> 
</beans>

바운딩 된 파일 구성 (서버로 보낸 메시지를 담당하는 파일) :

<int:gateway id="requestGateway" service-interface="com.myCompany.myChannel.Common.RequestGateway" default-request-channel="requestChannel" /> 
  <int:channel id="requestChannel" /> 
  <int:channel id="requestChannel1" /> 
  <int:object-to-json-transformer input-channel="requestChannel" output-channel="requestChannel1" content-type="application/json" /> 
  <int-http:outbound-gateway request-channel="requestChannel1" reply-channel="channel4" url="http://localhost:8080/myChannel_prj-1.0.0.BUILD-SNAPSHOT/http/receiveGateway" http-method="POST" /> 
  <bean id="FFSampleRequestHttp" class="com.myCompany.myChannel.model.FFSampleRequestHttp" /> 
  <int:json-to-object-transformer input-channel="channel4" output-channel="requestChannel" type="com.myCompany.myChannel.model.FFSampleResponseHttp" object-mapper="jackson2JsonObjectMapper" /> 
  <bean id="jackson2JsonObjectMapper" class="org.springframework.integration.support.json.Jackson2JsonObjectMapper" /> 
  </beans>

내 impl 클래스 메서드는 다음과 같습니다.

public  FfSampleResponseHttp issueResponseFor(FfSampleRequestHttp request) {

        FfSampleResponseHttp ffSampleResponse2 = new FfSampleResponseHttp();

        ffSampleResponse2.setCifNumber("Yappi I am in the method");
        log.info("issueResponseFor(FfSampleRequesthttp request)");

        return ffSampleResponse2;

    }

내 서비스 메서드 issueResponseFor 클라이언트에서 서버 측에 현재 호출 할 수 있지만 더 처리 할 때 :

Caused by: java.lang.IllegalArgumentException: 'json' argument must be an instance of: [class java.lang.String, class [B, class java.io.File, class java.net.URL, class java.io.InputStream, class java.io.Reader]
       at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:93)
       at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:44)
       at org.springframework.integration.support.json.AbstractJacksonJsonObjectMapper.fromJson(AbstractJacksonJsonObjectMapper.java:55)
       at org.springframework.integration.json.JsonToObjectTransformer.doTransform(JsonToObjectTransformer.java:78)
       at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
       ... 54 more

내 서비스 메소드를 성공적으로 로밍 한 후 Jackson2JsonObjectMapper.fromJson (...) 매개 변수의 json 객체에서 응답하는 동안 페이로드 본문이 비어있는 동안 디버깅하는 동안 확인했습니다. 나는 실수를 어디에서하고 있는지 이해할 수 없다. 귀하의 도움 / 의견을 제공해주십시오. 다시 설정 파일에 뭔가 빠졌는지 다시 알려주십시오. 귀하의 성원에 진심으로 감사드립니다.

해결법

  1. ==============================

    1.클라이언트와 String == 'text / plain'을 반환하기 때문에 기본 변환기가 String 응답을 FFSampleResponseHttp 개체로 변환하는 방법을 결정할 가능성은 없습니다.

    클라이언트와 String == 'text / plain'을 반환하기 때문에 기본 변환기가 String 응답을 FFSampleResponseHttp 개체로 변환하는 방법을 결정할 가능성은 없습니다.

    그것을 고칠 수있는 간단한 방법 :

    그렇지 않으면 자신의 HttpMessageConverter를 작성하여 문자열을 적절한 객체로 변환해야합니다.

    MappingJackson2HttpMessageConverter (기본 변환기 중 하나) 및 예상 응답 유형과 작동하게하려면 content type = 'application / json'으로 회신을 보내야합니다.

    필요한 경우 뒤에 를 추가하고 에 응답을 보내기 만하면됩니다.

    따라서 어떤 솔루션을 선택할지는 사용자에게 달려 있지만 기본 구성과의 불일치로 인해 현재 상태가 작동하지 않습니다.

    최신 정보

    승인. FfSampleResponseHttp 객체를 String이 아닌 HTTP 응답으로 반환하도록 서버를 변경했기 때문에 HTTP에 대한 응답을 보내기 전에 contentType = 'application / json'헤더를 추가하기 만하면 MappingJackson2HttpMessageConverter가 자동으로 작업을 수행합니다. 객체가 JSON으로 변환되고 올바른 contentType 헤더가 있어야합니다.

    클라이언트 측에서는 expected-response-type = "com.mycompany.MyChannel.model.FFSampleResponseHttp"로 돌아가고 MappingJackson2HttpMessageConverter가 다시 처리해야합니다.

    물론 뒤에 메시지 흐름에서 를 제거해야합니다.

  2. ==============================

    2.다음은 간단한 해결책입니다.

    다음은 간단한 해결책입니다.

    이 종속성을 추가하십시오.

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.3</version>
    </dependency>
    

    출처 : http://www.javaproficiency.com/2016/01/rest-template-could-not-extract.html

  3. ==============================

    3.Artem Bilan이 말했듯이 MappingJackson2HttpMessageConverter는 application / json content-type에 대한 응답 만 지원하므로이 문제가 발생합니다. 서버 코드를 변경할 수 없지만 클라이언트 코드를 변경할 수있는 경우 (그런 경우) 인터셉터를 사용하여 컨텐트 유형 헤더를 변경할 수 있습니다.

    Artem Bilan이 말했듯이 MappingJackson2HttpMessageConverter는 application / json content-type에 대한 응답 만 지원하므로이 문제가 발생합니다. 서버 코드를 변경할 수 없지만 클라이언트 코드를 변경할 수있는 경우 (그런 경우) 인터셉터를 사용하여 컨텐트 유형 헤더를 변경할 수 있습니다.

    restTemplate.getInterceptors().add((request, body, execution) -> {
                ClientHttpResponse response = execution.execute(request,body);
                response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                return response;
            });
    
  4. ==============================

    4.

    public class Application {
    
        private static List<HttpMessageConverter<?>> getMessageConverters() {
            List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
            converters.add(new MappingJacksonHttpMessageConverter());
            return converters;
        }   
    
        public static void main(String[] args) {
            RestTemplate restTemplate = new RestTemplate();
    
            restTemplate.setMessageConverters(getMessageConverters());
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
            HttpEntity<String> entity = new HttpEntity<String>(headers);
            //Page page = restTemplate.getForObject("http://graph.facebook.com/pivotalsoftware", Page.class);
    
            ResponseEntity<Page> response = 
                      restTemplate.exchange("http://graph.facebook.com/skbh86", HttpMethod.GET, entity, Page.class, "1");
            Page page = response.getBody();
            System.out.println("Name:    " + page.getId());
            System.out.println("About:   " + page.getFirst_name());
            System.out.println("Phone:   " + page.getLast_name());
            System.out.println("Website: " + page.getMiddle_name());
            System.out.println("Website: " + page.getName());
        }
    }
    
  5. from https://stackoverflow.com/questions/24723394/could-not-extract-response-no-suitable-httpmessageconverter-found-for-response by cc-by-sa and MIT license