Giter Site home page Giter Site logo

spring-guides / gs-consuming-rest Goto Github PK

View Code? Open in Web Editor NEW
191.0 30.0 287.0 1.16 MB

Consuming a RESTful Web Service :: Learn how to retrieve web page data with Spring's RestTemplate.

Home Page: https://spring.io/guides/gs/consuming-rest/

License: Apache License 2.0

Java 89.60% Shell 10.40%

gs-consuming-rest's Introduction

This guide walks you through the process of creating an application that consumes a RESTful web service.

What You Will Build

You will build an application that uses Spring’s RestTemplate to retrieve a random Spring Boot quotation at http://localhost:8080/api/random.

Starting with Spring Initializr

You can use this pre-initialized project and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.

To manually initialize the project:

  1. Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.

  2. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.

  3. Click Dependencies and select Spring Web.

  4. Click Generate.

  5. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.

Note
If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
Note
You can also fork the project from Github and open it in your IDE or other editor.

Fetching a REST Resource

With project setup complete, you can create a simple application that consumes a RESTful service.

Before you can do so, you need a source of REST resources. We have provided an example of such a service at https://github.com/spring-guides/quoters. You can run that application in a separate terminal and access the result at http://localhost:8080/api/random. That address randomly fetches a quotation about Spring Boot and returns it as a JSON document. Other valid addresses include http://localhost:8080/api/ (for all the quotations) and http://localhost:8080/api/1 (for the first quotation), http://localhost:8080/api/2 (for the second quotation), and so on (up to 10 at present).

If you request that URL through a web browser or curl, you receive a JSON document that looks something like this:

{
   type: "success",
   value: {
      id: 10,
      quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
   }
}

That is easy enough but not terribly useful when fetched through a browser or through curl.

A more useful way to consume a REST web service is programmatically. To help you with that task, Spring provides a convenient template class called RestTemplate. RestTemplate makes interacting with most RESTful services a one-line incantation. And it can even bind that data to custom domain types.

First, you need to create a domain class to contain the data that you need. The following listing shows the Quote record class, which you can use as your domain class:

src/main/java/com/example/consumingrest/Quote.java

link:complete/src/main/java/com/example/consumingrest/Quote.java[role=include]

This simple Java record class is annotated with @JsonIgnoreProperties from the Jackson JSON processing library to indicate that any properties not bound in this type should be ignored.

To directly bind your data to your custom types, you need to specify the variable name to be exactly the same as the key in the JSON document returned from the API. In case your variable name and key in JSON doc do not match, you can use @JsonProperty annotation to specify the exact key of the JSON document. (This example matches each variable name to a JSON key, so you do not need that annotation here.)

You also need an additional class, to embed the inner quotation itself. The Value record class fills that need and is shown in the following listing (at src/main/java/com/example/consumingrest/Value.java):

link:complete/src/main/java/com/example/consumingrest/Value.java[role=include]

This uses the same annotations but maps onto other data fields.

Finishing the Application

The Initializr creates a class with a main() method. The following listing shows the class the Initializr creates (at src/main/java/com/example/consumingrest/ConsumingRestApplication.java):

link:initial/src/main/java/com/example/consumingrest/ConsumingRestApplication.java[role=include]

Now you need to add a few other things to the ConsumingRestApplication class to get it to show quotations from our RESTful source. You need to add:

  • A logger, to send output to the log (the console, in this example).

  • A RestTemplate, which uses the Jackson JSON processing library to process the incoming data.

  • A CommandLineRunner that runs the RestTemplate (and, consequently, fetches our quotation) on startup.

The following listing shows the finished ConsumingRestApplication class (at src/main/java/com/example/consumingrest/ConsumingRestApplication.java):

link:complete/src/main/java/com/example/consumingrest/ConsumingRestApplication.java[role=include]

Finally, you need to set the server port. The quoters application uses the default server port, 8080, so this application cannot also use the same port. You can set the server port to 8081 by adding the following line to application properties (which the Initializr created for you):

server.port=8081

Running the Application

You should see output similar to the following but with a random quotation:

2019-08-22 14:06:46.506  INFO 42940 --- [           main] c.e.c.ConsumingRestApplication           : Quote{type='success', value=Value{id=1, quote='Working with Spring Boot is like pair-programming with the Spring developers.'}}
Note
If you see an error that reads, Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.consumingrest.Quote], it is possible that you are in an environment that cannot connect to the backend service (which sends JSON if you can reach it). Maybe you are behind a corporate proxy. Try setting the http.proxyHost and http.proxyPort system properties to values appropriate for your environment.

