Не удалось извлечь ответ: не найден подходящий HttpMessageConverter для типа ответа
Я новичок в весенней интеграции и работаю в http-модуле spring integration для моего требования к проекту. Я отправляю запрос от исходящего шлюза в качестве 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-исходящий-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>
Web.в XML
<?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>
сервлет-конфигурации.в 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.
я использовал базовый пример кода spring integration для справки. Пожалуйста, предоставьте свой вклад. Я также попытался использовать spring object mapper в файлах конфигурации с JSON to object transformer, но затем также я получаю аналогичные проблемы для HttpMessageConverter. Пожалуйста, помогите мне с вашими ценными входами / предложениями и дайте мне знать, если у нас есть какие-либо ограничения с spring integration http object mapper.
Привет Артем, Спасибо за ответ. Я все еще сталкиваюсь с некоторыми проблемами, упомянутыми ниже. Я внес изменения в свои файлы конфигурации в соответствии с вашим предложением. но столкнувшись с проблемой, когда используя Jackson2JsonObjectMapper и нужна ваша дальнейшая помощь. Пожалуйста, найдите ниже описание проблемы.
Я сделал изменения в Мои файлы и теперь файлы, как показано ниже: Мой Сервлет-Конфиг.содержимое 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>
Out bound file config (файл, который отвечает за отправку сообщения на сервер):
<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
Я проверил во время отладки, что тело полезной нагрузки в то время как в ответе становится пустым в объекте json в параметре Jackson2JsonObjectMapper.fromJson (...) после успешного роуминга через мой метод обслуживания. Я не могу понять, где я делаю ошибку. Пожалуйста, предоставьте свою помощь/ввод. Снова дайте мне знать, если я снова чего-то не хватает в моих файлах конфигурации. Большое спасибо за ваш поддержка.
4 ответов
так как вы возвращаетесь к клиенту просто String
и content type == 'text/plain'
, нет никаких шансов для преобразователей по умолчанию, чтобы определить, как конвертировать String
ответ FFSampleResponseHttp
"объект".
самый простой способ исправить это:
- удалить
expected-response-type
С<int-http:outbound-gateway>
- добавить
replyChannel1
<json-to-object-transformer>
в противном случае вы должны написать свой собственный HttpMessageConverter
для преобразования строки в соответствующий объект.
сделать это работы с MappingJackson2HttpMessageConverter
(один из преобразователей по умолчанию) и ваш expected-response-type
, вы должны отправить свой ответ с content type = 'application/json'
.
если есть необходимость, просто добавьте <header-enricher>
после <service-activator>
и перед отправкой ответа <int-http:inbound-gateway>
.
Итак, вам решать, какое решение выбрать, но ваше текущее состояние не работает из-за несоответствия конфигурации по умолчанию.
обновление
ОК. Так как вы изменили свой сервер на return FfSampleResponseHttp
объект как HTTP-ответ, а не строка, просто добавьте contentType = 'application/json'
заголовок перед отправкой ответа для HTTP и MappingJackson2HttpMessageConverter
будет делать вещи для вас, ваш объект будет преобразован в JSON и с правильным contentType
заголовок.
со стороны клиента вы должны вернуться в expected-response-type="com.mycompany.MyChannel.model.FFSampleResponseHttp"
и MappingJackson2HttpMessageConverter
должен сделать материал для вас снова.
конечно, вы должны удалить <json-to-object-transformer>
от вас поток сообщений после <int-http:outbound-gateway>
.
Как сказал Артем Билан, эта проблема возникает потому, что MappingJackson2HttpMessageConverter
поддерживает ответ только с типом контента application/json. Если вы не можете изменить код сервера, но можете изменить код клиента(у меня был такой случай), вы можете изменить заголовок content-type С помощью interceptor:
restTemplate.getInterceptors().add((request, body, execution) -> {
ClientHttpResponse response = execution.execute(request,body);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
return response;
});
вот простое решение
попробуйте добавить эту зависимость
<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
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());
}
}