-
Notifications
You must be signed in to change notification settings - Fork 3k
Add REST Client guide #791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
= {project-name} - Using the REST Client | ||
|
||
This guide explains how to use the MicroProfile REST Client in order to interact with REST APIs | ||
with very little effort. | ||
|
||
== Prerequisites | ||
|
||
To complete this guide, you need: | ||
|
||
* less than 15 minutes | ||
* an IDE | ||
* JDK 1.8+ installed with `JAVA_HOME` configured appropriately | ||
* Apache Maven 3.5.3+ | ||
|
||
Remember, you need to configure Maven as indicated in the link:maven-config.html[Maven configuration page]. | ||
|
||
== Solution | ||
|
||
We recommend you to follow the instructions in the next sections and create the application step by step. | ||
However, you can go right to the completed example. | ||
|
||
Clone the Git repository: `git clone https://github.com/jbossas/protean-quickstarts.git`, or download an https://github.com/jbossas/protean-quickstarts/archive/master.zip[archive]. | ||
|
||
The solution is located in the `rest-client` directory. | ||
|
||
== Creating the Maven project | ||
|
||
First, we need a new project. Create a new project with the following command: | ||
|
||
[source, subs=attributes+] | ||
---- | ||
mvn org.jboss.shamrock:shamrock-maven-plugin:{shamrock-version}:create \ | ||
-DprojectGroupId=org.acme \ | ||
-DprojectArtifactId=rest-client \ | ||
-DclassName="org.acme.restclient.CountriesResource" \ | ||
-Dpath="/country" \ | ||
-Dextensions="rest-client, jaxrs-json" | ||
---- | ||
|
||
This command generates the Maven project with a REST endpoint and imports the `rest-client` and `jaxrs-json` extensions. | ||
|
||
|
||
== Setting up the model | ||
|
||
In this guide we will be demonstrating how to consume part of the REST API supplied by the link:https://restcountries.eu[restcountries.eu] service. | ||
Our first order of business is to setup the model we will be using, in the form of a `Country` POJO. | ||
|
||
Create a `src/main/java/org/acme/restclient/Country.java` file and set the following content: | ||
|
||
[source,java] | ||
---- | ||
package org.acme.restclient; | ||
|
||
import java.util.List; | ||
|
||
public class Country { | ||
|
||
private String name; | ||
private String alpha2Code; | ||
private String capital; | ||
private List<Currency> currencies; | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getAlpha2Code() { | ||
return alpha2Code; | ||
} | ||
|
||
public void setAlpha2Code(String alpha2Code) { | ||
this.alpha2Code = alpha2Code; | ||
} | ||
|
||
public String getCapital() { | ||
return capital; | ||
} | ||
|
||
public void setCapital(String capital) { | ||
this.capital = capital; | ||
} | ||
|
||
public List<Currency> getCurrencies() { | ||
return currencies; | ||
} | ||
|
||
public void setCurrencies(List<Currency> currencies) { | ||
this.currencies = currencies; | ||
} | ||
|
||
public static class Currency { | ||
private String code; | ||
private String name; | ||
private String symbol; | ||
|
||
public String getCode() { | ||
return code; | ||
} | ||
|
||
public void setCode(String code) { | ||
this.code = code; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getSymbol() { | ||
return symbol; | ||
} | ||
|
||
public void setSymbol(String symbol) { | ||
this.symbol = symbol; | ||
} | ||
} | ||
|
||
} | ||
---- | ||
|
||
The model above in only a subset of the fields provided by the service, but it suffices for the purposes of this guide. | ||
|
||
== Create the interface | ||
|
||
Using the MicroProfile REST Client is as simple as creating an interface using the proper JAX-RS and MicroProfile annotations. In our case the interface should be created at `src/main/java/org/acme/restclient/CountriesService.java` and have the following content: | ||
|
||
[source, java] | ||
---- | ||
package org.acme.restclient; | ||
|
||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; | ||
|
||
import javax.ws.rs.GET; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.PathParam; | ||
import javax.ws.rs.Produces; | ||
import java.util.Set; | ||
|
||
@Path("/v2") | ||
@RegisterRestClient | ||
public interface CountriesService { | ||
|
||
@GET | ||
@Path("/name/{name}") | ||
@Produces("application/json") | ||
Set<Country> getByName(@PathParam("name") String name); | ||
} | ||
---- | ||
|
||
The `getByName` method gives our code the ability to query a country by name from the REST Countries API. The client will handle all the networking and marshalling leaving our code clean of such technical details. | ||
|
||
The purpose of the annotations in the code above is the following: | ||
|
||
* `@RegisterRestClient` allows {project-name} to know that this interface is meant to be used as a REST Client | ||
* `@Path`, `@GET` and `@PathParam` are the standard JAX-RS annotations used to define how to access the service | ||
* `@Produces` defines the expected content-type | ||
|
||
[NOTE] | ||
==== | ||
While `@Consumes` and `@Produces` are optional as auto-negotiation is supported, | ||
it is heavily recommended to annotate your endpoints with them to define precisely the expected content-types. | ||
|
||
It will allow to narrow down the number of JAX-RS providers (which can be seen as converters) included in the native image. | ||
==== | ||
|
||
== Create the configuration | ||
|
||
In order to determine the base URL to which REST calls will be made, the REST Client uses configuration from `META-INF/microprofile-config.properties`. | ||
The name of the property needs to follow a certain convention which is best displayed in the following code: | ||
|
||
[source] | ||
---- | ||
# Your configuration properties | ||
org.acme.restclient.CountriesService/mp-rest/url=https://restcountries.eu/rest | ||
---- | ||
|
||
Having this configuration means that all requests performed using `org.acme.restclient.CountriesService` will use `https://restcountries.eu/rest` as the base URL. | ||
|
||
Note that `org.acme.restclient.CountriesService` _must_ match the fully qualified name of the `CountriesService` interface we created in the previous section. | ||
|
||
Using the configuration above, calling the `getByName` method of `CountriesService` with a value of `France` would result in an HTTP GET request being made to `https://restcountries.eu/rest/v2/name/France`. | ||
|
||
== Update the JAX-RS resource | ||
|
||
Open the `src/main/java/org/acme/restclient/CountriesResource.java` file and update it with the following content: | ||
|
||
[source,java] | ||
---- | ||
import org.eclipse.microprofile.rest.client.inject.RestClient; | ||
|
||
import javax.inject.Inject; | ||
import javax.ws.rs.GET; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.PathParam; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.core.MediaType; | ||
import java.util.Set; | ||
|
||
@Path("/country") | ||
public class CountriesResource { | ||
|
||
@Inject | ||
@RestClient | ||
private CountriesService countriesService; | ||
|
||
|
||
@GET | ||
@Path("/name/{name}") | ||
@Produces(MediaType.APPLICATION_JSON) | ||
public Set<Country> name(@PathParam("name") String name) { | ||
return countriesService.getByName(name); | ||
} | ||
} | ||
---- | ||
|
||
Note that in addition to the standard CDI `@Inject` annotation, we also need to use the MicroProfile `@RestClient` annotation to inject `CountriesService`. | ||
|
||
== Update the test | ||
|
||
We also need to update the functional test to reflect the changes made to the endpoint. | ||
Edit the `src/test/java/org/acme/restclient/CountriesResourceTest.java` file and change the content of the `testCountryNameEndpoint` method to: | ||
|
||
|
||
[source, java] | ||
---- | ||
package org.acme.restclient; | ||
|
||
import org.jboss.shamrock.test.junit.ShamrockTest; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static io.restassured.RestAssured.given; | ||
import static org.hamcrest.CoreMatchers.is; | ||
|
||
@ShamrockTest | ||
public class CountriesResourceTest { | ||
|
||
@Test | ||
public void testCountryNameEndpoint() { | ||
given() | ||
.when().get("/country/name/greece") | ||
.then() | ||
.statusCode(200) | ||
.body("$.size()", is(1), | ||
"[0].alpha2Code", is("GR"), | ||
"[0].capital", is("Athens"), | ||
"[0].currencies.size()", is(1), | ||
"[0].currencies[0].name", is("Euro") | ||
); | ||
} | ||
|
||
} | ||
---- | ||
|
||
geoand marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
The code above uses link:http://rest-assured.io/[REST Assured]'s link:https://github.com/rest-assured/rest-assured/wiki/GettingStarted#jsonpath[json-path] capabilities. | ||
|
||
== Package and run the application | ||
|
||
Run the application with: `mvn compile shamrock:dev`. | ||
Open your browser to http://localhost:8080/country/name/greece. | ||
|
||
You should see a JSON object containing some basic information about Greece. | ||
|
||
As usual, the application can be packaged using `mvn clean package` and executed using the `-runner.jar` file. | ||
You can also generate the native executable with `mvn clean package -Pnative`. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.