Summary

Congratulations! You have just developed a simple REST client by using Spring Boot.

gs-consuming-rest's People

Contributors

amriteya avatar andrii-kovalenko-celonis avatar bartoszmajsak avatar bclozel avatar btalbott avatar buzzardo avatar cbeams avatar gregturn avatar habuma avatar heaven31415 avatar jayeshjanyani avatar joshlong avatar p-g714 avatar pauldragoslav avatar robertmcnees avatar royclarkson avatar sdeleuze avatar shakuzen avatar spring-operator avatar tsuyo avatar yairm210 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gs-consuming-rest's Issues

Update Spring Boot version

Update the guide to use the most recent Spring Boot version.

To do so, update the Spring Boot version in:

initial/build.gradle
initial/pom.xml
complete/build.gradle
complete/pom.xml

Failed to execute CommandLineRunner

As the title says... I clone you repo, say "mvnw spring-boot:run" and... that is the exception I get after it doenwloaded and compiled the app.

This happens too if I build the projekt fresh with the Initializer and write every class myself.

There is one thing, though, I have to run "mvn wrapper:wrapper" before I can do anything, because this dev machine sits behind a company proxy. Would that be able to cause such an error?

Wrong word `Initalizr`

I found the word on line 111 in README.adoc.

The Initalizr creates a class with a `main()` method. The following listing shows the
class the Initializr creates (at
`src/main/java/com/example/consumingrest/ConsumingRestApplication.java`):

Can you fix initalizr to initialzr

Typo in pom.xml example

Hello,

There's a typo in the Maven import in the Maven file:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>

The "boot" package is missing here.

Error when building in SpringTool with Maven

Hello, this error happens on my side, and i don't have found a solution for this problem.

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-02-04 11:36:39.036 ERROR 276 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:787) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
	at com.example.consumingrest.ConsumingRestApplication.main(ConsumingRestApplication.java:18) ~[classes/:na]

Close down tomcat gracefully after completion of application.

After running this application a second time i get the following errors:

Verify the connector's configuration, identify and stop any process that's listening on port 8080, or configure this application to listen on another port.

Caused by: java.net.BindException: Address already in use
Caused by: org.apache.catalina.LifecycleException: service.getName(): "Tomcat"; Protocol handler start failed

There is no discussion on how to close down tomcat. Looking in the server window of Spring Tool Suite shows a tomcat server that is not running and not used by the application (obviously since its an embedded server). So you can not stop it there. I did find that I could stop the application clicking the red square showing in the attached image and then run the application again without error. I believe there should be a better way to run this application and shut it down gracefully.
sts stop application

Can't run the sample with no error

I tried running the sample application and it shows following error, so I guess there must be something missing, like setting the response type, because I think it should be "application/json".

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.0.RELEASE)

2016-09-23 16:55:10.563  INFO 12436 --- [           main] hello.Application                        : Starting Application on WANGZEN4 with PID 12436 (C:\Users\wangzen\git\gs-consuming-rest\complete\target\classes started by wangzen in C:\Users\wangzen\git\gs-consuming-rest\complete)
2016-09-23 16:55:10.566  INFO 12436 --- [           main] hello.Application                        : No active profile set, falling back to default profiles: default
2016-09-23 16:55:10.613  INFO 12436 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@be64738: startup date [Fri Sep 23 16:55:10 CST 2016]; root of context hierarchy
2016-09-23 16:55:11.429  INFO 12436 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-09-23 16:55:11.894  INFO 12436 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report enable debug logging (start with --debug)


2016-09-23 16:55:11.924 ERROR 12436 --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:801) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:782) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:769) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1185) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1174) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at hello.Application.main(Application.java:18) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class hello.Quote] and content type [text/html;charset="utf-8"]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:622) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at hello.Application.lambda$run$0(Application.java:29) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    ... 11 common frames omitted

