///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

///////////////////////////////////////////////////////////////////////////////

= gRPC Server Routing
:pagename: grpc-server-routing
:description: Helidon gRPC Server Routing
:keywords: helidon, grpc, java

== gRPC Server Routing

Unlike Webserver, which allows you to route requests based on path expression
and the HTTP verb, gRPC server always routes requests based on the service and
method name. This makes routing configuration somewhat simpler -- all you need
to do is register your services:

[source,java]
----
    private static GrpcRouting createRouting(Config config) {
        return GrpcRouting.builder()
                .register(new GreetService(config)) // <1>
                .register(new EchoService())        // <2>
                .register(new MathService())        // <3>
                .build();
    }
----

<1> Register `GreetService` instance.
<2> Register `EchoService` instance.
<3> Register `MathService` instance.

Both "standard" gRPC services that implement `io.grpc.BindableService` interface
(typically implemented by extending generated server-side stub and overriding
its methods), and Helidon gRPC services that implement
`io.helidon.grpc.server.GrpcService` interface can be registered.

The difference is that Helidon gRPC services allow you to customize behavior
down to the method level, and provide a number of useful helper methods that
make service implementation easier, as we'll see in a moment.

== Customizing Service Definitions

When registering a service, regardless of its type, you can customize its
descriptor by providing configuration consumer as a second argument to the
`register` method.

This is particularly useful when registering standard `BindableService`
instances, as it allows you to add certain Helidon-specific behaviors, such as
<<06_health_checks.adoc, health checks>> and <<07_metrics.adoc, metrics>> to them:

[source,java]
----
    private static GrpcRouting createRouting(Config config) {
        return GrpcRouting.builder()
                .register(new GreetService(config))
                .register(new EchoService(), service -> {
                    service.healthCheck(CustomHealthChecks::echoHealthCheck)  // <1>
                           .metered();                                        // <2>
                })
                .build();
    }
----

<1> Add custom health check to the service.
<2> Specify that all the calls to service methods should be metered.

== Specifying Global Interceptors

`GrpcRouting` also allows you to specify <<05_interceptors.adoc, custom interceptors>>
that will be applied to all registered services.

This is useful to configure features such as tracing, security and metrics collection,
and we provide built-in interceptors for those purposes that you can simply register
with the routing definition:

[source,java]
----
    private static GrpcRouting createRouting(Config config) {
        return GrpcRouting.builder()
                .intercept(GrpcMetrics.timed())     // <1>
                .register(new GreetService(config))
                .register(new EchoService())
                .register(new MathService())
                .build();
    }
----

<1> Register `GrpcMetrics` interceptor that will collect timers for all methods of
    all services (but can be overridden at the individual service or even method level).
