Nital
Nital

Reputation: 6114

Error while consuming a REST API in Spring Boot

I am trying to consume REST API which takes JSON payload and returns plain/text in the response. But I am getting following error during runtime.

SpotifyIntegrationApplication.java

@SpringBootApplication
public class SpotifyIntegrationApplication {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpotifyIntegrationApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(SpotifyIntegrationApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) {
        NewOrder newOrder = new NewOrder();
        return args -> {
            ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost:9999/order-sold", newOrder, String.class);
            LOGGER.info("responseEntity: " + responseEntity);
        };
    }

}

NewOrder.java

public class NewOrder {
    String orderId;
}

build.gradle

buildscript {
    ext {
        springBootVersion = '1.5.10.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.synapse.integration'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    runtime('com.h2database:h2')
    runtime('mysql:mysql-connector-java')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

Error:

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:735) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:304) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at com.synapse.integration.spotify.SpotifyIntegrationApplication.main(SpotifyIntegrationApplication.java:20) [classes/:na]
Caused by: org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.synapse.integration.spotify.model.NewOrder]
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:907) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:658) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:621) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:415) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at com.synapse.integration.spotify.SpotifyIntegrationApplication.lambda$run$0(SpotifyIntegrationApplication.java:32) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    ... 6 common frames omitted

Upvotes: 3

Views: 1676

Answers (4)

Arsalan Khalid
Arsalan Khalid

Reputation: 256

Hmm, the answers are all a bit confusing, when looking at Spring's documentation at: https://spring.io/guides/gs/consuming-rest/

It seems you should be able to successfully consume a response, map to a JSON object via annotated object.

However, even in doing this:

@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
    return args -> {
        Quote quote = restTemplate.getForObject(
                "http://localhost:8978/greeting", Quote.class);
        System.out.println(quote.toString());
        log.info(quote.toString());      
    };

I'm still getting the above Failed to execute CommandLineRunner error, going to have to investigate if its worth actually mapping to the HttpResponseObject. Hopefully there are some thoughts on my comment here.

Upvotes: 0

Nital
Nital

Reputation: 6114

Found the solution from above responses plus from some additional googling.

SpotifyIntegrationApplication.java

@SpringBootApplication
public class SpotifyIntegrationApplication {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpotifyIntegrationApplication.class);
    public static final String ENDPOINT = "http://localhost:9999/order-sold";

    public static void main(String[] args) {
        SpringApplication.run(SpotifyIntegrationApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) {
        return args -> {
            NewOrder newOrder = new NewOrder();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<NewOrder> entity = new HttpEntity<>(newOrder, headers);
            ResponseEntity<String> responseEntity = restTemplate.exchange(ENDPOINT, POST, entity, String.class);
            LOGGER.info("responseEntity: " + responseEntity);
        };
    }

}

NewOrder.java

@Data
public class NewOrder {

    private String orderId;

}

Although this was not part of the original question but also removed Tomcat library dependency since I am just consuming the API and not building one.

build.gradle

compile('org.springframework.boot:spring-boot-starter-web') {
    exclude module: "spring-boot-starter-tomcat"
}

Upvotes: 0

Chaitanya
Chaitanya

Reputation: 131

If the request made accepts only json, then provide headers specifying the content-type and convert the object to json( use Gson to convert object to json) and make a post request by setting all these to a HttpEntity

HttpHeaders headers = new HttpHeaders();
headers.add("content-type", "application/json");
headers.add("accept", "application/json");

String requestBody = gson.toJson(requestObject);

HttpEntity<String> httpEntity = new HttpEntity(requestBody,headers);

and make the rest call as

restTemplate.exchange(requestUrl,HttpMethod.POST,httpEntity,MyResponse.class)

Upvotes: 0

JaisAnkit
JaisAnkit

Reputation: 154

 I have used restTemplate.exchange but you can modify to use postForEntity 
 or postForObject. Hope this helps.

 private HttpHeaders createHttpHeaders() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    return headers;
    }

@RequestMapping("/testClient")
public String testClient() {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = createHttpHeaders();
    HttpEntity<String> entity = new HttpEntity<String>("parameters",
            headers);
    ResponseEntity<String> response = restTemplate.exchange(url,
            HttpMethod.GET, entity, String.class);
    if (response.getStatusCode().equals(HttpStatus.OK)) {
        System.out.println("getbody -" + response.getBody());
    }
    return "Test Client";
}

Upvotes: 1

Related Questions