Helidon Basics

3
0
Send lab feedback

Helidon Basic Lab

About Oracle Helidon

Helidon provides an open source, lightweight, fast, reactive, cloud native framework for developing Java microservices.

The framework supports two programming models for writing microservices:

  • Helidon SE is designed to be a microframework that supports the reactive programming model,

  • Helidon MP, on the other hand, is an Eclipse MicroProfile runtime that allows the Jakarta EE community to run microservices in a portable way. MicroProfile contains features like Metrics, Health Check, Streams Operators, Open Tracing, OpenAPI, REST client, and fault tolerance. You can find detailed information about MicroProfile on the Eclipse MicroProfile site.

Helidon microservice is a lightweight Java SE application with minimum dependency requirement, fast startup time and outstanding performance.

STEP 1: Create projects

  1. Create workspace directory for Eclipse.

    On the desktop right click and select Terminal Emulator or click on the desktop menu and select Terminal Emulator.

    In the Terminal Emulator create a folder.

    mkdir workspace

    Change to the directory.

    cd ~/workspace

  2. Generate the projects.

    Copy and paste the following maven command to download the Helidon Quickstart SE projects. Press Enter.

    mvn -U archetype:generate -DinteractiveMode=false \
        -DarchetypeGroupId=io.helidon.archetypes \
        -DarchetypeArtifactId=helidon-quickstart-se \
        -DarchetypeVersion=2.3.0 \
        -DgroupId=io.helidon.examples \
        -DartifactId=helidon-quickstart-se \
        -Dpackage=io.helidon.examples.quickstart.se

    Copy and paste the following maven command to download the Helidon Quickstart MP projects. Press Enter.

    mvn -U archetype:generate -DinteractiveMode=false \
        -DarchetypeGroupId=io.helidon.archetypes \
        -DarchetypeArtifactId=helidon-quickstart-mp \
        -DarchetypeVersion=2.3.0 \
        -DgroupId=io.helidon.examples \
        -DartifactId=helidon-quickstart-mp \
        -Dpackage=io.helidon.examples.quickstart.mp

You can continue to the next step.

STEP 2: Sanity check

  1. Check the SE project (helidon-quickstart-se) is working. In the Terminal Emulator already opened, enter the following to start the application.

    cd ~/workspace/helidon-quickstart-se
    mvn clean package
    java -jar target/helidon-quickstart-se.jar  

    Note

    You can cut and paste multiple command line.

  2. Lets check the application in running successfully. Open a new tab in your web browser and enter the following URL.

    http://localhost:8080/greet

    The browser page should look something like this.

  3. Stop the application by going to the Terminal Emulator where the application is running and press Ctrl+C to stop the process.

  4. Check the MP project (helidon-quickstart-mp) is working. In the Terminal Emulator enter the following to start the application.

    cd ~/workspace/helidon-quickstart-mp
    mvn clean package
    java -jar target/helidon-quickstart-mp.jar
    
  5. Check the application is running successfully using a different method this time, the command curl. Start a new Terminal Emulator and enter the following.

    curl http://localhost:8080/greet

    The output should look like.

  6. Stop the Java application. Go to the Terminal Emulator where the application is running and press Ctrl+C to stop the process.

You can continue to the next step.

STEP 3: Import the projects into Eclipse

To build the applications you will use the widely adopted Eclipse IDE (Integrated Development Enviroment).

You will import the application in to Eclipse.

  1. Launch Eclipse by double click on the Eclipse IDE icon on the desktop.

    Click browse and select the folder /home/luna.user/workspace and click Launch.

  2. Close the Welcome tab to navigate to the Package Explorer.

  3. Import the following projects in to Eclipse.

    1. helidon-quickstart-se (SE project)
    2. helidon-quickstart-mp (MP project)

    From the menu bar, select File -> Import then in the import window select Maven -> Existing Maven Projects and click Next.

    Select /home/luna.user/workspace/helidon-quickstart-se and click Finish.

    If may see an error or warnings, you can ignore it for now, click Finish.

    You have successfully imported the package.

  4. Repeat the import steps for the MP project. The project is at /home/luna.user/workspace/helidon-quickstart-mp folder.

How to resolve the Jandex/Maven issue

