public GrpcService build() {
        final HandlerRegistry handlerRegistry;
        if (USE_COROUTINE_CONTEXT_INTERCEPTOR) {
            final ServerInterceptor coroutineContextInterceptor =
                    new ArmeriaCoroutineContextInterceptor(useBlockingTaskExecutor);
            interceptors().add(coroutineContextInterceptor);
        }
        if (!enableUnframedRequests && unframedGrpcErrorHandler != null) {
            throw new IllegalStateException(
                    "'unframedGrpcErrorHandler' can only be set if unframed requests are enabled");
        }
        if (!enableHttpJsonTranscoding && httpJsonTranscodingErrorHandler != null) {
            throw new IllegalStateException(
                    "'httpJsonTranscodingErrorHandler' can only be set if HTTP/JSON transcoding feature " +
                    "is enabled");
        }
        if (enableHttpJsonTranscoding && !supportedSerializationFormats.contains(
                GrpcSerializationFormats.JSON)) {
            throw new IllegalStateException(
                    "'GrpcSerializationFormats.JSON' must be set if 'enableHttpJsonTranscoding' is set"
            );
        }
        if (enableHealthCheckService) {
            grpcHealthCheckService = GrpcHealthCheckService.builder().build();
        }
        if (grpcHealthCheckService != null) {
            registryBuilder.addService(grpcHealthCheckService.bindService(), null, ImmutableList.of());
        }

        final GrpcExceptionHandlerFunction grpcExceptionHandler;
        if (exceptionMappingsBuilder != null) {
            grpcExceptionHandler = exceptionMappingsBuilder.build().orElse(GrpcExceptionHandlerFunction.of());
        } else if (exceptionHandler != null) {
            grpcExceptionHandler = exceptionHandler.orElse(GrpcExceptionHandlerFunction.of());
        } else {
            grpcExceptionHandler = GrpcExceptionHandlerFunction.of();
        }
        registryBuilder.setDefaultExceptionHandler(grpcExceptionHandler);

        if (interceptors != null) {
            final HandlerRegistry.Builder newRegistryBuilder = new HandlerRegistry.Builder();
            final ImmutableList<ServerInterceptor> interceptors = this.interceptors.build();
            for (Entry entry : registryBuilder.entries()) {
                final MethodDescriptor<?, ?> methodDescriptor = entry.method();
                final ServerServiceDefinition intercepted =
                        ServerInterceptors.intercept(entry.service(), interceptors);
                newRegistryBuilder.addService(entry.path(), intercepted, methodDescriptor, entry.type(),
                                              entry.additionalDecorators());
            }
            if (grpcExceptionHandler != null) {
                newRegistryBuilder.setDefaultExceptionHandler(grpcExceptionHandler);
            }
            handlerRegistry = newRegistryBuilder.build();
        } else {
            handlerRegistry = registryBuilder.build();
        }

        GrpcService grpcService = new FramedGrpcService(
                handlerRegistry,
                firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
                firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
                supportedSerializationFormats,
                jsonMarshallerFactory,
                protoReflectionServiceInterceptor,
                maxRequestMessageLength, maxResponseMessageLength,
                useBlockingTaskExecutor,
                unsafeWrapRequestBuffers,
                useClientTimeoutHeader,
                enableHttpJsonTranscoding, // The method definition might be set when transcoding is enabled.
                grpcHealthCheckService,
                autoCompression,
                useMethodMarshaller);
        if (enableUnframedRequests) {
            grpcService = new UnframedGrpcService(
                    grpcService, handlerRegistry,
                    unframedGrpcErrorHandler != null ? unframedGrpcErrorHandler
                                                     : UnframedGrpcErrorHandler.of());
        }
        if (enableHttpJsonTranscoding) {
            final HttpJsonTranscodingOptions httpJsonTranscodingOptions;
            if (httpJsonTranscodingErrorHandler != null) {
                httpJsonTranscodingOptions =
                        HttpJsonTranscodingOptions
                                .builder()
                                .queryParamMatchRules(
                                        this.httpJsonTranscodingOptions.queryParamMatchRules())
                                .errorHandler(httpJsonTranscodingErrorHandler)
                                .build();
            } else {
                httpJsonTranscodingOptions = this.httpJsonTranscodingOptions;
            }
            grpcService = HttpJsonTranscodingService.of(grpcService, httpJsonTranscodingOptions);
        }
        if (handlerRegistry.containsDecorators()) {
            grpcService = new GrpcDecoratingService(grpcService, handlerRegistry);
        }
        return grpcService;
    }
Constructs a new {@link GrpcService} that can be bound to
{@link ServerBuilder}. It is recommended to bind the service to a server using
{@linkplain ServerBuilder#service(HttpServiceWithRoutes, Function[])
ServerBuilder.service(HttpServiceWithRoutes)} to mount all service paths
without interfering with other services.
grpc/src/main/java/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.java