|
| 1 | +/////////////////////////////////////////////////////////////////////////////// |
| 2 | + |
| 3 | + Copyright (c) 2025 Oracle and/or its affiliates. |
| 4 | + |
| 5 | + Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | + you may not use this file except in compliance with the License. |
| 7 | + You may obtain a copy of the License at |
| 8 | + |
| 9 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | + |
| 11 | + Unless required by applicable law or agreed to in writing, software |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | + See the License for the specific language governing permissions and |
| 15 | + limitations under the License. |
| 16 | + |
| 17 | +/////////////////////////////////////////////////////////////////////////////// |
| 18 | +
|
| 19 | += Declarative |
| 20 | +
|
| 21 | +:description: Helidon SE Declarative |
| 22 | +:keywords: helidon, se, injection, declarative |
| 23 | +:h1Prefix: SE |
| 24 | +:feature-name: Declarative |
| 25 | +:rootdir: {docdir}/../.. |
| 26 | +
|
| 27 | +include::{rootdir}/includes/se.adoc[] |
| 28 | +
|
| 29 | +== Contents |
| 30 | +
|
| 31 | +- <<Overview, Overview>> |
| 32 | +- <<Usage, Usage>> |
| 33 | +- <<Features, Features>> |
| 34 | +
|
| 35 | +== Overview |
| 36 | +
|
| 37 | +Helidon declarative programming model allows inversion of control style programming with all the performance benefits of Helidon SE. |
| 38 | +
|
| 39 | +Our declarative approach has the following advantages: |
| 40 | +
|
| 41 | +- Uses Helidon SE imperative code to implement features (i.e. performance is same as "pure" imperative application) |
| 42 | +- Generates all the necessary code at build-time, to avoid reflection and bytecode manipulation at runtime |
| 43 | +- It is based on xref:injection.adoc#Overview[Helidon Injection] |
| 44 | +- Declarative features are in the same modules as Helidon SE features (i.e. does not require additional dependencies) |
| 45 | +
|
| 46 | +[NOTE] |
| 47 | +Helidon Declarative is an incubating feature. The APIs shown here are subject to change. These APIs will be finalized in a future release of Helidon. |
| 48 | +
|
| 49 | +== Usage |
| 50 | +
|
| 51 | +To create a declarative application, use the annotations provided in our Helidon SE modules (details under <<Features, Features>>), and the maven plugin |
| 52 | +described in xref:injection.adoc#generate-binding[Injection: Startup] to generate the binding. |
| 53 | +
|
| 54 | +In addition, the following section must be added to the `build` of the Maven `pom.xml` to enable annotation processors that generate the necessary code: |
| 55 | +
|
| 56 | +[source,xml] |
| 57 | +---- |
| 58 | +<plugins> |
| 59 | + <plugin> |
| 60 | + <groupId>org.apache.maven.plugins</groupId> |
| 61 | + <artifactId>maven-compiler-plugin</artifactId> |
| 62 | + <configuration> |
| 63 | + <annotationProcessorPaths> |
| 64 | + <path> |
| 65 | + <groupId>io.helidon.bundles</groupId> |
| 66 | + <artifactId>helidon-bundles-apt</artifactId> |
| 67 | + <version>${helidon.version}</version> |
| 68 | + </path> |
| 69 | + </annotationProcessorPaths> |
| 70 | + </configuration> |
| 71 | + </plugin> |
| 72 | +</plugins> |
| 73 | +---- |
| 74 | +
|
| 75 | +
|
| 76 | +== Features |
| 77 | +
|
| 78 | +The following features are currently implemented: |
| 79 | +
|
| 80 | +- <<Dec-Config, Configuration>> |
| 81 | +- <<Dec-HTTP-Server, HTTP Server Endpoint>> |
| 82 | +- <<Dec-HTTP-Client, Typed HTTP Client>> |
| 83 | +- <<Dec-FT, Fault Tolerance>> |
| 84 | +- <<Dec-Scheduling, Scheduling>> |
| 85 | +
|
| 86 | +A Helidon Declarative application should be started using the generated application binding, to ensure no lookup and no reflection. |
| 87 | +The call to `ServiceRegistryManager.start` ensures that all services with a defined `RunLevel` are started, including Helidon WebServer, Scheduled services etc. |
| 88 | +
|
| 89 | +[source,java] |
| 90 | +.Example of a declarative main class |
| 91 | +---- |
| 92 | +include::{sourcedir}/se/inject/DeclarativeExample.java[tag=snippet_1, indent=0] |
| 93 | +---- |
| 94 | +
|
| 95 | +=== Configuration [[Dec-Config]] |
| 96 | +
|
| 97 | +Configuration can be injected as a whole into any service, or a specific configuration option can be injected using `@Configuration.Value`. Default values can be defined using annotations in `@Default` |
| 98 | +
|
| 99 | +Services available for injection: |
| 100 | +
|
| 101 | +- link:{config-javadoc-base-url}/io/helidon/config/Config.html[`io.helidon.config.Config`] |
| 102 | +
|
| 103 | +Annotations: |
| 104 | +
|
| 105 | +- link:{config-javadoc-base-url}/io/helidon/config/Configuration.html[`io.helidon.config.Configuration.Value`] - define the configuration key to inject, on constructor parameter |
| 106 | +- Annotations defined in link:{common-javadoc-base-url}/io/helidon/common/Default.html[`io.helidon.common.Default`] - define a default typed value, on the same constructor parameter |
| 107 | +
|
| 108 | +Example of usage can be seen below in HTTP Server Endpoint example. |
| 109 | +
|
| 110 | +=== HTTP Server Endpoint [[Dec-HTTP-Server]] |
| 111 | +
|
| 112 | +To create an HTTP endpoint, simply annotate a class with `@RestServer.Endpoint`, and |
| 113 | +add at least one method annotated with one of the HTTP method annotations, such as `@Http.GET`. |
| 114 | +
|
| 115 | +Services available for injection: |
| 116 | +
|
| 117 | +N/A |
| 118 | +
|
| 119 | +Supported method parameters (no annotation required): |
| 120 | +
|
| 121 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/ServerRequest.html[`io.helidon.webserver.http.ServerRequest`] |
| 122 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/ServerResponse.html[`io.helidon.webserver.http.ServerResponse`] |
| 123 | +- link:{context-javadoc-base-url}/io/helidon/common/context/Context.html[`io.helidon.common.context.Context`] |
| 124 | +- `io.helidon.common.security.SecurityContext` |
| 125 | +- link:{security-javadoc-base-url}/io/helidon/security/SecurityContext.html`[`io.helidon.security.SecurityContext] - in case `helidon-security` module is on the classpath |
| 126 | +
|
| 127 | +Annotations on endpoint type: |
| 128 | +
|
| 129 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.Endpoint.html[`io.helidon.webserver.http.RestServer.Endpoint`] - required annotation |
| 130 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.Listener.html[`io.helidon.webserver.http.RestServer.Listener`] - to define the named listener this should be served on (named port/socket) |
| 131 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.Header.html[`io.helidon.webserver.http.RestServer.Header`] - header to return with each response from this endpoint |
| 132 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.ComputedHeader.html[`io.helidon.webserver.http.RestServer.ComputedHeader`] - computed header to return with each response from this endpoint |
| 133 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Path.html[`io.helidon.http.Http.Path`] - path (context) this endpoint will be available on |
| 134 | +
|
| 135 | +Annotations on endpoint methods: |
| 136 | +
|
| 137 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.Header.html[`io.helidon.webserver.http.RestServer.Header`] - header to return with each response from this method |
| 138 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.ComputedHeader.html[`io.helidon.webserver.http.RestServer.ComputedHeader`] - computed header to return with each response from this method |
| 139 | +- link:{webserver-javadoc-base-url}/io/helidon/webserver/http/RestServer.Status.html[`io.helidon.webserver.http.RestServer.Status`] - status to return (if a custom one is required) |
| 140 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Path.html[`io.helidon.http.Http.Path`] - path (context) this method will be available on (subpath of the endpoint path) |
| 141 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.GET.html[`io.helidon.http.Http.GET`] (and other methods) - definition of HTTP method this method will serve |
| 142 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.HttpMethod.html[`io.helidon.http.Http.HttpMethod`] - for custom HTTP method names (mutually exclusive with above) |
| 143 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Produces.html[`io.helidon.http.Http.Produces`] - what media type this method produces (return entity content type) |
| 144 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Consumes.html[`io.helidon.http.Http.Consumes`] - what media type this method accepts (request entity content type) |
| 145 | +
|
| 146 | +Annotations on method parameters: |
| 147 | +
|
| 148 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Entity.html[`io.helidon.http.Http.Entity`] - Request entity, a typed parameter is expected, will use HTTP media type modules to coerce into the correct type |
| 149 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.HeaderParam.html[`io.helidon.http.Http.HeaderParam`] - Typed HTTP request header value |
| 150 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.QueryParam.html[`io.helidon.http.Http.QueryParam`] - Typed HTTP query value |
| 151 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.PathParam.html[`io.helidon.http.Http.PathParam`] - Typed parameter from path template |
| 152 | +
|
| 153 | +[source,java] |
| 154 | +.Example of an HTTP Server Endpoint |
| 155 | +---- |
| 156 | +include::{sourcedir}/se/inject/DeclarativeExample.java[tag=snippet_2, indent=0] |
| 157 | +---- |
| 158 | +
|
| 159 | +=== Typed HTTP Client [[Dec-HTTP-Client]] |
| 160 | +
|
| 161 | +To create a typed HTTP client, create an interface annotated with `RestClient.Endpoint`, and at least one method annotated |
| 162 | +with one fo the HTTP method annotations, such as `@Http.GET`. Methods can only have parameters annotated with one of the |
| 163 | +`Http` qualifiers. |
| 164 | +
|
| 165 | +Annotations on endpoint type: |
| 166 | +
|
| 167 | +- link:{webclient-api-javadoc-base-url}/io/helidon/webclient/api/RestClient.Endpoint.html[`io.helidon.webclient.api.RestClient.Endpoint`] - required annotation |
| 168 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Path.html[`io.helidon.http.Http.Path`] - path (context) the server listens on |
| 169 | +- link:{webclient-api-javadoc-base-url}/io/helidon/webclient/api/RestClient.Header.html[`io.helidon.webclient.api.RestClient.Header`] - header to include in every request to the server |
| 170 | +- link:{webclient-api-javadoc-base-url}/io/helidon/webclient/api/RestClient.ComputedHeader.html[`io.helidon.webclient.api.RestClient.ComputedHeader`] - header to compute and include in every request to the server |
| 171 | +
|
| 172 | +Annotations on endpoint methods: |
| 173 | +
|
| 174 | +- link:{webclient-api-javadoc-base-url}/io/helidon/webclient/api/RestClient.Header.html[`io.helidon.webclient.api.RestClient.Header`] - header to include in every request to the server |
| 175 | +- link:{webclient-api-javadoc-base-url}/io/helidon/webclient/api/RestClient.ComputedHeader.html[`io.helidon.webclient.api.RestClient.ComputedHeader`] - header to compute and include in every request to the server |
| 176 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Path.html[`io.helidon.http.Http.Path`] - path (context) the server serves this endpoint method on |
| 177 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.GET.html[`io.helidon.http.Http.GET`] (and other methods) - definition of HTTP method this method will invoke |
| 178 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.HttpMethod.html[`io.helidon.http.Http.HttpMethod`] - for custom HTTP method names (mutually exclusive with above) |
| 179 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Produces.html[`io.helidon.http.Http.Produces`] - what media type this method produces (content type of entity from the server) |
| 180 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Consumes.html[`io.helidon.http.Http.Consumes`] - what media type this method accepts (request entity content type) |
| 181 | +
|
| 182 | +Annotations on method parameters: |
| 183 | +
|
| 184 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.Entity.html[`io.helidon.http.Http.Entity`] - Request entity, a typed parameter is expected, will use HTTP media type modules to write to the request |
| 185 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.HeaderParam.html[`io.helidon.http.Http.HeaderParam`] - Typed HTTP header value to send |
| 186 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.QueryParam.html[`io.helidon.http.Http.QueryParam`] - Typed HTTP query value to send |
| 187 | +- link:{http-javadoc-base-url}/io/helidon/http/Http.PathParam.html[`io.helidon.http.Http.PathParam`] - Typed parameter from path template to construct the request URI |
| 188 | +
|
| 189 | +[source,java] |
| 190 | +.Example of a Typed HTTP Client |
| 191 | +---- |
| 192 | +include::{sourcedir}/se/inject/DeclarativeExample.java[tag=snippet_3, indent=0] |
| 193 | +---- |
| 194 | +
|
| 195 | +
|
| 196 | +=== Fault Tolerance [[Dec-FT]] |
| 197 | +
|
| 198 | +Fault tolerance annotation allow adding features to methods on services. |
| 199 | +The annotations can be added to any method that supports interception (i.e. methods that are not private). |
| 200 | +
|
| 201 | +Method Annotations: |
| 202 | +
|
| 203 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.Retry.html[`io.helidon.faulttolerance.Ft.Retry`] - allow retries |
| 204 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.Fallback.html[`io.helidon.faulttolerance.Ft.Fallback`] - fallback to another method that provides |
| 205 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.Async.html[`io.helidon.faulttolerance.Ft.Async`] - invoke method asynchronously |
| 206 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.Timeout.html[`io.helidon.faulttolerance.Ft.Timeout`] - invoke method with a timeout |
| 207 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.Bulkhead.html[`io.helidon.faulttolerance.Ft.Bulkhead`] - use bulkhead |
| 208 | +- link:{faulttolerance-javadoc-base-url}/io/helidon/faulttolerance/Ft.CircuitBreaker.html[`io.helidon.faulttolerance.Ft.CircuitBreaker`] - use circuit breaker |
| 209 | +
|
| 210 | +[source,java] |
| 211 | +.Example of Fault Tolerance Fallback |
| 212 | +---- |
| 213 | +include::{sourcedir}/se/inject/DeclarativeExample.java[tag=snippet_4, indent=0] |
| 214 | +---- |
| 215 | +
|
| 216 | +=== Scheduling [[Dec-Scheduling]] |
| 217 | +
|
| 218 | +Scheduling allows service methods to be invoked periodically. |
| 219 | +
|
| 220 | +Method annotations: |
| 221 | +
|
| 222 | +- link:{scheduling-se-javadoc-base-url}/io/helidon/scheduling/Scheduling.Cron.html[`io.helidon.scheduling.Scheduling.Cron`] - execute with schedule defined by a CRON expression |
| 223 | +- link:{scheduling-se-javadoc-base-url}/io/helidon/scheduling/Scheduling.FixedRate.html[`io.helidon.scheduling.Scheduling.FixedRate`] - execute with a fixed interval |
| 224 | +
|
| 225 | +[source,java] |
| 226 | +.Example of a fixed rate scheduled method |
| 227 | +---- |
| 228 | +include::{sourcedir}/se/inject/DeclarativeExample.java[tag=snippet_5, indent=0] |
| 229 | +---- |
0 commit comments