Let resolve the Jandex/Maven issue for helidon-quickstart-mp.

  1. Change the notification of Maven in the Eclypse preferences.

    Open Window -> Preferences and select Maven -> Errors/Warnings and change notifications Plugin execution not covered by lifecycle configuration from Error to Warning.

    Clcik Apply and close and then Yes.

  2. The Error now becomes a warning message.

Now the applications are imported and ready to develop.

You can continue to the next step.

STEP 4: Using config

Using Eclipse, take a look at Main.java in the SE project. Helidon SE is the core version of Helidon that requires almost everything to be done manually.

However it is smaller and faster compared not just to MP but to other microservices frameworks.

In the MP project there is no Main.java or starter class. Technically, the main class is not needed unless you want to control the startup sequence.

In the following steps you will create this main class to change default configuration source and order.

But in case of SE the main class already contains several configuration elements to activate built in features and the custom logic.

However to start a simple server using Config is not a big deal, but comparing to MP requires few more lines.

The other main difference is the implementation of the Greet service endpoint.

In case of MP it is a well known JAX-RS using annotations (see GreetResource.java).

Simple coding and the framework does the rest of the job.

While SE requires Routing definition where the service (see GreetService.java) which takes care about the response is registered. Functional, controlled, lightweight and streamlined API usage.

Using Config

The config component provides a Java API to load and process configuration properties from various sources into a Config object which the application can use to retrieve config data.

The system reads configuration from a config source, a physical location (such as a file, a URL, or a String) which holds config data.

Each config source works with a config parser which translates a particular text format (for example, Java properties or YAML) into an in-memory tree which represents the configuration’s structure and values.

An optional polling strategy detects and publishes changes to the underlying config source so the config source itself or your application can respond.

Your application uses the Config object which results from building that in-memory tree to retrieve config data. The app can navigate explicitly among the nodes in the tree and fetch a node’s value. The Config object lets your application retrieve config data as a typed ConfigValue.

The default config uses the following config sources:

  1. System properties config source
  2. Environment variables config source
  3. A classpath config source called application.? where the ? depends on supported media types currently on the classpath. By default it is properties, if you have YAML support on classpath, it would be application.yaml (a ConfigParser may add additional supported suffixes for default file)

The priority (most to least important) means that if a given config key appears in more than one source, the value assigned in a more important source overrules the value from a less important source.

In this step we will modify the applications so they run on different ports.

  1. Modify the MP project to run on a different port.

    Open src/main/resources -> META-INF folder. Double click on the file microprofile-config.properties and change the server.port number 8080 to 8081, save the config file.

  2. To run the MP application from Eclipse and adding custom server start and/or configuration we need to implement main class or starter class.

    Create main class in the io.helidon.examples.quickstart.mp package.

    Right click on the project and select New -> Class.

    Enter the name of this class as Main (Capital M), click finish.

  3. Replace the content with the following code.

    package io.helidon.examples.quickstart.mp;
    
    import io.helidon.microprofile.server.Server;
    import java.io.IOException;
    
    public final class Main {
    
        private Main() { }
    
        public static void main(final String[] args) throws IOException {
            Server server = startServer();
            System.out.println("http://localhost:" + server.port() + "/greet")   ;
        }
    
        static Server startServer() {
            return Server.builder()
                .build()
                .start();
        }
    }

    Your Main.java content should look like this.

  4. Start the application using the Main.class.

    Right click on Main.java and select Run As -> Java Application.

  5. Check the application is running.

    Go to your web browser and enter the following URL.

    http://localhost:8081/greet

    The application is running successfully with the new port number.

You can continue to the next step.

STEP 5: Configuration sources, change support

After using the default config file, now customise the configuration on both projects.

