Hidetoshi  Maekawa
Hidetoshi Maekawa

Reputation: 59

about RestTemplate

I have linked [Spring-Boot Rest API] and [Go Rest API] in the following configuration. Although the service of the destination URI exists, I intend to connect using RestTemplate in a communicable environment, but somehow it is a 404 error.

First of all, communication (2) is normal

The Rest service of [Go Rest API] is available from the terminal with the following cURL command.

$ curl http://localhost:18000/ping -X GET
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                             Dload  Upload   Total   Spent    Left  Speed
100   120  100   120    0     0    480      0 --:--:-- --:--:-- --:--:--   591
{"pong":"ok","meta":{"host":"622c72386c52","rid":"","StartTime":"2017-05-31T06:33:37.654710044Z","execute_time":0.0061}}

I would like to have the [Spring-Boot Rest API] on the front side and use the RestTemplate internally to access the above URL. It was coded as follows.

@RequestMapping(value = "/ping/", method = RequestMethod.POST)
public final ResponseEntity<ResPongDto> ping(@RequestBody SalesSituationInquiries input) {

    String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
    this.logger.info("■■UT:[{}]disposalDate:{}   ", methodName,input.getDisposalDate());
    // ①To   Client Response:ResPongDto
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    // ②From Client Request:SalesSituationInquiries
    this.logger.info("■■UT:[{}] From: {} To: {}", methodName,TotalSalesUtil.getStrFromByTo(input.getDisposalDate().toString()),input.getDisposalDate().toString());
    this.logger.info("■■UT:[{}] URL: {}", methodName,DailyReportsUtil.API_GO_PING_URL);
    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

    // ③To   Go Rest API Request:null
    // ④From Go Rest API Response:ResPongDto
    ResponseEntity<ResPongDto> resultGoMonth = restTemplate.exchange(
            TotalSalesUtil.createTotalSalesUrl(DailyReportsUtil.API_GO_PING_URL, "", "")
            , HttpMethod.GET
            , new HttpEntity<>(null)
            , ResPongDto.class);
    this.logger.info("■■UT:[{}] testRestTemplate.exchange(): ", methodName);

    result = new ResponseEntity<ResPongDto>(resultGoMonth.getBody(), headers, HttpStatus.CREATED);
    return result;
}

(2) via (1) Unfortunately, the result is a 404 error.

2017-05-31 15:35:43.190 [maekawa-PC-main]                   INFO  Exp:[id: tenant_id:] j.c.b.b.a.hogehogeApplication Started hogehogeApplication in 5.61 seconds (JVM running for 10.472)
2017-05-31 15:38:50.700 [maekawa-PC-http-nio-9999-exec-1]   WARN  Exp:[id: tenant_id:] j.c.b.b.a.i.YamlAuthenticationProcessingMockInterceptor YamlAuthenticationProcessingMockInterceptor:モック機能が動作しています。
2017-05-31 15:38:50.767 [maekawa-PC-http-nio-9999-exec-1]   INFO  Exp:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[ping]disposalDate:2017-04-03
2017-05-31 15:38:50.770 [maekawa-PC-http-nio-9999-exec-1]   INFO  Exp:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[ping] From: 2017-04-01 To: 2017-04-03
2017-05-31 15:38:50.770 [maekawa-PC-http-nio-9999-exec-1]   INFO  Exp:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[ping] URL: http://localhost:18000/ping
2017-05-31 15:38:50.868 [maekawa-PC-http-nio-9999-exec-1]   ACS   Exp:[id: tenant_id:] url:/api/v1/totalsalesstatus/ping/ status:200 elapsedNanoTime:146217390
2017-05-31 15:38:50.871 [maekawa-PC-http-nio-9999-exec-1]   ERROR  o.a.c.c.C.[.[.[.[dispatcherServlet] Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing 
failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 Not Found] with root cause

org.springframework.web.client.HttpClientErrorException: 404 Not Found
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
    at xx.xx.api.TotalSalesStatusCommandService.ping(TotalSalesStatusCommandService.java:90)
    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:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

Note:

(2)curl http://localhost:18000/ping -X GET

(1)curl http://localhost:9999/api/v1/totalsalesstatus/ping/ -X POST -H "Content-Type: application/json" -d '{"hoghoge": "1234", "disposalDate": "2017-04-03"}'

I do not know why they do not communicate with cURL, so please help me.

Upvotes: 0

Views: 15540

Answers (4)

Rajeev Rathor
Rajeev Rathor

Reputation: 1922

I struggled a lot with this exception Even URL is absolutely correct and relative URLs works for POST request. 404 means URL specify in RestTemplate or HttpRequest for GET type method is incorrect due to Query Param or Request Params or Path Params. Reason Query/Path param's value contain special character that converted or interpreted differently. Let Say queryParams is [email protected] which converted into email=test20%xyz41%.com

Solution: Decoding while passing query/path params.

Add Following code at server side [controller code]

ServerSide[Controller]:

import java.net.URLDecoder;
                         import java.net.URLEncoder;

String encodedEmail = URLDecoder.decode(email, "UTF-8");

It perfectly working and tested code.

Upvotes: 0

user3343491
user3343491

Reputation: 29

Try this. I was also getting the same error. The problem is caused by incorrect encoding.

public String getWeather(String cityName) {
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(weatherDataURL)
                                                       .queryParam("q", cityName)
                                                       .queryParam("APPID", apiKey);
    return restTemplate.getForObject(builder.buildAndExpand().toUri(), String.class);
}

Upvotes: 0

alfcope
alfcope

Reputation: 2427

Have you tried using getForEntity instead of exchange?

ResponseEntity<ResPongDto> resultGoMonth = restTemplate.getForEntity(
        TotalSalesUtil.createTotalSalesUrl(DailyReportsUtil.API_GO_PING_URL, "", "")
        , ResPongDto.class);

I guess your problem is you are not setting the right headers. You could try adding the accept header to the request.

final HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

HttpEntity entity = new HttpEntity(headers);
ResponseEntity<ResPongDto> resultGoMonth = restTemplate.exchange(
            TotalSalesUtil.createTotalSalesUrl(DailyReportsUtil.API_GO_PING_URL, "", ""),
            HttpMethod.GET,
            entity,
            ResPongDto.class);

This code has not been tested. It is just an example.

BTW, I do not know how you are creating the resttemplate object, but you should not update the converters. It should be done at initialisation point only, as resttemplate are not thread safe once they have been created.

Upvotes: 1

Sudhakar
Sudhakar

Reputation: 3180

Try below code. This consumes application/json as body and produces the json response.

@RequestMapping(value = "/ping", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public final ResponseEntity<ResPongDto> ping(@RequestBody SalesSituationInquiries input) {
    ..
}

Upvotes: 0

Related Questions