- Helidon SE WebClient Guide
This guide describes how to create a sample Helidon SE project that can be used to run some basic examples using WebClient.
What you need
For this 15 minute tutorial, you will need the following:
| Java SE 21 (Open JDK 21) | Helidon requires Java 21+ (25+ recommended). |
| Maven 3.8+ | Helidon requires Maven 3.8+. |
| Docker 18.09+ | If you want to build and run Docker containers. |
| Kubectl 1.16.5+ | If you want to deploy to Kubernetes, you need kubectl and a Kubernetes cluster (you can install one on your desktop). |
java -version
mvn --version
docker --version
kubectl version# On Mac
export JAVA_HOME=`/usr/libexec/java_home -v 21`
# On Linux
# Use the appropriate path to your JDK
export JAVA_HOME=/usr/lib/jvm/jdk-21WebClient Features
Helidon’s WebClient is used to perform HTTP REST requests to target endpoints and handle their responses.
WebClient provides the following features:
User-friendly: Every client and request is created by a builder pattern, so it improves readability and code maintenance.
Following redirects: The WebClient is able to follow the redirect chain and perform requests on the correct endpoint for you. You no longer have to point your client to the correct/final endpoint.
Tracing, metrics and security propagation: When you configure the Helidon WebServer to use tracing, metrics and security, the settings are automatically propagated to the WebClient and used during request/response.
For more information about the WebClient, please refer to the WebClient Introduction.
WebClient Usage
Create a sample SE project
Generate the project sources using the Helidon SE Maven archetype. The result is a simple project that can be used for the examples in this guide.
mvn -U archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-se \
-DarchetypeVersion=4.4.1 \
-DgroupId=io.helidon.examples \
-DartifactId=helidon-quickstart-se \
-Dpackage=io.helidon.examples.quickstart.seYou should now have a directory called helidon-quickstart-se.
cd helidon-quickstart-seThe Helidon quickstart is a greeting application supporting several HTTP requests such as GET and PUT. Using it will be time-saving for this exercise as it will allow us to modify the project to demonstrate some of the Webclient features and usability, rather than start from scratch.
The quickstart example utilizes WebClient solely for testing purposes, with the dependency configured under the test scope. To use WebClient within your application, remove the test scope from the dependency in the pom.xml.
test scope from WebClient dependency<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient</artifactId>
</dependency>Add ClientExample class
In io.helidon.examples.quickstart.se package, create a new class named ClientExample. This class will use the WebClient to send request to the greeting application.
public class ClientExample {
public static void main(String[] args) {
}
}Add the following code to the main method to create a WebClient instance. The builder approach allows you to create the WebClient with specific settings and improves the readability and simplicity of the code.
WebClient webClient = WebClient.builder()
.baseUri("http://localhost:8080")
.build();- The base URI of the outbound requests.
By default, the Helidon quickstart application runs on localhost:8080. If for some reason the host name or port number of the quickstart application is changed, make sure that the baseURI is also modified to reflect that change. Once built, the WebClient can be used to send a GET request to the greeting application.
ClientResponseTyped<String> response = webClient.get()
.path("/greet")
.request(String.class);
String entityString = response.entity();
System.out.println(entityString);- Create an HTTP GET request.
- Target endpoint path.
- Execute the request
- Return response entity handled as a String.
The path method appends /greet to the WebClient base URI which results to the request URI becoming http://localhost:8080/greet. The received response entity will be a greeting message and will be automatically handled as a String. If no specific type is set in the method request(), HttpClientResponse will be returned by default. This HttpClientResponse object contains response code, headers and entity.
Run the application
mvn packageThis command will create helidon-quickstart-se.jar in the target folder.
java -cp target/helidon-quickstart-se.jar io.helidon.examples.quickstart.se.MainOpen a new command prompt or terminal and run the ClientExample class you just created.
java -cp target/helidon-quickstart-se.jar io.helidon.examples.quickstart.se.ClientExample{"message":"Hello World!"}When the ClientExample finishes its execution, you can stop the Main class by pressing CTRL+C.
Discover other WebClient functionality
In practice, String is not the most useful return type, since it usually needs some more handling. In this case, it could be more interesting to return an object of another type like a JSON object. One way to process a JSON object is by enabling Helidon’s built-in JSON-P support and this can be simply achieved by adding its dependency in the project’s pom.xml:
<dependency>
<groupId>io.helidon.http.media</groupId>
<artifactId>helidon-http-media-jsonp</artifactId>
</dependency>Once the dependency is added, the feature will be automatically loaded as a service allowing the response methods to easily parse the JSON object.
ClientResponseTyped<JsonObject> response = webClient.get()
.path("/greet/David")
.request(JsonObject.class);
String value = response.entity().getString("message");
System.out.println(value);- Request a JsonObject as return value.
- Extract the value of the JsonObject with name of
message.
In the URI, the String value following greet is a path parameter which allows the application to greet someone.
Hello David!It is also possible to change the greeting word by using a PUT request to /greet/greeting path. The request also needs to include a body with JSON type and using a structure like {"greeting" : "value"}.
JsonObject entity = Json.createObjectBuilder()
.add("greeting", "Bonjour")
.build();
webClient.put()
.path("/greet/greeting")
.submit(entity);
ClientResponseTyped<JsonObject> response = webClient.get()
.path("/greet/David")
.request(JsonObject.class);
String entityString = response.entity().getString("message");
System.out.println(entityString);- Create a JsonObject with key
greetingand valuebonjour. - Create a PUT request.
- Submit the JsonObject created earlier.
- Execute a GET call to verify that the greeting has been changed.
- Retrieve the greeting message from the JSON object
Executing the above code will yield this output showing that the greeting word has been changed.
Bonjour David!WebClient Metrics
WebClient, like other Helidon components, supports Metrics. The following example introduces a counter metric that can be used to measure WebClient request activity. There are two ways to set up metrics, programmatically on the WebClient instance or manually using the configuration file.
Add metrics dependency
To enable support for this feature, the helidon-webclient-metrics dependency needs to be added .
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient-metrics</artifactId>
</dependency>Set up metrics on WebClient instance
Metrics can be registered on the WebClient directly. The following example shows how a Counter metric can be defined, created and monitored.
MeterRegistry METER_REGISTRY = Metrics.globalRegistry();
String metricName = "counter.GET.localhost";
Counter counter = METER_REGISTRY.getOrCreate(Counter.builder(metricName));
System.out.println(metricName + ": " + counter.count());
WebClientService clientServiceMetric = WebClientMetrics.counter()
.methods(Method.GET) // OPTIONAL
.success(true) // OPTIONAL
.errors(true) // OPTIONAL
.description("Metric Description") // OPTIONAL
.nameFormat("counter.%1$s.%2$s")
.build(); - Specify the metric name.
- From the
MeterRegistry, create a Counter metric using the specified metric name. - Specify how the name of the metric will be generated using the
nameFormat. - Build a WebClient Metric Service that can count number of GET requests made.
In this example, the metric uses a Counter to measure the number of GET requests executed on the localhost. The format strings in the parameter value of nameFormat method will identify how the name of a metric will get generated:
%1$s= Request method%2$s= Request host%3$s= Response status
So for example, if the nameFormat value is metric.%1$s.%2$s.%3$s and a request uses a GET method, targeting a URL with localhost as the hostname, and got a response code of 200, that the final metric will get created with a name of metric.GET.localhost.200.
To register the metric service, simply use the addService method and pass in the created WebClient Metric Service as a parameter.
WebClient webClient = WebClient.builder()
.baseUri("http://localhost:8080")
.addService(clientServiceMetric)
.build();
webClient.get().path("/greet").request(); - Register the metric service to the webclient.
- Send an HTTP GET request
To verify that the metric is set up correctly, print the value of the Counter at the end of the main method.
System.out.println(metricName + ": " + counter.count());This will result to an output showing that a metric with the name of counter.GET.localhost was created with a count value of 1 indicating that it correctly measured the request that was just made.
counter.GET.localhost: 1Set up metrics with configuration files
Using the configuration file can reduce the code complexity and make the metrics simpler to use. With this approach, it eliminates the need to modify the source code for scenarios where the metric settings have to be changed. The application.yaml file is the default configuration file for Helidon and can be used to set up metrics settings.
client:
services:
metrics:
- type: COUNTER
methods: ["GET"]
description: "Metric Description"
name-format: "counter.%1$s.%2$s"In the example configuration definition above, the metrics configuration are located under client.services.metrics. The metric setting can start either by its type or methods. The configuration file uses the same keywords as the programmatic way. For example, type defines the kind of metric and methods identifies the http methods that will be measured.
MeterRegistry METER_REGISTRY = Metrics.globalRegistry();
String counterName = "counter.GET.localhost";
Counter counter = METER_REGISTRY.getOrCreate(Counter.builder(counterName));
System.out.println(counterName + ": " + counter.count());
Config config = Config.create();
WebClient webClient = WebClient.builder()
.baseUri("http://localhost:8080")
.config(config.get("client"))
.build();
webClient.get().path("/greet").request();
System.out.println(counterName + ": " + counter.count()); - Choose the metric name.
- Create counter metric from
MeterRegistry. - Create a Helidon Config instance from default config file
application.yaml. - Configure the WebClient using the
clientsection fromapplication.yaml. - Send an HTTP GET request
- Print out the metric result
As demonstrated, using the configuration file reduces the amount of code needed in the source code. For more information about metrics, see the Helidon Metrics Guide.