Modify the MP project

  1. For MP project create the mp-config.yaml config file in the resources folder.

  2. Right click on src/main/resources and select New -> Other...

    Select General -> File and click Next.

    Enter file name as mp-config.yaml and click finish.

    The extention yaml is not reccognised in Eclipse, lets install the extention. Click OK.

    Click install.

    Accept the agreement.

    Accept the certificate click Accept selected.

    Restart Eclipse and click close.

    When you have restarted Eclipse, open the yaml file you created earlier.

  3. Copy and paste the following content into the new file and save it.

    app:
     greeting: "Hello Helidon MP from YAML config"

  4. In the Package Explorer tab open src/main/java -> io.helidon.examples.quickstart.mp, open the Main.java file.

    In the Main class add a new buildConfig method which reads the new config file.

    private static Config buildConfig() {
        return Config.builder()
            .disableEnvironmentVariablesSource()
            .sources(
                classpath("mp-config.yaml").optional(),
                classpath("META-INF/microprofile-config.properties"))
            .build();
    }

    Change server startup to.

        return Server.builder()
            .config(buildConfig())
            .build()
            .start();

    If the IDE can't offer the missing import packages then add the following import packages.

    import io.helidon.config.Config;
    import static io.helidon.config.ConfigSources.classpath;

    The Main.java should look like this.

  5. Now, run the MP application using Main.java and check the result.

    In the web browser enter the following URL.

    http://localhost:8081/greet

    You should see the following message.

  6. Modify the greeting message in the mp-config.yaml file and save.

    greeting: "Hello Helidon MP from YAML config 2"

  7. Refresh the web browser to view the change.

Modify the SE project

Now modify the SE application but here register polling to watch config file changes.

Due to the polling the application will pick up the configuration changes in the file without the application restart.

However this requires external configuration file.

  1. Create the se-config.properties config file in the SE project resources folder.

    In the SE project right click on src/main/resources, select New -> Other than select General -> File and click Next.

    Enter the following as name.

    se-config.properties

    Copy and paste the following content and save.

    app.greeting=Hello Helidon SE
  2. In the Package Explorer tab select src/main/java -> io.helidon.examples.quickstart.se, open the Main.java file.

    In the Main class add a new buildConfig method which reads the new config file.

    private static Config buildConfig() {
    
        return Config
                .builder()
                // specify config sources
                .sources(file("/home/luna.user/workspace/helidon-quickstart-se/src/main/resources/se-config.properties")
                    .pollingStrategy(regular(Duration.ofSeconds(1))),
                         classpath("application.yaml"))
                .build();
    }

    If the IDE can't offer the missing import packages then copy from here.

    import static io.helidon.config.ConfigSources.file;
    import static io.helidon.config.ConfigSources.classpath;
    import static io.helidon.config.PollingStrategies.regular;
    import java.time.Duration;
  3. Find the default config creation in the startServer method and replace with the new buildConfig method.

    Find the line Config config = Config.create(); and replace with the following.

    Config config = buildConfig();

    The Main.java should look like similar:

  4. To reflect the runtime config changes modify the GreetService class.

  5. Add the following package.

    import java.util.function.Supplier;

  6. Open the class and replace the line

    private final AtomicReference greeting = new AtomicReference<>();

    with the following.

    private Supplier<String> greetingSupplier;

  7. Modify the constructor GreetService method to set supplier instead of the greeting member.

    replace the line

    greeting.set(config.get("app.greeting").asString().orElse("Ciao"));

    with the following.

    greetingSupplier = config.get("app.greeting").asString().supplier("Ciao");

  8. Use the supplier in the sendResponse method (replace the line where is the error):

    replace the line

    String msg = String.format("%s %s!", greeting.get(), name);

    with the following.

    String msg = String.format("%s %s!", greetingSupplier.get(), name);

  9. Finally in the updateGreetingFromJson method use the supplier instead of the old greeting variable (replace the line where is the error).

    replace the line

    greeting.set(jo.getString("greeting"));

    with the following.

    greetingSupplier = () -> jo.getString("greeting");

  10. Check your GreetService class.

  11. Run the SE application using Main.java and check the output.

    Once the application is running successfully, in the web browser enter the URL.

    http://localhost:8080/greet

    You should see the output as.

  12. Change the se-config.properties config file greeting property.

    app.greeting=Hello Helidon SE from YAML config 2
  13. Save the changes and refresh the browser, press F5.

    You should see the output as.

    You can continue to the next step.

STEP 6: Metrics

Helidon provides the following to support metrics.

  1. The endpoint /metrics.

    A configurable endpoint that exposes metrics information in JSON format (as specified by the MicroProfile Metrics specification) or in plain text (for Prometheus metrics).

    Check the plain text using a browser.

    http://localhost:8081/metrics

    For JSON result use curl:

    curl -s -H 'Accept: application/json' -X GET http://localhost:8081/metrics/

  2. A base set of metrics available at /metrics/base, as specified by the MicroProfile Metrics specification.

  3. A set of Helidon-specific metrics, available at /metrics/vendor

    See the plain text result using your browser.

    http://localhost:8081/metrics/vendor

