외부기관 API를 통해서 데이터를 주고받고 하는 부분이 있어 RestTemplate을 사용하는 중에 발생한 에러 포스팅해볼게요.
public ResponseEntity<T2> post(String endpointUrl, T1 body, Class<T2> responseType, HeadersStrategy strategy) {
HttpEntity<T1> httpEntity = new HttpEntity<>(body, headers(HttpMethod.POST, strategy));
ResponseEntity<T2> response = restTemplate.postForEntity(endpointUrl, httpEntity, responseType);
return response;
}
body부분에 VO class를 전달하고 post로 발송하니 서버 쪽에서는 parameter값이 없다 하여 확인을 했어요.
private static boolean romePresent =
ClassUtils.isPresent("com.rometools.rome.feed.WireFeed",
RestTemplate.class.getClassLoader());
private static final boolean jaxb2Present =
ClassUtils.isPresent("javax.xml.bind.Binder",
RestTemplate.class.getClassLoader());
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
RestTemplate.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
RestTemplate.class.getClassLoader());
private static final boolean jackson2XmlPresent =
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper",
RestTemplate.class.getClassLoader());
private static final boolean gsonPresent =
ClassUtils.isPresent("com.google.gson.Gson",
RestTemplate.class.getClassLoader());
실제 RestTemplate 소스 부분이에요. 기본적인 Converter들이에요 일반적인 json방식은 jackson으로 변환이 돼요.
public RestTemplate() {
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
}
else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
}
}
생성자 소스 부분인데 여기에서 생성할 때 기본적인 Converter를 등록해요.
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter instanceof GenericHttpMessageConverter) {
GenericHttpMessageConverter<Object> genericMessageConverter = (GenericHttpMessageConverter<Object>) messageConverter;
if (genericMessageConverter.canWrite(requestBodyType, requestBodyClass, requestContentType)) {
if (!requestHeaders.isEmpty()) {
for (Map.Entry<String, List<String>> entry : requestHeaders.entrySet()) {
httpHeaders.put(entry.getKey(), new LinkedList<String>(entry.getValue()));
}
}
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
logger.debug("Writing [" + requestBody + "] as \"" + requestContentType +
"\" using [" + messageConverter + "]");
}
else {
logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
}
genericMessageConverter.write(
requestBody, requestBodyType, requestContentType, httpRequest);
return;
}
}
else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
if (!requestHeaders.isEmpty()) {
for (Map.Entry<String, List<String>> entry : requestHeaders.entrySet()) {
httpHeaders.put(entry.getKey(), new LinkedList<String>(entry.getValue()));
}
}
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
logger.debug("Writing [" + requestBody + "] as \"" + requestContentType +
"\" using [" + messageConverter + "]");
}
else {
logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
}
}
((HttpMessageConverter<Object>) messageConverter).write(
requestBody, requestContentType, httpRequest);
return;
}
}
RestTemplate에서 execute실행 전 소스인데 전달받은 body가 해당 converter에 해당되는지 판별하고 값을 write를 하고 있습니다. 저기에 해당이 안되면 body가 없이 전달이 되기 때문에 생성할 때 convert를 전달하거나 기본 내장된 convert를 사용해야 해요. 그래서 사용한 게 Spring에서 제공하는 MultiValueMap이에요. 해당 부분은 MAP처럼 parameter를 put을해서 사용하시면 돼요.
MultiValueMap<String, Object> mmap = new LinkedMultiValueMap<>();
사용 중에 값은 전달이 되는데 빨간 부분처럼 header에 "multipart/form-data"가 추가되어 API 서버에서 parameter를 못 받는 현상이 발견되어서 확인 중에VO변수 중에 Integer를 사용하는 변수들이 있는데 Integer -> String로 변경 후 실행하니 multipart가 add가 안되었습니다. 왜 Integer를 사용하면 붙는지는 소스를 더 확인을 안 하여 그냥 String을 사용하기로 하였습니다~~~
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(HTTP_CONNECT_TIMEOUT);
requestFactory.setReadTimeout(HTTP_READ_TIMEOUT);
farmLandInfoReqRequestTemplatProvider.get().setRequestFactory(requestFactory);
Map<String, Object> map = new HashMap<>();
MultiValueMap<String, Object> mmap = new LinkedMultiValueMap<>();
try {
map = BeanConverter.toMap(request);
mmap.setAll(map);
} catch (Exception e) {
}
return farmLandInfoReqRequestTemplatProvider.get().post(url, mmap, BaseReqResponse.class);
최종적으로 body부분을 MultivalueMap으로 변경하여 사용하였습니다.
'개발 > Java' 카테고리의 다른 글
이클립스 Formatter off (0) | 2021.02.16 |
---|---|
Java 단방향,양방향 암호화 (1) | 2021.01.25 |
List 중복 제거 및 List 정렬(Collections.sort) (1) | 2021.01.04 |
org.javers.core.Javers사용하여 Java Model 값 비교 (4) | 2020.11.27 |
egov 3.9버전 mybatis association 사용시 에러(org.apache.ibatis.javassist.util.proxy.SecurityActions.setAccessible) (0) | 2020.11.19 |