From d61541fdf933825baf0474d06935b5afa67033a9 Mon Sep 17 00:00:00 2001 From: Romain Grecourt Date: Fri, 29 Sep 2023 02:35:14 -0700 Subject: [PATCH] Update HttpRules API to not have varargs with generics (#7687) * Update HttpRules API to not have method with vararg with generics - Update HttpService interface to not be a Supplier to remove ambiguity - Replace `register(Supplier... service)` with register(HttpService... service)` - Overload it with 5 variants to accept up to 5 suppliers of services (@SafeVarags is not usable on interfaces) - Add `register(List services)` for more than 5 services - Replace `register(String pathPattern, Supplier... service)` with register(String pathPattern, HttpService... service)` - Overload it with 5 variants to accept up to 5 suppliers of services (@SafeVarags is not usable on interfaces) - Add `register(String pathPattern, List services)` for more than 5 services Fixes #7656 * Fix javadoc references to the old method `register(java.util.function.Supplier[])` --- .../microprofile/server/RoutingPath.java | 2 +- .../webserver/security/SecurityFeature.java | 6 +- .../staticcontent/StaticContentService.java | 2 +- .../webserver/tracing/TracingFeature.java | 3 +- .../helidon/webserver/http/HttpRouting.java | 107 ++++++++++- .../webserver/http/HttpRoutingFeature.java | 11 +- .../io/helidon/webserver/http/HttpRules.java | 175 +++++++++++++++++- .../helidon/webserver/http/HttpService.java | 11 +- .../helidon/webserver/http/ServiceRules.java | 21 +-- .../webserver/http/HttpRoutingTest.java | 4 +- .../helidon/webserver/http/HttpRulesTest.java | 5 +- 11 files changed, 299 insertions(+), 48 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/RoutingPath.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/RoutingPath.java index 3f9db4d5252..44bb022309a 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/RoutingPath.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/RoutingPath.java @@ -27,7 +27,7 @@ /** * Path of a {@link io.helidon.webserver.http.HttpService} to register with routing. * If a service is not annotated with this annotation, it would be registered without a path using - * {@link io.helidon.webserver.http.HttpRules#register(java.util.function.Supplier[])}. + * {@link io.helidon.webserver.http.HttpRules#register(io.helidon.webserver.http.HttpService[])}. * * Configuration can be overridden using configuration: *
    diff --git a/webserver/security/src/main/java/io/helidon/webserver/security/SecurityFeature.java b/webserver/security/src/main/java/io/helidon/webserver/security/SecurityFeature.java index 3aa283b9f37..5d05c914267 100644 --- a/webserver/security/src/main/java/io/helidon/webserver/security/SecurityFeature.java +++ b/webserver/security/src/main/java/io/helidon/webserver/security/SecurityFeature.java @@ -125,7 +125,7 @@ private SecurityFeature(Security security, Config config, SecurityHandler defaul /** * Create a consumer of routing config to be - * {@link io.helidon.webserver.http.HttpRouting.Builder#register(java.util.function.Supplier[])} registered} with + * {@link io.helidon.webserver.http.HttpRouting.Builder#addFeature(java.util.function.Supplier) registered} with * web server routing to process security requests. * This method is to be used together with other routing methods to protect web resources programmatically. * Example: @@ -143,7 +143,7 @@ public static SecurityFeature create(Security security) { /** * Create a consumer of routing config to be - * {@link io.helidon.webserver.http.HttpRouting.Builder#register(java.util.function.Supplier[])} registered} with + * {@link io.helidon.webserver.http.HttpRouting.Builder#addFeature(java.util.function.Supplier) registered} with * web server routing to process security requests. * This method configures security and web server integration from a config instance * @@ -157,7 +157,7 @@ public static SecurityFeature create(Config config) { /** * Create a consumer of routing config to be - * {@link io.helidon.webserver.http.HttpRouting.Builder#register(java.util.function.Supplier[])} registered} with + * {@link io.helidon.webserver.http.HttpRouting.Builder#addFeature(java.util.function.Supplier) registered} with * web server routing to process security requests. * This method expects initialized security and creates web server integration from a config instance * diff --git a/webserver/static-content/src/main/java/io/helidon/webserver/staticcontent/StaticContentService.java b/webserver/static-content/src/main/java/io/helidon/webserver/staticcontent/StaticContentService.java index 649304d5b6e..872468578ab 100644 --- a/webserver/static-content/src/main/java/io/helidon/webserver/staticcontent/StaticContentService.java +++ b/webserver/static-content/src/main/java/io/helidon/webserver/staticcontent/StaticContentService.java @@ -33,7 +33,7 @@ * Serves 'static content' (files) from filesystem or using a classloader to the * {@link io.helidon.webserver.WebServer WebServer} * {@link io.helidon.webserver.http.HttpRouting}. It is possible to - * {@link io.helidon.webserver.http.HttpRouting.Builder#register(java.util.function.Supplier[]) register} it on the routing. + * {@link io.helidon.webserver.http.HttpRouting.Builder#register(HttpService[]) register} it on the routing. *
    {@code
      * // Serve content of attached '/static/pictures' on '/pics'
      * Routing.builder()
    diff --git a/webserver/tracing/src/main/java/io/helidon/webserver/tracing/TracingFeature.java b/webserver/tracing/src/main/java/io/helidon/webserver/tracing/TracingFeature.java
    index 86dd257491f..5f541a6177f 100644
    --- a/webserver/tracing/src/main/java/io/helidon/webserver/tracing/TracingFeature.java
    +++ b/webserver/tracing/src/main/java/io/helidon/webserver/tracing/TracingFeature.java
    @@ -78,8 +78,7 @@ private TracingFeature(Builder builder) {
          *
          * @param tracer tracer to use for tracing spans created by this feature
          * @return tracing configuration to register with
    -     *         {@link
    -     *         io.helidon.webserver.http.HttpRouting.Builder#register(java.util.function.Supplier[])}
    +     *         {@link io.helidon.webserver.http.HttpRouting.Builder#addFeature(java.util.function.Supplier)}
          */
         public static TracingFeature create(Tracer tracer) {
             return create(tracer, TracingConfig.ENABLED);
    diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java
    index 083316f01e3..39fabed79fa 100644
    --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java
    +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java
    @@ -143,10 +143,105 @@ private enum RoutingResult {
          */
         public interface Builder extends HttpRules, io.helidon.common.Builder {
             @Override
    -        Builder register(Supplier... service);
    +        Builder register(HttpService... service);
     
             @Override
    -        Builder register(String path, Supplier... service);
    +        default Builder register(Supplier service) {
    +            HttpRules.super.register(service);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(Supplier service1, Supplier service2) {
    +            HttpRules.super.register(service1, service2);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3) {
    +            HttpRules.super.register(service1, service2, service3);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3,
    +                                 Supplier service4) {
    +            HttpRules.super.register(service1, service2, service3, service4);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3,
    +                                 Supplier service4,
    +                                 Supplier service5) {
    +            HttpRules.super.register(service1, service2, service3, service4, service5);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(List> services) {
    +            HttpRules.super.register(services);
    +            return this;
    +        }
    +
    +        @Override
    +        Builder register(String path, HttpService... service);
    +
    +        @Override
    +        default Builder register(String pathPattern, Supplier service) {
    +            HttpRules.super.register(pathPattern, service);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(String pathPattern,
    +                                 Supplier service1,
    +                                 Supplier service2) {
    +            HttpRules.super.register(pathPattern, service1, service2);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(String pathPattern,
    +                                 Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3) {
    +            HttpRules.super.register(pathPattern, service1, service2, service3);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(String pathPattern,
    +                                 Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3,
    +                                 Supplier service4) {
    +            HttpRules.super.register(pathPattern, service1, service2, service3, service4);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(String pathPattern,
    +                                 Supplier service1,
    +                                 Supplier service2,
    +                                 Supplier service3,
    +                                 Supplier service4,
    +                                 Supplier service5) {
    +            HttpRules.super.register(pathPattern, service1, service2, service3, service4, service5);
    +            return this;
    +        }
    +
    +        @Override
    +        default Builder register(String pathPattern, List> services) {
    +            HttpRules.super.register(pathPattern, services);
    +            return this;
    +        }
     
             @Override
             Builder route(HttpRoute route);
    @@ -438,13 +533,13 @@ public HttpRouting build() {
             }
     
             @Override
    -        public Builder register(Supplier... service) {
    +        public Builder register(HttpService... service) {
                 mainRouting.service(service);
                 return this;
             }
     
             @Override
    -        public Builder register(String path, Supplier... service) {
    +        public Builder register(String path, HttpService... service) {
                 mainRouting.service(path, service);
                 return this;
             }
    @@ -620,13 +715,13 @@ public HttpRouting build() {
             }
     
             @Override
    -        public Builder register(Supplier... service) {
    +        public Builder register(HttpService... service) {
                 rootRules.register(service);
                 return this;
             }
     
             @Override
    -        public Builder register(String pathPattern, Supplier... service) {
    +        public Builder register(String pathPattern, HttpService... service) {
                 rootRules.register(pathPattern, service);
                 return this;
             }
    diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRoutingFeature.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRoutingFeature.java
    index a0c6d9a6728..0424aea859d 100644
    --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRoutingFeature.java
    +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRoutingFeature.java
    @@ -18,7 +18,6 @@
     
     import java.util.ArrayList;
     import java.util.List;
    -import java.util.function.Supplier;
     
     import io.helidon.common.Weighted;
     
    @@ -42,14 +41,14 @@ void filter(Filter filter) {
         }
     
          void error(Class exceptionClass, ErrorHandler handler) {
    -        this.registrations.add(new ErrorReg(exceptionClass, handler));
    +        this.registrations.add(new ErrorReg<>(exceptionClass, handler));
         }
     
    -    void service(Supplier... services) {
    +    void service(HttpService... services) {
             this.registrations.add(new ServiceReg(services));
         }
     
    -    void service(String path, Supplier... services) {
    +    void service(String path, HttpService... services) {
             this.registrations.add(new ServicePathReg(path, services));
         }
     
    @@ -78,14 +77,14 @@ public void register(HttpRouting.Builder routing) {
             }
         }
     
    -    private record ServiceReg(Supplier[] services) implements Registration {
    +    private record ServiceReg(HttpService[] services) implements Registration {
             @Override
             public void register(HttpRouting.Builder routing) {
                 routing.register(services);
             }
         }
     
    -    private record ServicePathReg(String path, Supplier[] services) implements Registration {
    +    private record ServicePathReg(String path, HttpService[] services) implements Registration {
             @Override
             public void register(HttpRouting.Builder routing) {
                 routing.register(path, services);
    diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRules.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRules.java
    index 60ecb2e8727..2175fffd185 100644
    --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRules.java
    +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRules.java
    @@ -16,6 +16,7 @@
     
     package io.helidon.webserver.http;
     
    +import java.util.List;
     import java.util.function.Consumer;
     import java.util.function.Function;
     import java.util.function.Predicate;
    @@ -36,7 +37,96 @@ public interface HttpRules {
          * @param service service to register
          * @return updated rules
          */
    -    HttpRules register(Supplier... service);
    +    HttpRules register(HttpService... service);
    +
    +    /**
    +     * Register a service on the current path.
    +     *
    +     * @param service service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(Supplier service) {
    +        return register(service.get());
    +    }
    +
    +    /**
    +     * Register two services on the current path.
    +     *
    +     * @param service1 first service to register
    +     * @param service2 second service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(Supplier service1,
    +                               Supplier service2) {
    +        return register(service1.get(), service2.get());
    +    }
    +
    +    /**
    +     * Register three services on the current path.
    +     *
    +     * @param service1 first service to register
    +     * @param service2 second service to register
    +     * @param service3 third service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3) {
    +        return register(service1.get(), service2.get(), service3.get());
    +    }
    +
    +    /**
    +     * Register four services on the current path.
    +     *
    +     * @param service1 first service to register
    +     * @param service2 second service to register
    +     * @param service3 third service to register
    +     * @param service4 fourth service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3,
    +                               Supplier service4) {
    +        return register(service1.get(), service2.get(), service3.get(), service4.get());
    +    }
    +
    +    /**
    +     * Register five services on the current path.
    +     *
    +     * @param service1 first service to register
    +     * @param service2 second service to register
    +     * @param service3 third service to register
    +     * @param service4 fourth service to register
    +     * @param service5 fifth service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3,
    +                               Supplier service4,
    +                               Supplier service5) {
    +        return register(service1.get(), service2.get(), service3.get(), service4.get(), service5.get());
    +    }
    +
    +    /**
    +     * Register services on the current path.
    +     *
    +     * @param services services to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(List> services) {
    +        return register(services.stream().map(Supplier::get).toArray(HttpService[]::new));
    +    }
    +
    +    /**
    +     * Register a service on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param service     service to register
    +     * @return updated rules
    +     */
    +    HttpRules register(String pathPattern, HttpService... service);
     
         /**
          * Register a service on sub-path of the current path.
    @@ -45,7 +135,88 @@ public interface HttpRules {
          * @param service     service to register
          * @return updated rules
          */
    -    HttpRules register(String pathPattern, Supplier... service);
    +    default HttpRules register(String pathPattern, Supplier service) {
    +        return register(pathPattern, service.get());
    +    }
    +
    +    /**
    +     * Register two services on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param service1    first service to register
    +     * @param service2    second service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(String pathPattern,
    +                               Supplier service1,
    +                               Supplier service2) {
    +        return register(pathPattern, service1.get(), service2.get());
    +    }
    +
    +    /**
    +     * Register three services on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param service1    first service to register
    +     * @param service2    second service to register
    +     * @param service3    third service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(String pathPattern,
    +                               Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3) {
    +        return register(pathPattern, service1.get(), service2.get(), service3.get());
    +    }
    +
    +    /**
    +     * Register four services on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param service1    first service to register
    +     * @param service2    second service to register
    +     * @param service3    third service to register
    +     * @param service4    fourth service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(String pathPattern,
    +                               Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3,
    +                               Supplier service4) {
    +        return register(pathPattern, service1.get(), service2.get(), service3.get(), service4.get());
    +    }
    +
    +    /**
    +     * Register five services on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param service1    first service to register
    +     * @param service2    second service to register
    +     * @param service3    third service to register
    +     * @param service4    fourth service to register
    +     * @param service5    fifth service to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(String pathPattern,
    +                               Supplier service1,
    +                               Supplier service2,
    +                               Supplier service3,
    +                               Supplier service4,
    +                               Supplier service5) {
    +        return register(pathPattern, service1.get(), service2.get(), service3.get(), service4.get(), service5.get());
    +    }
    +
    +    /**
    +     * Register services on sub-path of the current path.
    +     *
    +     * @param pathPattern URI path pattern
    +     * @param services    services to register
    +     * @return updated rules
    +     */
    +    default HttpRules register(String pathPattern, List> services) {
    +        return register(pathPattern, services.stream().map(Supplier::get).toArray(HttpService[]::new));
    +    }
     
         /**
          * Add a route. This allows also protocol version specific routing.
    diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpService.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpService.java
    index 312894f7223..83644d22694 100644
    --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpService.java
    +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpService.java
    @@ -16,22 +16,16 @@
     
     package io.helidon.webserver.http;
     
    -import java.util.function.Supplier;
    -
     import io.helidon.webserver.ServerLifecycle;
     
     /**
      * Encapsulates a set of {@link HttpRouting routing} rules and related logic.
      * 

    * Instance can be assigned to the {@link HttpRouting routing} using - * {@link HttpRouting.Builder#register(java.util.function.Supplier[])} methods. + * {@link HttpRouting.Builder#register(java.util.function.Supplier)} methods. */ @FunctionalInterface -public interface HttpService extends Supplier, ServerLifecycle { - @Override - default HttpService get() { - return this; - } +public interface HttpService extends ServerLifecycle { /** * Updates the routing to add handlers of this service. @@ -40,4 +34,3 @@ default HttpService get() { */ void routing(HttpRules rules); } - diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/ServiceRules.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/ServiceRules.java index ba6749e4cbf..ff2913a5700 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/ServiceRules.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/ServiceRules.java @@ -19,7 +19,6 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; -import java.util.function.Supplier; import io.helidon.http.Method; import io.helidon.http.PathMatcher; @@ -46,26 +45,22 @@ class ServiceRules implements HttpRules { } @Override - public HttpRules register(Supplier... services) { - for (Supplier service : services) { - HttpService theService = service.get(); - ServiceRules subRules = new ServiceRules(theService, PathMatchers.any(), ALWAYS_PREDICATE); - theService.routing(subRules); + public HttpRules register(HttpService... services) { + for (HttpService service : services) { + ServiceRules subRules = new ServiceRules(service, PathMatchers.any(), ALWAYS_PREDICATE); + service.routing(subRules); routes.add(subRules.build()); } - return this; } @Override - public HttpRules register(String pathPattern, Supplier... services) { - for (Supplier service : services) { - HttpService theService = service.get(); - ServiceRules subRules = new ServiceRules(theService, PathMatchers.create(pathPattern), ALWAYS_PREDICATE); - theService.routing(subRules); + public HttpRules register(String pathPattern, HttpService... services) { + for (HttpService service : services) { + ServiceRules subRules = new ServiceRules(service, PathMatchers.create(pathPattern), ALWAYS_PREDICATE); + service.routing(subRules); routes.add(subRules.build()); } - return this; } diff --git a/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRoutingTest.java b/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRoutingTest.java index ffc1949f431..86fe2b95a87 100644 --- a/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRoutingTest.java +++ b/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRoutingTest.java @@ -118,12 +118,12 @@ public Handler getHandler() { } @Override - public HttpRouting.Builder register(Supplier... service) { + public HttpRouting.Builder register(HttpService... service) { return null; } @Override - public HttpRouting.Builder register(String path, Supplier... service) { + public HttpRouting.Builder register(String path, HttpService... service) { return null; } diff --git a/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRulesTest.java b/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRulesTest.java index dc20c2fb181..27c57e8448d 100644 --- a/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRulesTest.java +++ b/webserver/webserver/src/test/java/io/helidon/webserver/http/HttpRulesTest.java @@ -17,7 +17,6 @@ package io.helidon.webserver.http; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Stream; import io.helidon.http.Method; @@ -119,12 +118,12 @@ public Handler getHandler() { } @Override - public HttpRules register(Supplier... service) { + public HttpRules register(HttpService... service) { return null; } @Override - public HttpRules register(String pathPattern, Supplier... service) { + public HttpRules register(String pathPattern, HttpService... service) { return null; }