Add custom metrics

In case of MP it is basically just an annotation.

  1. Add the following annotation to the getDefaultMessage method in the io.helidon.examples.quickstart.mp.GreetResource class and save the changes.

  2. In the io.helidon.examples.quickstart.mp.GreetResource class add the package.

    import org.eclipse.microprofile.metrics.annotation.Timed;
    import org.eclipse.microprofile.metrics.annotation.Counted;
    

    Add the following annotation to the getDefaultMessage method and save the changes.

    @Timed
    @Counted(name = "my-mp-metrics", absolute = true)

  3. Stop the running application if necessary and run again Main.java in MP project.

    Click on the console and then terminate.

  4. Check the output in your browser.

    http://localhost:8081/metrics/application/my-mp-metrics

    Refresh the greet application a few times

    http://localhost:8081/greet

    Check again and the value of the counter have changed.

  5. The configured method is another metric type available for Prometheus

    http://localhost:8081/metrics/application/io.helidon.examples.quickstart.mp.GreetResource.getDefaultMessage

    These are history/summary and gauge type metrics.

In SE project we need to do more coding.

  1. Add metric support to GreetService.java in the constructor. Also create defaultMessageCounter member to store the actual value:

  2. In the io.helidon.examples.quickstart.se class add the the following packages.

    import org.eclipse.microprofile.metrics.Counter;
    import org.eclipse.microprofile.metrics.MetricRegistry;
    import io.helidon.metrics.RegistryFactory;

    Add defaultMessageCounter member to store the actual value.

    private final Counter defaultMessageCounter;

    Add metric support when calling GreetService.

      RegistryFactory metricsRegistry = RegistryFactory.getInstance();
      MetricRegistry appRegistry = metricsRegistry.getRegistry(MetricRegistry.Type.APPLICATION);
      defaultMessageCounter = appRegistry.counter("my-se-metrics");

    Increment the counter value when calling getDefaultMessageHandler.

    defaultMessageCounter.inc();

    Save the changes.

  3. Stop the SE application if necessary and run again using Main.java in SE project.

    Refresh the page http://localhost:8080/greet a few times and check the metrics at

    http://localhost:8080/metrics/application/my-se-metrics

Use Prometheus to monitor metrics

Prometheus is an open-source systems monitoring and alerting toolkit. Its main feature is the multi-dimensional data model with time series data identified by metric name and key/value pairs.

In the following steps you will download and run Prometheus.

  1. Download the setup script.

    In a terminal run the following command.

    curl -LSs https://raw.githubusercontent.com/nagypeter/helidon-tutorial/master/scripts/setup.prometheus.sh | bash
  2. Once the script has finished in a new browser tab enter the following URL.

    http://localhost:9090
    

  3. Start typing "my" in the expression field, select the counter application_my_mp_metrics_total and click Execute to add this metrics to the panel.

  4. You can see the current value in the table view, click on the Graph tab for the graph view.

  5. To increase the value hit the http://localhost:8081/greet refresh button F5 a few times.

    You can play and check with other metrics.

You can continue to the next step.

STEP 7: Health checks

It’s a good practice to monitor your microservice’s health, to ensure that it is available and performs correctly.

Applications implement health checks to expose health status that is collected at regular intervals by external tooling, such as orchestrators like Kubernetes.

The orchestrator may then take action, such as restarting your application if the health check fails.

A typical health check combines the statuses of all the dependencies that affect availability and the ability to perform correctly:

  • network latency
  • storage
  • database
  • other services used by your application

MP Health checks

Helidon MP implements the MicroProfile Health specification. The specification prescribes how external tools probe a service’s health checks and how you implement health checks as part of your microservice that are specific to your service’s needs.

Helidon provides built-in, default checks for each endpoint. The built-in liveness checks include various environmental values, such as whether the JVM has detected deadlocks or whether there is sufficient heap space.

The built-in readiness check always reports UP.

Check by using the built-in health status.

http://localhost:8081/health

The output should look like this.

