diff --git a/applications/mp/pom.xml b/applications/mp/pom.xml index 93ce8ea6b85..ef79efb655f 100644 --- a/applications/mp/pom.xml +++ b/applications/mp/pom.xml @@ -1,7 +1,7 @@ + + + 4.0.0 + + io.helidon.applications + helidon-applications-project + 3.1.1-SNAPSHOT + ../pom.xml + + io.helidon.applications + helidon-applications + pom + Helidon Applications Parent + Maven boilerplate for Helidon applications + + + UTF-8 + UTF-8 + 17 + ${maven.compiler.source} + ${maven.compiler.source} + 3.8.1 + 3.1.2 + 1.6.0 + 3.0.0-M5 + 3.0.3 + 3.0.3 + 3.0.2 + 0.9.16 + 1.5.0.Final + 0.5.1 + 2.7 + 3.0.0-M5 + + + + ${project.artifactId} + + + kr.motd.maven + os-maven-plugin + ${version.plugin.os} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${version.plugin.compiler} + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.plugin.surefire} + + false + + ${project.build.outputDirectory}/logging.properties + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.plugin.failsafe} + + false + true + + + + org.apache.maven.plugins + maven-dependency-plugin + ${version.plugin.dependency} + + + copy-libs + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + false + false + true + true + runtime + test + + + + + + org.apache.maven.plugins + maven-resources-plugin + ${version.plugin.resources} + + + org.apache.maven.plugins + maven-jar-plugin + ${version.plugin.jar} + + + + true + libs + + ${mainClass} + false + + + + + + org.codehaus.mojo + exec-maven-plugin + ${version.plugin.exec} + + java + true + + -classpath + + ${mainClass} + + + + + io.helidon.build-tools + helidon-maven-plugin + ${version.plugin.helidon} + + + io.helidon.licensing + helidon-licensing + ${helidon.version} + + + + + io.helidon.build-tools + helidon-cli-maven-plugin + ${version.plugin.helidon-cli} + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${version.plugin.protobuf} + + com.google.protobuf:protoc:${version.lib.google-protobuf}:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:${version.lib.grpc}:exe:${os.detected.classifier} + + + + org.graalvm.buildtools + native-maven-plugin + ${version.plugin.nativeimage} + + + resource-config + + + true + + + + build-native-image + + + true + + ${project.build.outputDirectory} + ${project.build.finalName} + false + + false + + + + --add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.configure=ALL-UNNAMED + + + + + + + + + + + helidon-cli + + + helidon.cli + true + + + + + + io.helidon.build-tools + helidon-cli-maven-plugin + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/applications/pom.xml b/applications/pom.xml index eb4fa15f8c3..47fa6d7513b 100644 --- a/applications/pom.xml +++ b/applications/pom.xml @@ -1,7 +1,7 @@ - ${mainClass} - false - - - - - - org.codehaus.mojo - exec-maven-plugin - ${version.plugin.exec} - - java - true - - -classpath - - ${mainClass} - - - - - io.helidon.build-tools - helidon-maven-plugin - ${version.plugin.helidon} - - - io.helidon.licensing - helidon-licensing - ${helidon.version} - - - - - io.helidon.build-tools - helidon-cli-maven-plugin - ${version.plugin.helidon-cli} - - - org.xolstice.maven.plugins - protobuf-maven-plugin - ${version.plugin.protobuf} - - com.google.protobuf:protoc:${version.lib.google-protobuf}:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:${version.lib.grpc}:exe:${os.detected.classifier} - - - - org.graalvm.buildtools - native-maven-plugin - ${version.plugin.nativeimage} - - - resource-config - - - true - - - - build-native-image - - - true - - ${project.build.outputDirectory} - ${project.build.finalName} - false - - false - - - - --add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.configure=ALL-UNNAMED - - - - - - - - - - - helidon-cli - - - helidon.cli - true - - - - - - io.helidon.build-tools - helidon-cli-maven-plugin - true - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/applications/se/pom.xml b/applications/se/pom.xml index 4ad07671abb..654cf062ed5 100644 --- a/applications/se/pom.xml +++ b/applications/se/pom.xml @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${module-dir} + + + diff --git a/archetypes/helidon/src/main/archetype/common/packaging.xml b/archetypes/helidon/src/main/archetype/common/packaging.xml index e7986fbd8a2..061b88f1059 100644 --- a/archetypes/helidon/src/main/archetype/common/packaging.xml +++ b/archetypes/helidon/src/main/archetype/common/packaging.xml @@ -39,11 +39,26 @@ | port:8080 | + | | | path: /greet | + +--------------------+ +-------------------+ diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/client/README.md.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/client/README.md.mustache new file mode 100644 index 00000000000..18d200e57c5 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/client/README.md.mustache @@ -0,0 +1,16 @@ +# Helidon OCI Archetype Client using MP + +This module demonstrates how to generate a Helidon Microprofile restful microservice-based client, using OpenApi tool, that communicates with a Helidon MP service endpoint. + +1. Client-side source code will be generated using OpenApi tool based on an OpenApi specification document in the form +of [api.yaml](../spec/api.yaml) as an input. The generated source code will be located in +target.generated-sources.client.src.main.java.{{package}}.client and will have the following components: + * A microprofile rest client interface (that can be registered with CDI). Please check out + [Microprofile Rest Client](https://helidon.io/docs/v3/#/mp/restclient) for more + information about this concept. + * A Json-based request/response model. +2. The generated Microprofile rest client interface called target.generated-sources.client.src.main.java.{{package}}.client.api.GreetApi +then can be injected using `@RestClient` or initialized using `RestClientBuilder` by end user application along with generated model classes for the request/response. + +## Generator Configuration +The generator configuration can be customized in [pom.xml](pom.xml). See [documentation](https://openapi-generator.tech/docs/generators/java) for detailed information on each option. \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/client/pom.xml.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/client/pom.xml.mustache new file mode 100644 index 00000000000..8ae521ff492 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/client/pom.xml.mustache @@ -0,0 +1,86 @@ + + + 4.0.0 + + {{groupId}} + {{parent-artifactId}} + {{project-version}} + + {{client-artifactId}} + {{project-version}} + + + + io.helidon.microprofile.rest-client + helidon-microprofile-rest-client + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + org.glassfish.jersey.media + jersey-media-json-jackson + + + org.openapitools + jackson-databind-nullable + + + io.helidon.microprofile.config + helidon-microprofile-config + runtime + + + + + + + org.jboss.jandex + jandex-maven-plugin + + + make-index + + + + + org.openapitools + openapi-generator-maven-plugin + + + generate-client + + generate + + + ${skipOpenApiGenerate} + ${project.basedir}/../spec/api.yaml + java-helidon-client + false + false + false + false + ${project.build.directory}/generated-sources/client + + {{package}}.client.api + GreetClient + false + {{helidon-version}} + mp + {{package}}.client.model + jackson + + + + + + + + diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/pom.xml.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/pom.xml.mustache new file mode 100644 index 00000000000..e7dfb985b21 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/pom.xml.mustache @@ -0,0 +1,62 @@ + + 4.0.0 + + io.helidon.applications + helidon-applications + {{helidon-version}} + + + {{groupId}} + {{parent-artifactId}} + {{project-version}} + pom + + + 0.2.3 + 1.1.0 + 6.2.1 + + + + + + org.openapitools + jackson-databind-nullable + ${version.lib.jackson.databind.nullable} + + + + + + + + + org.jboss.jandex + jandex-maven-plugin + ${version.plugin.jandex} + + + make-index + + jandex + + process-classes + + + + + org.openapitools + openapi-generator-maven-plugin + ${version.plugin.openapi} + + + + + + + client + server + + diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/README.md.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/README.md.mustache new file mode 100644 index 00000000000..d986efac941 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/README.md.mustache @@ -0,0 +1,247 @@ +# Helidon OCI Archetype Server using MP + +This module demonstrates a simple Hello World JAX-RS based application and is composed of the following: + +1. Server-side source code that will be generated using OpenApi tool based on an OpenApi specification document in the form + of [api.yaml](../spec/api.yaml) as an input. The generated source code will be located in + target.generated-sources.server.src.main.java.{{package}}.server and will have the following components: + * A JAX-RS base interface + * A model source code that will represent a JSON object +2. A server application that will implement the generated JAX-RS base interface to add a simple hello world +greet logic. Furthermore, it will also include OCI SDK integration with OCI Logging and Metrics. +3. It also showcases how to use generated [client](../client) to test this server application. + +## OCI SDK integration +Helidon provides easy integration with the OCI SDK by injecting SDK clients. This server application provides a sample +demonstration for both the OCI Monitoring and Logging SDK in src.main.java.{{package}}.server.GreetResource.java with simple annotations like below: +```java + @Inject + public GreetResource(Monitoring monitoringClient, Logging loggingClient, ...) +``` +Authentication can be configured and is explained in [Application Configuration](#application-configuration) +section with the use of `oci.auth-strategy` property in [microprofile-config.properties](src/main/resources/META-INF/microprofile-config.properties). +If not specified, it will default to `auto` which will cycle through all the authentication types until one succeeds. + +To enable this feature, the `helidon-integrations-oci-sdk-cdi` artifact needs to be +added as a dependency in the application's [pom.xml](pom.xml): +```xml + + + io.helidon.integrations.oci.sdk + helidon-integrations-oci-sdk-cdi + runtime + +``` +Along with this dependency, the OCI SDK common library and the OCI service library that's going to be used also +needs to be added. For example, to integrate with OCI logging, below is the example of the dependency declaration: +```xml + + com.oracle.oci.sdk + oci-java-sdk-common + compile + + + com.oracle.oci.sdk + oci-java-sdk-loggingingestion + compile + +``` + +## Custom Logs Monitoring +This Server application can also be configured to demonstrate OCI Custom Logs Monitoring using Unified Monitoring Agent +(not part of Helidon). It was added in this project to demonstrate logging processor (collect and send to logging service) capabilities. + +To set this up, please see the details in [Creating Custom Logs](https://docs.oracle.com/en-us/iaas/Content/Logging/Concepts/custom_logs.htm#creating_custom_logs). +See [OCI IAM Setup for Custom Logs](#oci-iam-setup-for-custom-logs) section below as well. After this exercise, it is expected that +a Log Group and Log OCI resources had been created. Please take note of the custom log that got created as its used in this configuration +setup as it will be used in the next section. Furthermore, Helidon logging also needs to be set up so that the log data can be persisted +into a file that was designated to be the log file that the Unified Monitoring Agent will process. Below is an example of the configuration +that needs to be set up in [logging.properties](src/main/resources/logging.properties). + +```properties +handlers=io.helidon.common.HelidonConsoleHandler, java.util.logging.FileHandler +java.util.logging.FileHandler.pattern=%h/helidon_log/helidon.log +java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter +``` + +The use of `java.util.logging.FileHandler` as a handler and defining the `java.util.logging.FileHandler.pattern` will +make the application save all the log data into ${HOME}/helidon_log/helidon.log which will then be monitored and +processed by the Unified Monitoring Agent. + +### OCI IAM Setup for Custom Logs +1. Using User Principal authentication + 1. Create oci config by generating + [API Signing Key](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm) for the IAM user who + will be responsible for publishing logs and metrics. + 2. Create a Group (ex.: `LogMetricPublisher`) and add the User to it. See + [Managing Groups](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managinggroups.htm#) for more + information. + 3. Create a Policy using the group from the previous step to allow metrics to be published. For logging, use the + compartment that was designated as the logging compartment. More details can be found here: + https://docs.oracle.com/en-us/iaas/Content/Identity/Reference/monitoringpolicyreference.htm#Details_for_Monitoring + * Metrics Policy: + ``` + Allow group LogMetricPublisher to use metrics in compartment LogMetricCompartment + ``` + * Logging Policy: + ``` + Allow group LogMetricPublisher to use log-content in compartment LogMetricCompartment + ``` +2. Using Instance Principal authentication on an OCI compute instance. More details can be found in + [Calling Services from an Instance](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm). + 1. Create a dynamic group for the compartment where the Compute instance will be created. + ``` + Any {instance.compartment.id = 'ocid1.compartment.oc1..mycompartmentocid'} + ``` + 2. Create policies to allow use (read/write) of metrics and logging. + * Metrics Policy: + ``` + Allow dynamic-group helidondev to use metrics in compartment LogMetricCompartment + ``` + * Logging Policy: + ``` + Allow dynamic-group dynamicgroup1 to use log-content in compartment LogMetricCompartment + ``` + +## Helidon MP Metrics to OCI +Helidon generated and recorded metrics can be transmitted to the +[OCI Monitoring service](https://docs.oracle.com/en-us/iaas/Content/Monitoring/Concepts/monitoringoverview.htm) by +adding the following configuration in +[src/main/resources/META-INF/microprofile-config.properties](src/main/resources/META-INF/microprofile-config.properties): + +```properties +# OCI compartment ID where the metrics will be sent +ocimetrics.compartmentId= +# OCI metric namespace +ocimetrics.namespace= +# Delay in seconds before the 1st metrics transmission to OCI takes place. Defaults to 1 second if not specified. +ocimetrics.initialDelay=30 +# Interval in seconds between metrics transmission to OCI. Defaults to 60 seconds if not specified. +ocimetrics.delay=180 +# Filter only the scopes that will be sent to OCI. This is optional and will default to all scopes if not specified. +ocimetrics.scopes.0=base +ocimetrics.scopes.1=vendor +ocimetrics.scopes.2=application +# Enable or disable metric transmission to OCI. Defaults to true if not specified. +ocimetrics.enabled=true +``` + +Alternatively, this can also be configured in yaml format and added to [src/main/resources/application.yaml](src/main/resources/application.yaml): + +```yaml +ocimetrics: + # OCI compartment ID where the metrics will be sent + compartmentId: + # OCI metric namespace + namespace: + # Delay in seconds before the 1st metrics transmission to OCI takes place. Defaults to 1 second if not specified. + initialDelay: 30 + # Interval in seconds between metrics transmission to OCI. Defaults to 60 seconds if not specified. + delay: 180 + # Filter only the scopes that will be sent to OCI. This is optional and will default to all scopes if not specified. + scopes: [base, vendor, application] + # Enable or disable metric transmission to OCI. Defaults to true if not specified. + enabled: true +``` + +Along with the above configuration setting, the `helidon-oci-integrations-metrics` artifact needs to be added as a +dependency in the application's [pom.xml](pom.xml): + +```xml + + + io.helidon.oci.integrations + helidon-oci-integrations-metrics + +``` + +For more details about the Helidon metrics, please check out the [Helidon MP Metrics Guide](https://helidon.io/docs/v3/#/mp/guides/metrics) +particularly the following relevant sections: +1. `Controlling Metrics Behavior` - has various options to manage the behaviour of the helidon metrics +2. `Application-Specific Metrics Data` - allows application-specific metrics to be created using CDI. + +As part of the example, some of the methods in src.main.java.{{package}}.server.GreetResource.java +where annotated with Application-Specific metrics such as @Counted, @Metered and @Timed as shown below: +```java + @Counted(name = "getDefaultMessage", absolute = true) + @Override + public GreetResponse getDefaultMessage() { + LOGGER.info("getDefaultMessage() is invoked"); + publishMetricAndLog("getDefaultMessage"); + return createGreetResponse("World"); + } + + @Metered(absolute = true, unit = MetricUnits.MILLISECONDS) + @Override + public GreetResponse getMessage(String name) { + LOGGER.info("getMessage(" + name + ") is invoked"); + publishMetricAndLog("getMessage"); + return createGreetResponse(name); + } + + @Timed(name = "updateGreeting", absolute = true, unit = MetricUnits.MILLISECONDS) + @Override + public void updateGreeting(@Valid @NotNull GreetUpdate body) { + LOGGER.info("updateGreeting(greeting: " + body.getGreeting() + ") is invoked"); + greetingProvider.setMessage(body.getGreeting()); + publishMetricAndLog("updateGreeting"); + } +``` + +## Health Checks +Helidon supports built-in and custom liveness and readiness health checks. Refer to +[MicroProfile Health](https://helidon.io/docs/v3/#/mp/health) for an overview and how to set up this +feature. For more details on how to use it including creating custom health checks, check out +[Helidon MP Health Check Guide](https://helidon.io/docs/v3/#/mp/guides/health). +src.main.java.{{package}}.server.GreetLivenessCheck.java and src.main.java.{{package}}.server.GreetReadinessCheck.java had been added +in the application to demonstrate custom liveness and readiness check, respectively. Liveness can be retrieved via +`/health/live` and readiness via `/health/ready`. Check out [Run and exercise the application](#run-and-exercise-the-application) +for examples of retrieving health checks statuses. + +## Application Configuration: +The application configuration can be customized in +[src/main/resources/META-INF/microprofile-config.properties](src/main/resources/META-INF/microprofile-config.properties). +and currently has the following parameters: +1. `app.greeting` - The greeting word and currently set to `Hello` +2. `server.host` - Host IP address of the server application and currently set to accept all at `0.0.0.0` +3. `server.port` - Host port of the server application and currently set to `8080` +4. `metrics.rest-request.enabled` - Enables rest request metrics and currently set `true`. Please see [Controlling REST.request Metrics](https://helidon.io/docs/v3/#/mp/guides/metrics#controlling-rest-request-metrics) for more information. +5. `oci.monitoring.compartmentId` - Compartment Id used for the sending custom metrics. Please see [Publishing Custom Metrics](https://docs.oracle.com/en-us/iaas/Content/Monitoring/Tasks/publishingcustommetrics.htm#Publishing_Custom_Metrics) for more details. +6. `oci.monitoring.namespace` - Monitoring namespace configured for sending metrics. Please see [Publishing Custom Metrics](https://docs.oracle.com/en-us/iaas/Content/Monitoring/Tasks/publishingcustommetrics.htm#Publishing_Custom_Metrics) for more information. +7. `oci.logging.id` - Custom log id configured. Please see [Custom Logs Monitoring](#Custom-Logs-Monitoring) for more information. +8. `oci.auth-strategy` - Allows OCI client authentication mechanism to be specified and can either be an individual +value or a list of authentication types separated by comma. If specified as a list, it will cycle through each until a +successful authentication is reached. This is currently set to `config_file,instance_principals,resource_principal` +which means that `config_file` will be tried first, then falls back to `instance_principals` if it fails, and +eventually falls back to `resource_principals` if `instance_principals` fails. The following are the different types +of OCI client authentication: + * `config_file` - Uses user authentication set in ~/.oci/config + * `config` - Sets user authentication in the helidon config, i.e. microprofile-config.properties + * `instance_principals` - Uses the compute instance as the authentication and authorization principal. Please see +[Calling Services from an Instance](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm) +for more details. + * `resource_principal` - Very similar to instance principal auth but uses OCI resources and services as the +authentication and authorization principal such as serverless functions. Please see +[About Using Resource Principal to Access Oracle Cloud Infrastructure Resources](https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/resource-principal-about.html#GUID-7EED5198-2C92-41B6-99DD-29F4187CABF5) for more information. + +Values of parameters in microprofile-config.properties (e.g., dev, test, prod) can also be overridden in a variety of +ways: +1. Using `config profiles` is a good way of running or testing multiple scenarios that require different property values. +Please see [Helidon Config Profiles Example](https://github.com/oracle/helidon/tree/master/examples/config/profiles) +for more details. This allows users to create a new profile in another file with the format +`microprofile-config<-ProfileName>.properties` and can then be switched to become the active profile by adding +`-dconfig.profile=ProfileName` when running the application. For example, in the section +[Run and exercise the application](#run-and-exercise-the-application), there are 2 options of running the application +by either using `-dconfig.profile=test` or `-dconfig.profile=prod` profile. Running with those profile options +will correspond to using specified properties in +[microprofile-config-test.properties](src/main/resources/META-INF/microprofile-config-test.properties) or +[microprofile-config-prod.properties](src/main/resources/META-INF/microprofile-config-prod.properties), respectively. +Moreover, properties that are not defined in those profiles will default to the ones that already exist in +[microprofile-config.properties](src/main/resources/META-INF/microprofile-config.properties). +2. Using [Environment Variables Mapping Rules](https://download.eclipse.org/microprofile/microprofile-config-2.0/microprofile-config-spec-2.0.html#default_configsources.env.mapping) +is another option that allows values of existing properties in the config file to be replaced. For example if you want +to replace the configured value of `server.port` (currently set to `8080`), all you need to do is set the +`SERVER_PORT` environment variable to the desired value: + ``` + SERVER_PORT=8888 java -jar target/{{artifactId}}-server.jar + ``` \ No newline at end of file diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetLivenessCheck.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetLivenessCheck.java.mustache new file mode 100644 index 00000000000..aebc0d91f0e --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetLivenessCheck.java.mustache @@ -0,0 +1,20 @@ +package {{package}}.server; + +import jakarta.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 { + private GreetingProvider provider; + + @Override + public HealthCheckResponse call() { + return HealthCheckResponse.named("CustomLivenessCheck") + .up() + .withData("time", System.currentTimeMillis()) + .build(); + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetReadinessCheck.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetReadinessCheck.java.mustache new file mode 100644 index 00000000000..f9ab55e8137 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetReadinessCheck.java.mustache @@ -0,0 +1,41 @@ +package {{package}}.server; + +import java.time.Duration; +import java.util.concurrent.atomic.AtomicLong; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.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("CustomReadinessCheck") + .up() + .withData("time", readyTime.get()) + .build(); + } + + public void onStartUp( + @Observes @Initialized(ApplicationScoped.class) Object init) { + readyTime = new AtomicLong(System.currentTimeMillis()); + } + + /** + * Become ready after 5 seconds + * + * @return true if application ready + */ + private boolean isReady() { + return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 5; + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetResource.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetResource.java.mustache new file mode 100644 index 00000000000..aa5896b0fd2 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetResource.java.mustache @@ -0,0 +1,235 @@ +package {{package}}.server; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.time.Instant; +import java.time.LocalDate; +import java.util.logging.Logger; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; + +import com.oracle.bmc.monitoring.Monitoring; +import com.oracle.bmc.monitoring.model.Datapoint; +import com.oracle.bmc.monitoring.model.MetricDataDetails; +import com.oracle.bmc.monitoring.model.PostMetricDataDetails; +import com.oracle.bmc.monitoring.requests.PostMetricDataRequest; + +import com.oracle.bmc.loggingingestion.Logging; +import com.oracle.bmc.loggingingestion.model.LogEntry; +import com.oracle.bmc.loggingingestion.model.LogEntryBatch; +import com.oracle.bmc.loggingingestion.model.PutLogsDetails; +import com.oracle.bmc.loggingingestion.requests.PutLogsRequest; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.metrics.MetricUnits; +import org.eclipse.microprofile.metrics.annotation.Counted; +import org.eclipse.microprofile.metrics.annotation.Metered; +import org.eclipse.microprofile.metrics.annotation.Timed; + +import {{package}}.server.api.GreetService; +import {{package}}.server.model.GreetResponse; +import {{package}}.server.model.GreetUpdate; + +/** + * A simple JAX-RS resource to greet you. Examples: + * + * Get default greeting message: + * curl -X GET http://localhost:8080/greet + * + * Get greeting message for Joe: + * curl -X GET http://localhost:8080/greet/Joe + * + * Change greeting + * curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting + * + * The message is returned as a GreetResource model object generated by OpenApi tool. + */ +@ApplicationScoped +public class GreetResource implements GreetService { + private static final Logger LOGGER = Logger.getLogger(GreetResource.class.getName()); + + // OCI SDK integration of monitoring and logging + private Monitoring monitoringClient; + private Logging loggingClient; + + // Retrieve configuration parameters + private String compartmentId; + private String namespace; + private String loggingId; + + /** + * The greeting message provider. + */ + private final GreetingProvider greetingProvider; + + private String hostName; + + /** + * Using constructor injection to get required configuration. + * By default this gets the value from META-INF/microprofile-config + * + * @param greetingConfig the configured greeting message + */ + @Inject + public GreetResource(Monitoring monitoringClient, Logging loggingClient, + @ConfigProperty(name = "oci.monitoring.compartmentId") String compartmentId, + @ConfigProperty(name = "oci.monitoring.namespace") String namespace, + @ConfigProperty(name = "oci.logging.id") String loggingId, + GreetingProvider greetingConfig) { + LOGGER.info("GreetResource is instantiated"); + this.monitoringClient = monitoringClient; + this.loggingClient = loggingClient; + this.compartmentId = compartmentId; + this.namespace = namespace; + this.loggingId = loggingId; + this.greetingProvider = greetingConfig; + try { + this.hostName = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + this.hostName = "HelidonOCITestHost"; + } + } + + /** + * Return a worldly greeting message via GreetResponse. + * + * @return {@link GreetResponse} + */ + @Counted(name = "getDefaultMessage", absolute = true) + @Override + public GreetResponse getDefaultMessage() { + LOGGER.info("getDefaultMessage() is invoked"); + publishMetricAndLog("getDefaultMessage"); + return createGreetResponse("World"); + } + + /** + * Return a greeting message using the name that was provided. + * + * @param name the name to greet + * @return {@link GreetResponse} + */ + @Metered(absolute = true, unit = MetricUnits.MILLISECONDS) + @Override + public GreetResponse getMessage(String name) { + LOGGER.info("getMessage(" + name + ") is invoked"); + publishMetricAndLog("getMessage"); + return createGreetResponse(name); + } + + /** + * Return a greeting message using the name that was provided. + * + * @param body the name to greet + * @return {@link GreetResponse} + */ + @Timed(name = "updateGreeting", absolute = true, unit = MetricUnits.MILLISECONDS) + @Override + public void updateGreeting(@Valid @NotNull GreetUpdate body) { + LOGGER.info("updateGreeting(greeting: " + body.getGreeting() + ") is invoked"); + greetingProvider.setMessage(body.getGreeting()); + publishMetricAndLog("updateGreeting"); + } + + /** + * Creates GreetResponse POJO that will contain the response data and + * will be processed using Jackson. + * + * @param who the name to greet + * @return {@link GreetResponse} + */ + private GreetResponse createGreetResponse(String who) { + GreetResponse greetResponse = new GreetResponse(); + greetResponse.setMessage(String.format("%s %s!", greetingProvider.getMessage(), who)); + greetResponse.setDate(LocalDate.now()); + return greetResponse; + } + + private void publishMetricAndLog(String methodName) { + publishMetric(methodName); + publishLog(methodName); + } + + /** + * Developers do not need to explicitly publish Helidon metrics (declared using annotations or registered with the + * MetricRegistry explicitly). This method shows how user code could publish their application metrics directly to OCI \ + * metrics. + */ + private void publishMetric(String name) { + // See https://github.com/oracle/oci-java-sdk/blob/v2.14.1/bmc-examples/src/main/java/MonitoringMetricPostExample.java#L72-L121 + List datapoints = + List.of(Datapoint.builder() + .timestamp(Date.from(Instant.now())) + .value(1.0) + .count(1) + .build()); + Map dimensions = + Map.of("host", this.hostName); + + MetricDataDetails metricDataDetails = MetricDataDetails.builder() + .compartmentId(this.compartmentId) + .namespace(this.namespace) + .name(name) + .datapoints(datapoints) + .dimensions(dimensions) + .build(); + + PostMetricDataDetails postMetricDataDetails = PostMetricDataDetails.builder() + .metricData(List.of(metricDataDetails)) + .build(); + + PostMetricDataRequest postMetricDataRequest = PostMetricDataRequest.builder() + .postMetricDataDetails(postMetricDataDetails) + .build(); + + try { + this.monitoringClient.setEndpoint(monitoringClient.getEndpoint().replaceFirst("telemetry\\.", "telemetry-ingestion.")); + this.monitoringClient.postMetricData(postMetricDataRequest); + LOGGER.info("publishMetric successfully sends metric to OCI monitoring service"); + } catch (Exception e) { + LOGGER.warning(String.format( + "Received error while executing MonitoringClient.postMetricData(: %s", e.getMessage())); + } + } + + /** + * A method a user may use to publish logs. + */ + private void publishLog(String name) { + Date entryDateTime = Date.from(Instant.now()); + PutLogsDetails putLogsDetails = PutLogsDetails.builder() + .specversion("1.0") + .logEntryBatches(new ArrayList<>(Arrays.asList(LogEntryBatch.builder() + .entries(new ArrayList<>(Arrays.asList(LogEntry.builder() + .data(String.format("%s was invoked on %tc", name, entryDateTime)) + .id(String.format("helidon-oci-%s", UUID.randomUUID().toString())).build()))) + .source(String.format("helidon-oci-%s", name)) + .type(name) + .subject(String.format("processing-%s", name)) + .defaultlogentrytime(entryDateTime).build()))).build(); + + PutLogsRequest putLogsRequest = PutLogsRequest.builder() + .logId(this.loggingId) + .putLogsDetails(putLogsDetails) + .timestampOpcAgentProcessing(Date.from(Instant.now())) + .build(); + + /* Send request to the Client */ + try { + this.loggingClient.putLogs(putLogsRequest); + LOGGER.info("publishLog() successfully sends log to OCI logging service"); + } catch (Exception e) { + LOGGER.warning( + String.format("Received error while executing LoggingClient.putLogs: %s", e.getMessage())); + } + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetingProvider.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetingProvider.java.mustache new file mode 100644 index 00000000000..2428a8ebb4c --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/GreetingProvider.java.mustache @@ -0,0 +1,34 @@ +package {{package}}.server; + +import java.util.concurrent.atomic.AtomicReference; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +/** + * Provider for greeting message. + */ +@ApplicationScoped +public class GreetingProvider { + private final AtomicReference message = new AtomicReference<>(); + + /** + * Create a new greeting provider, reading the message from configuration. + * + * @param message greeting to use + */ + @Inject + public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) { + this.message.set(message); + } + + String getMessage() { + return message.get(); + } + + void setMessage(String message) { + this.message.set(message); + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/package-info.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/package-info.java.mustache new file mode 100644 index 00000000000..fdb924d01c7 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/java/__pkg__/server/package-info.java.mustache @@ -0,0 +1 @@ +package {{package}}.server; diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-prod.properties b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-prod.properties new file mode 100644 index 00000000000..36aac4f263b --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-prod.properties @@ -0,0 +1,2 @@ +# Oci Authentication method using Instance Principals +oci.auth-strategy=instance_principals diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-test.properties b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-test.properties new file mode 100644 index 00000000000..df287484fa5 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/main/resources/META-INF/microprofile-config-test.properties @@ -0,0 +1,2 @@ +# Oci Authentication method using User Credentials in an oci config file +oci.auth-strategy=config_file diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/Common.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/Common.java.mustache new file mode 100644 index 00000000000..1f6157358a6 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/Common.java.mustache @@ -0,0 +1,25 @@ +package {{package}}.server; + +import {{package}}.client.api.ApiException; +import {{package}}.client.api.GreetApi; +import {{package}}.client.model.GreetUpdate; +import {{package}}.client.model.GreetResponse; + +/** + * Common utilities for all server test classes + */ +class Common { + public static String getDefaultMessage(GreetApi greetApi) throws ApiException { + GreetResponse greetResponse = greetApi.getDefaultMessage(); + return greetResponse.getMessage(); + } + + public static String getMessage(GreetApi greetApi, String path) throws ApiException { + GreetResponse greetResponse = greetApi.getMessage(path); + return greetResponse.getMessage(); + } + + static void updateGreeting(GreetApi greetApi, String newGreeting) throws ApiException { + greetApi.updateGreeting(new GreetUpdate().greeting(newGreeting)); + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceConfigFileTest.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceConfigFileTest.java.mustache new file mode 100644 index 00000000000..b3504d51414 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceConfigFileTest.java.mustache @@ -0,0 +1,46 @@ +package {{package}}.server; + +import java.net.URI; + +import jakarta.inject.Inject; + +import io.helidon.microprofile.server.ServerCdiExtension; +import io.helidon.microprofile.tests.junit5.Configuration; +import io.helidon.microprofile.tests.junit5.HelidonTest; + +import {{package}}.client.api.ApiException; +import {{package}}.client.api.GreetApi; +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@HelidonTest +@Configuration(profile = "test") +class GreetResourceConfigFileTest { + private GreetApi greetApi; + + @Inject + private ServerCdiExtension serverCdiExtension; + @BeforeEach + void beforeEach() { + URI uriInfo = URI.create(String.format("http://localhost:%s/", + serverCdiExtension.port() + )); + greetApi = RestClientBuilder.newBuilder() + .baseUri(uriInfo) + .build(GreetApi.class); + } + + @Test + void testHelloWorld() throws ApiException { + assertThat(Common.getDefaultMessage(greetApi), is("Hello World!")); + assertThat(Common.getMessage(greetApi, "Joe"), is("Hello Joe!")); + + // Change Greeting test + Common.updateGreeting(greetApi, "Hola"); + assertThat(Common.getDefaultMessage(greetApi), is("Hola World!")); + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceInstancePrincipalTest.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceInstancePrincipalTest.java.mustache new file mode 100644 index 00000000000..9e1159be45e --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceInstancePrincipalTest.java.mustache @@ -0,0 +1,47 @@ +package {{package}}.server; + +import java.net.URI; + +import jakarta.inject.Inject; + +import io.helidon.microprofile.server.ServerCdiExtension; +import io.helidon.microprofile.tests.junit5.Configuration; +import io.helidon.microprofile.tests.junit5.HelidonTest; + +import {{package}}.client.api.ApiException; +import {{package}}.client.api.GreetApi; +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@HelidonTest +@Configuration(profile = "prod") +class GreetResourceInstancePrincipalTest { + private GreetApi greetApi; + + @Inject + private ServerCdiExtension serverCdiExtension; + + @BeforeEach + void beforeEach() { + URI uriInfo = URI.create(String.format("http://localhost:%s/", + serverCdiExtension.port() + )); + greetApi = RestClientBuilder.newBuilder() + .baseUri(uriInfo) + .build(GreetApi.class); + } + + @Test + void testHelloWorld() throws ApiException { + assertThat(Common.getDefaultMessage(greetApi), is("Hello World!")); + assertThat(Common.getMessage(greetApi, "Joe"), is("Hello Joe!")); + + // Change Greeting test + Common.updateGreeting(greetApi, "Hola"); + assertThat(Common.getDefaultMessage(greetApi), is("Hola World!")); + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceMockedTest.java.mustache b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceMockedTest.java.mustache new file mode 100644 index 00000000000..90c5697db84 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/server/src/test/java/__pkg__/server/GreetResourceMockedTest.java.mustache @@ -0,0 +1,197 @@ +package {{package}}.server; + +import java.net.URI; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.Alternative; +import jakarta.inject.Inject; + +import io.helidon.microprofile.server.ServerCdiExtension; +import io.helidon.microprofile.tests.junit5.AddBean; +import io.helidon.microprofile.tests.junit5.HelidonTest; + +import com.oracle.bmc.Region; +import com.oracle.bmc.loggingingestion.Logging; +import com.oracle.bmc.loggingingestion.requests.PutLogsRequest; +import com.oracle.bmc.loggingingestion.responses.PutLogsResponse; +import com.oracle.bmc.monitoring.Monitoring; +import com.oracle.bmc.monitoring.MonitoringPaginators; +import com.oracle.bmc.monitoring.MonitoringWaiters; +import com.oracle.bmc.monitoring.requests.*; +import com.oracle.bmc.monitoring.responses.*; +import {{package}}.client.api.ApiException; +import {{package}}.client.api.GreetApi; +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static jakarta.interceptor.Interceptor.Priority.APPLICATION; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@HelidonTest +@AddBean(GreetResourceMockedTest.MockLogging.class) +@AddBean(GreetResourceMockedTest.MockMonitoring.class) +class GreetResourceMockedTest { + private GreetApi greetApi; + + @Inject + private ServerCdiExtension serverCdiExtension; + + private static RuntimeException putLogsException, postMetricDataException = null; + + @BeforeEach + void beforeEach() { + URI uriInfo = URI.create(String.format("http://localhost:%s/", + serverCdiExtension.port() + )); + greetApi = RestClientBuilder.newBuilder() + .baseUri(uriInfo) + .build(GreetApi.class); + } + @Test + void testHelloWorld() throws ApiException { + assertThat(Common.getDefaultMessage(greetApi), is("Hello World!")); + assertThat(Common.getMessage(greetApi, "Joe"), is("Hello Joe!")); + + // Change Greeting test + Common.updateGreeting(greetApi, "Hola"); + assertThat(Common.getDefaultMessage(greetApi), is("Hola World!")); + } + + @Test + void testOciFailureShouldNotCauseInternalError() throws ApiException { + putLogsException = new RuntimeException("Simulate Logging.putLogs Exception"); + postMetricDataException = new RuntimeException("Simulate Logging.postMetricDataException"); + assertThat(Common.getDefaultMessage(greetApi), is("Hello World!")); + // reset exception variables + putLogsException = postMetricDataException = null; + } + + @Alternative + @Priority(APPLICATION + 1) + static class MockLogging implements Logging { + + private String endpoint; + + private MockLogging() { + super(); + } + + @Override + public void close() {} + + @Override + public String getEndpoint() { + return this.endpoint; + } + + @Override + public void setRegion(Region region) {} + + @Override + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + @Override + public void setRegion(String region) {} + + @Override + public void refreshClient() {} + + @Override + public PutLogsResponse putLogs(PutLogsRequest request) { + if (putLogsException != null) { + throw putLogsException; + } + return PutLogsResponse.builder() + .__httpStatusCode__(200) + .build(); + } + } + + @Alternative + @Priority(APPLICATION + 1) + static class MockMonitoring implements Monitoring { + @Override + public void setEndpoint(String s) {} + + @Override + public String getEndpoint() {return "http://www.DummyEndpoint.com";} + + @Override + public void setRegion(Region region) {} + + @Override + public void setRegion(String s) {} + + @Override + public ChangeAlarmCompartmentResponse changeAlarmCompartment(ChangeAlarmCompartmentRequest changeAlarmCompartmentRequest) { + return null; + } + + @Override + public CreateAlarmResponse createAlarm(CreateAlarmRequest createAlarmRequest) {return null;} + + @Override + public DeleteAlarmResponse deleteAlarm(DeleteAlarmRequest deleteAlarmRequest) {return null;} + + @Override + public GetAlarmResponse getAlarm(GetAlarmRequest getAlarmRequest) {return null;} + + @Override + public GetAlarmHistoryResponse getAlarmHistory(GetAlarmHistoryRequest getAlarmHistoryRequest) {return null;} + + @Override + public ListAlarmsResponse listAlarms(ListAlarmsRequest listAlarmsRequest) {return null;} + + @Override + public ListAlarmsStatusResponse listAlarmsStatus(ListAlarmsStatusRequest listAlarmsStatusRequest) { + return null; + } + + @Override + public ListMetricsResponse listMetrics(ListMetricsRequest listMetricsRequest) {return null;} + + @Override + public void refreshClient() {} + + @Override + public PostMetricDataResponse postMetricData(PostMetricDataRequest postMetricDataRequest) { + if (postMetricDataException != null) { + throw postMetricDataException; + } + return PostMetricDataResponse.builder() + .__httpStatusCode__(200) + .build(); + } + + @Override + public RemoveAlarmSuppressionResponse removeAlarmSuppression(RemoveAlarmSuppressionRequest removeAlarmSuppressionRequest) { + return null; + } + + @Override + public RetrieveDimensionStatesResponse retrieveDimensionStates(RetrieveDimensionStatesRequest retrieveDimensionStatesRequest) { + return null; + } + + @Override + public SummarizeMetricsDataResponse summarizeMetricsData(SummarizeMetricsDataRequest summarizeMetricsDataRequest) { + return null; + } + + @Override + public UpdateAlarmResponse updateAlarm(UpdateAlarmRequest updateAlarmRequest) {return null;} + + @Override + public MonitoringWaiters getWaiters() {return null;} + + @Override + public MonitoringPaginators getPaginators() {return null;} + + @Override + public void close() {} + } +} diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/spec/README.md b/archetypes/helidon/src/main/archetype/mp/oci/files/spec/README.md new file mode 100644 index 00000000000..09207f1a8e9 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/spec/README.md @@ -0,0 +1,5 @@ +# OpenAPI Specification Document + +This module contains an [OpenApi v3 specification](https://spec.openapis.org/oas/v3.0.0) document in the form of +[api.yaml](api.yaml) that will be used by both the [server](../server/README.md) +and [client](../client/README.md) modules to generate Server API and Client code, respectively. diff --git a/archetypes/helidon/src/main/archetype/mp/oci/files/spec/api.yaml b/archetypes/helidon/src/main/archetype/mp/oci/files/spec/api.yaml new file mode 100644 index 00000000000..15d50a6f733 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/files/spec/api.yaml @@ -0,0 +1,69 @@ +info: + title: Hello World Greet Helidon MP Application + version: '1.0' +openapi: 3.0.3 +paths: + /greet: + get: + summary: Gets default greet message + operationId: getDefaultMessage + tags: + - greet + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GreetResponse' + description: OK + /greet/{name}: + get: + summary: Gets message based on the parameter name + operationId: getMessage + tags: + - greet + parameters: + - in: path + name: name + required: true + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GreetResponse' + description: OK + /greet/greeting: + put: + summary: Set the greeting to use in future messages. + operationId: updateGreeting + tags: + - greet + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GreetUpdate' + required: true + responses: + '204': + description: Greeting updated + '400': + description: JSON body content did not contain setting for 'greeting' +components: + schemas: + GreetResponse: + properties: + message: + type: string + date: + format: date + type: string + type: object + GreetUpdate: + properties: + greeting: + type: string + type: object diff --git a/archetypes/helidon/src/main/archetype/mp/oci/oci-mp.xml b/archetypes/helidon/src/main/archetype/mp/oci/oci-mp.xml new file mode 100644 index 00000000000..f83170137e1 --- /dev/null +++ b/archetypes/helidon/src/main/archetype/mp/oci/oci-mp.xml @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + server + true + + + false + true + false + false + true + false + + + + + + + files + + **/*.mustache + + + + ../common/files + + src/main/resources/** + + + + +oci.monitoring.namespace= + +# OCI Logging configuration +oci.logging.id= + +# OCI Authentication strategy +oci.auth-strategy=config_file,instance_principals,resource_principal + ]]> + + + + # OCI metric namespace + namespace: + # Delay in seconds before the 1st metrics transmission to OCI takes place. Defaults to 1 second if not specified. + initialDelay: 10 + # Interval in seconds between metrics transmission to OCI. Defaults to 60 seconds if not specified. + delay: 180 + # Filter only the scopes that will be sent to OCI. This is optional and will default to all scopes if not specified. + scopes: [base, vendor, application] + # Enable or disable metric transmission to OCI. Defaults to true if not specified. + enabled: true + ]]> + + + + + + + + + files + + server/src/main/resources + spec + + + + ${artifactId}-parent + ${artifactId}-client + ${artifactId}-server + ${groupId} + ${version} + io.helidon.microprofile.cdi.Main + + + io.helidon.microprofile.bundles + helidon-microprofile-core + + + io.helidon.microprofile.cdi + helidon-microprofile-cdi + + + jakarta.enterprise + jakarta.enterprise.cdi-api + + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.openapitools + jackson-databind-nullable + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + org.glassfish.jersey.media + jersey-media-json-jackson + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + io.helidon.microprofile.health + helidon-microprofile-health + + + io.helidon.microprofile.metrics + helidon-microprofile-metrics + + + io.helidon.integrations.oci.sdk + helidon-integrations-oci-sdk-cdi + + + com.oracle.oci.sdk + oci-java-sdk-common + + + com.oracle.oci.sdk + oci-java-sdk-loggingingestion + + + com.oracle.oci.sdk + oci-java-sdk-monitoring + + + io.helidon.integrations.oci.metrics + helidon-integrations-oci-metrics-cdi + runtime + + + org.jboss + jandex + runtime + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + io.helidon.microprofile.tests + helidon-microprofile-tests-junit5 + test + + + ${groupId} + ${artifactId}-client + ${version} + + + + + org.jboss.jandex + jandex-maven-plugin + + + make-index + + + + + org.openapitools + openapi-generator-maven-plugin + + + generate-server + + generate + + + ${skipOpenApiGenerate} + ${project.basedir}/../spec/api.yaml + java-helidon-server + false + false + false + false + ${project.build.directory}/generated-sources/server + + {{package}}.server.api + false + {{helidon-version}} + mp + {{package}}.server.model + jackson + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*MockedTest + + + ]]> + + + + + test + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ConfigFileTest + + + + + + + + prod + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*InstancePrincipalTest + + + + + + + ]]> + + + + + + + + + + +``` + +Mount this volume as part of your application containers specification +```yaml + volumeMounts: + - mountPath: /root/.oci + name: oci-config +``` + ]]> + + + client/pom.xml + server/pom.xml + + + client/src + server/src + spec/api.yaml + + + + diff --git a/archetypes/helidon/src/main/archetype/se/custom/database.xml b/archetypes/helidon/src/main/archetype/se/custom/database.xml index 8c51adf0571..77eef5c0fe8 100644 --- a/archetypes/helidon/src/main/archetype/se/custom/database.xml +++ b/archetypes/helidon/src/main/archetype/se/custom/database.xml @@ -37,7 +37,7 @@ url: jdbc:h2:tcp://localhost:1521/test h2 H2 - + url: jdbc:mysql:tcp://127.0.0.1:3306/pokemon?useSSL=false helidon-integrations-db-mysql MySQL - + url: jdbc:oracle:thin:@localhost:1521/XE ojdbc OracleDB - + Helidon SE application that uses the dbclient API with MongoDB database. - +