2016-09-23 16:55:11.926  INFO 12436 --- [           main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@be64738: startup date [Fri Sep 23 16:55:10 CST 2016]; root of context hierarchy
2016-09-23 16:55:11.928  INFO 12436 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 1

Source code for Application.java (Standalone Version) does not compile

The example source code for the first version of the src/main/java/hello/Application.java (standalone version) does not contain the package declaration is is missing the imports as well. For that reason it does not compile directly.

Though fixing the file is not a big issue it might confuse java newbies and I suggest to replace the existing example source code with the following one that compiles without errors:

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;

public class Application {

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String args[]) {
        RestTemplate restTemplate = new RestTemplate();
        Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
    }
}

Text of guide refers incorrectly to Pivotal and Lombok

The guide says "If all you need to know are Pivotal’s name, phone number, website URL, and what the pivotalsoftware page is about, then the following domain class should do fine:", but the example being used is quotes about Spring Boot, not Pivotal's web page.

After the example domain class, Quote.java, it says "It also uses Project Lombok’s @DaTa annotation, which provides a getter, a setter, a toString, and other supporting methods." However, "@DaTa" is not used.

Two questions

Hello everyone,

I have completed the tutorial. However, two questions remain:

  1. Why does the application exposes a webservice on port 8080? I thought the application is a client that consumes an REST-API.
  2. What can the application do after the RESP-API's response is printed on the console? As far as I see, I cannot trigger to call the RESP-API again.

Thanks!

Jan

RestTemplate is being deprecated.

According to https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html:

NOTE: As of 5.0, the non-blocking, reactive org.springframework.web.reactive.client.WebClient offers a modern alternative to the RestTemplate with efficient support for both sync and async, as well as streaming scenarios. The RestTemplate will be deprecated in a future version and will not have major new features added going forward.

Anyone care to rewrite this guide for WebClient?

./gradlew build has FileNotFoundException

After successfully completing a few other guides (Building a RESTful Web Service, Building Java Projects with Gradle) then running ./gradlew build gives me a FileNotFoundException as seen in this gist: https://gist.github.com/kentoj/31ef5123d31712594c87

I am running the ./gradlew build command after the "Build an executable JAR" section.

The app runs correctly when I try to run it with java -jar build/libs/gs-consuming-rest-0.1.0.jar

Update: After hitting this issue with the 'consuming-rest' guide I did the actuator-service guide and I was successful in using ./gradlew build there.

Guide doesn't work in a plain IDE due to the use of Lombok

Without Lombok, there's no toString on Quote so the log message reads:

2015-09-22 16:04:29.475  INFO 54815 --- [           main] hello.Application                        : hello.Quote@7582ff54

There also aren't any setters so Jackson's unable to perform any binding. That means that you can't even see the values if you use a debugger.

IMO, we shouldn't use Lombok in the Guides. It's extra setup that people have to do, and also extra "magic" that people have to understand.

A bit of literal error

finishing-the-application
Original sentence:
The Initalizr creates a class with a main() method. The following listing shows the class the Initializr creates...

Revised sentence:
The initializer creates a class with a main() method. The following listing shows the class the initializer creates...

error 403 forbidden

when i try to build the sample app with gradle i get an error 403 forbidden

here is the stacktrace

14:48:40.048 [main] DEBUG o.s.web.client.RestTemplate - Created GET request for "http://graph.facebook.com/pivotalsoftware"
14:48:40.080 [main] DEBUG o.s.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json]
14:48:40.547 [main] DEBUG o.s.web.client.RestTemplate - GET request for "http://graph.facebook.com/pivotalsoftware" resulted in 403 (Forbidden); invoking error handler
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:614)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:570)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:530)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
at hello.Application.main(Application.java:13)
:run FAILED

i hope you can help me

quoters is down

Tried to run the example but not working just realized gturnquist-quoters is down, not sure if there is a mirror for this API or hosted somewhere else to update your example.

Caused by: org.springframework.web.client.HttpClientErrorException$NotFound: 404 Not Found: [404 Not Found: Requested route ('gturnquist-quoters.cfapps.io') does not exist

Port already in use due to local quoters

I tried to run this example with quoters running locally as well - as suggested in "Fetching a REST Resource". The (consumer) application failed to start due to Web server failed to start. Port 8080 was already in use.

IMHO there is no reason why this consumer application should fire up a web server.

Thus the solution for me was to change the main method to

new SpringApplicationBuilder(GsConsumingRestApplication.class)
	.web(WebApplicationType.NONE) // .REACTIVE, .SERVLET
	.run(args);

Would it be okay to include this in the repo?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.