MicroProfile Health supports two types of health checks:

  • Liveness checks report whether the runtime environment in which the service is running is sufficient to support the work the service performs.

    The environment is beyond the control of the service itself and typically cannot improve without outside intervention.

    If a microservice instance reports a DOWN liveness check, it should never report UP later. It will need to be stopped and a replacement instance created.

  • Readiness checks report whether the service is currently capable of performing its work.

    A service that reports DOWN for its readiness cannot at the moment do its job, but at some future point it might become able to do so without requiring a restart.

MP Liveness Health Check

In this step you will add a custom liveness health check

  1. Create a new class in io.helidon.examples.quickstart.mp package.

    Right click on the io.helidon.examples.quickstart.mp package, select New -> Class and enter name as

    GreetLivenessCheck
  2. Copy the content below and overwrite the content in the new class then save the changes.

    package io.helidon.examples.quickstart.mp;
    
    import javax.enterprise.context.ApplicationScoped;
    import org.eclipse.microprofile.health.HealthCheck;
    import org.eclipse.microprofile.health.HealthCheckResponse;
    import org.eclipse.microprofile.health.Liveness;
    
    @Liveness
    @ApplicationScoped
    public class GreetLivenessCheck implements HealthCheck {
    
    	@Override
    	public HealthCheckResponse call() {
    		return HealthCheckResponse.named("MyMPLivenessCheck").up().withData("time", System.currentTimeMillis()).build();
    	}
    }

    Note

    This check doesn't do a real check just demonstrates the place and method for such custom action. It only shows the current time and return UP status always.

  3. Stop the MP application if necessary and run again.

  4. Check the health status again, refresh the browser with the URL http://localhost:8081/health .

MP Readiness Health Check

Here you will add a custom readiness health check.

  1. Create a new class in io.helidon.examples.quickstart.mp package.

    Right click on the io.helidon.examples.quickstart.mp package, select New -> Class and enter name as

    GreetReadinessCheck
  2. Copy the content below and overwrite the content in the new class then save the changes.

    package io.helidon.examples.quickstart.mp;
    
    import java.time.Duration;
    import java.util.concurrent.atomic.AtomicLong;
    import javax.enterprise.context.ApplicationScoped;
    
    import javax.enterprise.context.Initialized;
    import javax.enterprise.event.Observes;
    import org.eclipse.microprofile.health.HealthCheck;
    import org.eclipse.microprofile.health.HealthCheckResponse;
    import org.eclipse.microprofile.health.Readiness;
    
    @Readiness
    @ApplicationScoped
    public class GreetReadinessCheck implements HealthCheck {
      private AtomicLong readyTime = new AtomicLong(0);
    
    
      @Override
      public HealthCheckResponse call() {
        return HealthCheckResponse.named("MyMPReadinessCheck")  
            .state(isReady())
            .withData("time", readyTime.get())
            .build();
      }
    
      public void onStartUp(
          @Observes @Initialized(ApplicationScoped.class) Object init) {
        readyTime = new AtomicLong(System.currentTimeMillis());
      }
    
      /**
       * Become ready after 10 seconds
       *
       * @return true if application ready
       */
      private boolean isReady() {
        return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 10;
      }
    }

    Note

    This check also doesn't do any check but what is important here is the application needs time to start properly. To demonstrate this delay the isReady method return true after 10 seconds of the application start.

  3. Restart the application and then immediatly refresh the browser with the URL http://localhost:8081/health .

    You should see MyMPReadinessCheck state as DOWN.

    After a few seconds refresh the browser again, you should see the state of the MyMPReadinessCheck has changed.

SE Health checks

In the case of SE it is still easy to add customer health check. Instead of annotation you build and register the HealthSupport.

To make it simpler the check is implemented in place without introducing a new class. This check will always return UP state and current time in millisecond as value.

The SE quickstart project already configured to produce built-in health check, you just need to add additional custom check.

  1. In io.helidon.examples.quickstart.se package modify the Main class.

    Add the package.

    import org.eclipse.microprofile.health.HealthCheckResponse;

    In the createRouting method, modify HealthSupport build, after the following lines

    HealthSupport health = HealthSupport.builder() .addLiveness(HealthChecks.healthChecks())

    add the following and save the changes.

    .addReadiness(() -> HealthCheckResponse.named("MySEReadinessCheck")
            .up()
            .withData("time", System.currentTimeMillis())
            .build())

    The complete HealthSupport build part should look like this:

  2. Stop the SE application and run again using Main.java.

    Check that the health information contains the new custome check:

You can continue to the next step.

STEP 8: Connect the services

In this example MP application will call the SE application's service. This communication is very common in microservices architecture.

MicroProfile Rest Client adds the capability to invoke remote microservices using a JAX-RS like interface to declare the operations.

Since you are dealing with remote object first you need to create a rest client interface.

A rest client interface can be annotated with @RegisterRestClient to automatically register it with CDI. The RegisterRestClient annotation has a property baseUri that can be used to define the base endpoint of this client.

In the interface you need to only define the necessary endpoints which is now the /greet/{name}.

  1. Go to io.helidon.examples.quickstart.mp package and create a new interface.

    Right click helidon-quickstart-mp select New -> Interface.

    Enter the interface name as

    GreetRestClient

    Click Finish.

    Note

    You are creating an interface not class!

  2. Replace the code with the following.

    package io.helidon.examples.quickstart.mp;
    
    import javax.json.JsonObject;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    
    import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
    
    @RegisterRestClient(baseUri="http://localhost:8080/greet")
    interface GreetRestClient {
    
         @GET
         JsonObject getDefaultMessage();
    
         @Path("/{name}")
         @GET
         JsonObject getMessage(@PathParam("name") String name);
    
    }

    By calling GreetRestClient.getMessage() you reach the endpoint of the SE application.

    Once a rest client interface is annotated, it can be injected into any CDI bean.

  3. Open GreetResource.java and add the following package.

    import org.eclipse.microprofile.rest.client.inject.RestClient;
  4. Add after the last method and save the changes.

    @Inject
    @RestClient
    GreetRestClient restClient;
    
    @GET
    @Path("/outbound/{name}")
    public JsonObject outbound(@PathParam("name") String name) {
       return restClient.getMessage(name);
    }

    This part injects the interface and define /outbound/{name} endpoint for MP application to invoke the REST call to the SE application.

    Usually the member declaration happens before the method(s) declaration but for easier understanding just copy together after the last method.

  5. Restart the MP application and test the outbound call.

    http://localhost:8081/greet/outbound/Jack

    {"message":"Hello Helidon SE from YAML config 2 Jack!"}

    You can see the SE application's message including the name appended to the outbound path as parameter.

You can continue to the next step.

STEP 9: Tracing

Helidon includes support for tracing through the OpenTracing APIs and is integrated with WebServer and Security. It also includes integration with Zipkin and Jaeger tracer tools.

This step will show you how to use Zipkin tracer tool.

Activate Tracing in SE Application

To activate tracing in SE application first add necessary libraries (dependencies) to the Maven project, pom.xml.

  1. Find the list and insert at the end the following elements then save the pom.xml.

            <dependency>
              <groupId>io.helidon.tracing</groupId>
              <artifactId>helidon-tracing</artifactId>
            </dependency>
            <dependency>
                <groupId>io.helidon.tracing</groupId>
                <artifactId>helidon-tracing-zipkin</artifactId>
            </dependency>

  2. Register the tracer in the webserver.

    Open Main.java and add the following package.

    import io.helidon.tracing.TracerBuilder;

    In the startServer method, after the line

    WebServer server = WebServer.builder(createRouting(config)) .config(config.get("server"))

    insert the following line and save the Main.java.

    .tracer(TracerBuilder.create(config.get("tracing")).build())

    The webserver creation should look like the following:

  3. In the application.yaml configuration file add tracing configuration element.

    Note

    It is enough to just set a name for the tracing service what will be displayed for this application in Zipkin. The other parameters can be default.

    Add the following at the end of the file.

    tracing:
      service: helidon-se

    Note

    Make sure there is no spaces before tracing and 2 spaces before service.

  4. Save the application.yaml and restart the SE application.

Activate Tracing in MP Application

  1. Open the helidon-quickstart-mp package.

    Add the tracing dependency (Zipkin) to the MP application's pom.xml and save the changes.

            <dependency>
                <groupId>io.helidon.tracing</groupId>
                <artifactId>helidon-tracing-zipkin</artifactId>
            </dependency>

  2. Configure the service name in microprofile-config.properties.

    Goto src/main/resources -> META-INF and append the following line to microprofile-config.properties.

    # Enable tracing
    tracing.service=helidon-mp

  3. Save changes and restart the MP application.

Start Zipkin and monitor applications

  1. Start the Zipkin tracer.

    In the Terminal Emulator run the following command.

    curl -LSs https://raw.githubusercontent.com/nagypeter/helidon-tutorial/master/scripts/setup.zipkin.sh | bash

    Note

    This will start the Zipkin tracer on http://localhost:9411 - this is also the default configuration that Helidon expects.

  2. Lets open the dashboard.

    http://localhost:9411/zipkin

  3. To generate tracing information invoke again the outbound call.

    In a new browser tab enter the following URL.

    http://localhost:8081/greet/outbound/Bill
  4. In the Zipkin tab click Run Query and then click Expand All.

    View the details by clicking on Show.

    You can see the detailed tracing result where both services are involved.

You can continue to the next step.

STEP 10: Fault tolerance

Shutdown the SE service and invoking the /greet/outbound endpoint:

http://localhost:8081/greet/outbound/Jack

You should get an internal server (HTTP ERROR 500) error.

To avoid such failure a microservices application always needs to prepared for such situation like service restarts, network delays, temporal infrastructure instabilities, etc.

Fault Tolerance is a MicroProfile specification which improves application robustness by providing support to conveniently handle error conditions (faults) that may occur in real-world applications.

  1. In the helidon-quickstart-mp package, open GreetResource.java.

    Add a package.

    import org.eclipse.microprofile.faulttolerance.Fallback;

    Add annotation to the outbound method:

    @Fallback(fallbackMethod = "onFailureOutbound")

    Create the fallback method:

    public JsonObject onFailureOutbound(String name) {
        return Json.createObjectBuilder().add("Failed", name).build();
    }

    Save the changes and restart both MP and SE applications.

  2. Validate it works as expected.

    Refresh the browser tab with the endpoint.

    http://localhost:8081/greet/outbound/Jack
  3. Shutdown the SE application and try again the endpoint.

    http://localhost:8081/greet/outbound/Jack
  4. You should see the Failed message instead of an internal server error.

    If you have time you can check the failure when SE invocation is not happening or previous HTTP ERROR 500 in the Zipkin:

    http://localhost:9411/zipkin

You can continue to the next step.

STEP 11: Static content

Helidon application can serve static content, for example web page.

So let's create a simple HTML page which invokes the /greet service and output the result.

  1. To activate static content support first add the necessary dependency to the Maven project.

    In the helidon-quickstart-se package, open pom.xml. Add the following then save.

      <dependency>
    	    <groupId>io.helidon.webserver</groupId>
    	    <artifactId>helidon-webserver-static-content</artifactId>
    	</dependency>

  2. Create the folder name static-content.

    Right click on the src/main/resources folder and select New... -> Folder. Enter folder name as static-content.

  3. Create the html file called index.html.

  4. Edit the html file.

    Right click on index.html and select Open With -> Text Editor.

    Copy and paste the following in to the new file and save.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Helidon SE</title>
    </head>
    <body>
    	<h2>Invoke greet:</h2>
    	<div id="greetMessage"></div>
    
    	<script>
    		var xmlhttp = new XMLHttpRequest();
    		var url = "/greet";
    
    		xmlhttp.onreadystatechange = function() {
    			if (this.readyState == 4 && this.status == 200) {
    				document.getElementById("greetMessage").innerHTML = this.responseText;
    			}
    		};
    		xmlhttp.open("GET", url, true);
    		xmlhttp.send();
    	</script>
    </body>
    </html>
  5. Register the static content folder in the router.

    In the Main.java file add the package.

    import io.helidon.webserver.staticcontent.StaticContentSupport;

    Add the following line to router builder in the createRouting method.

    .register("/", StaticContentSupport.builder("/static-content"))

  6. Save the changes and restart the SE application.

  7. In a browser test the static web page, enter the URL.

    http://localhost:8080/index.html 

    The html page invokes the /greet endpoint and output the result.

Congratulation!

You have successfully completed this lab.

To end this session, click the End Session button in the toolbar.

SSR