diff --git a/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java b/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java index 6f693c25344..798869862a3 100644 --- a/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java +++ b/starter-core/src/main/java/io/micronaut/starter/build/dependencies/MicronautDependencyUtils.java @@ -42,6 +42,7 @@ public final class MicronautDependencyUtils { public static final String GROUP_ID_MICRONAUT_GCP = "io.micronaut.gcp"; public static final String GROUP_ID_MICRONAUT_KAFKA = "io.micronaut.kafka"; public static final String GROUP_ID_MICRONAUT_OCI = "io.micronaut.oraclecloud"; + public static final String GROUP_ID_MICRONAUT_OPENSEARCH = "io.micronaut.opensearch"; public static final String GROUP_ID_MICRONAUT_SERDE = "io.micronaut.serde"; public static final String GROUP_ID_MICRONAUT_REACTOR = "io.micronaut.reactor"; public static final String GROUP_ID_MICRONAUT_SECURITY = "io.micronaut.security"; @@ -219,6 +220,11 @@ public static Dependency.Builder ociDependency() { return micronautDependency(GROUP_ID_MICRONAUT_OCI); } + @NonNull + public static Dependency.Builder opensearchDependency() { + return micronautDependency(GROUP_ID_MICRONAUT_OPENSEARCH); + } + @NonNull public static Dependency.Builder platformDependency() { return micronautDependency(GROUP_ID_MICRONAUT_PLATFORM); diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java new file mode 100644 index 00000000000..f82aa0cb809 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchAmazon.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchAmazon extends OpenSearchFeature { + + public static final String NAME = "opensearch-amazon"; + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "Open Search Amazon"; + } + + @Override + public String getDescription() { + return "Adds support for Amazon OpenSearch Service"; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java new file mode 100644 index 00000000000..a81b625b8de --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchContributingTestContainerDependency.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.build.dependencies.Dependency; +import io.micronaut.starter.feature.testcontainers.ContributingTestContainerDependency; + +import java.util.Collections; +import java.util.List; + +public interface OpenSearchContributingTestContainerDependency extends ContributingTestContainerDependency { + + @Override + default List testContainersDependencies() { + return Collections.singletonList(Dependency.builder() + .groupId("org.opensearch") + .artifactId("opensearch-testcontainers") + .test() + .build()); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java new file mode 100644 index 00000000000..969a81c1013 --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchFeature.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.application.ApplicationType; +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils; +import io.micronaut.starter.feature.Category; +import io.micronaut.starter.feature.Feature; + +public abstract class OpenSearchFeature implements Feature, OpenSearchContributingTestContainerDependency { + + @Override + public boolean supports(ApplicationType applicationType) { + return true; + } + + @Override + public String getMicronautDocumentation() { + return "https://micronaut-projects.github.io/micronaut-opensearch/latest/guide/"; + } + + @Override + public String getThirdPartyDocumentation() { + return "https://opensearch.org/docs/latest/clients/java/"; + } + + @Override + public String getCategory() { + return Category.SEARCH; + } + + @Override + public void apply(GeneratorContext generatorContext) { + generatorContext.addDependency(MicronautDependencyUtils + .opensearchDependency() + .artifactId("micronaut-" + getName()) + .compile()); + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java new file mode 100644 index 00000000000..59359833dbf --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchHttpClient5.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchHttpClient5 extends OpenSearchFeature { + + public static final String NAME = "opensearch-httpclient5"; + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "OpenSearch HttpClient 5"; + } + + @Override + public String getDescription() { + return "Adds support for OpenSearch using Apache HttpClient 5 Transport"; + } +} diff --git a/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java new file mode 100644 index 00000000000..e0a7ee413df --- /dev/null +++ b/starter-core/src/main/java/io/micronaut/starter/feature/opensearch/OpenSearchRestClient.java @@ -0,0 +1,60 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.starter.feature.opensearch; + +import io.micronaut.starter.application.generator.GeneratorContext; +import io.micronaut.starter.feature.FeatureContext; +import io.micronaut.starter.feature.json.JacksonDatabindFeature; +import jakarta.inject.Singleton; + +@Singleton +public class OpenSearchRestClient extends OpenSearchFeature { + + public static final String NAME = "opensearch-restclient"; + + private final JacksonDatabindFeature jacksonDatabindFeature; + + public OpenSearchRestClient(JacksonDatabindFeature jacksonDatabindFeature) { + this.jacksonDatabindFeature = jacksonDatabindFeature; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getTitle() { + return "OpenSearch REST Client"; + } + + @Override + public void apply(GeneratorContext generatorContext) { + super.apply(generatorContext); + } + + @Override + public void processSelectedFeatures(FeatureContext featureContext) { + if (!featureContext.isPresent(JacksonDatabindFeature.class)) { + featureContext.addFeature(jacksonDatabindFeature); + } + } + + @Override + public String getDescription() { + return "Adds support for OpenSearch RestClient-based transport"; + } +} diff --git a/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy b/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy new file mode 100644 index 00000000000..89146c21973 --- /dev/null +++ b/starter-core/src/test/groovy/io/micronaut/starter/feature/opensearch/OpenSearchFeatureSpec.groovy @@ -0,0 +1,67 @@ +package io.micronaut.starter.feature.opensearch + +import io.micronaut.starter.ApplicationContextSpec +import io.micronaut.starter.BuildBuilder +import io.micronaut.starter.build.BuildTestUtil +import io.micronaut.starter.build.BuildTestVerifier +import io.micronaut.starter.build.dependencies.MicronautDependencyUtils +import io.micronaut.starter.build.dependencies.Scope +import io.micronaut.starter.feature.Category +import io.micronaut.starter.feature.database.TestContainers +import io.micronaut.starter.fixture.CommandOutputFixture +import io.micronaut.starter.options.BuildTool + +class OpenSearchFeatureSpec extends ApplicationContextSpec implements CommandOutputFixture { + + void 'test opensearch feature #opensearchFeature.name contributes dependencies for #buildTool'(OpenSearchFeature opensearchFeature, BuildTool buildTool) { + given: + String template = new BuildBuilder(beanContext, buildTool) + .features([opensearchFeature.name]) + .render() + when: + String groupId = MicronautDependencyUtils.GROUP_ID_MICRONAUT_OPENSEARCH + String artifactId = "micronaut-" + opensearchFeature.getName() + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + + then: + verifier.hasDependency(groupId, artifactId) + if (opensearchFeature instanceof OpenSearchRestClient) { + assert verifier.hasDependency("io.micronaut", "micronaut-jackson-databind") + } + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void 'test opensearch feature #opensearchFeature.name contributes testcontainers dependencies for #buildTool'(OpenSearchFeature opensearchFeature, BuildTool buildTool) { + given: + String template = new BuildBuilder(beanContext, buildTool) + .features([opensearchFeature.name, TestContainers.NAME]) + .render() + when: + BuildTestVerifier verifier = BuildTestUtil.verifier(buildTool, template) + + then: + verifier.hasDependency("org.opensearch", "opensearch-testcontainers", Scope.TEST) + verifier.hasDependency("org.testcontainers", "testcontainers", Scope.TEST) + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void "test opensearch feature #opensearchFeature.name is search engine category"(OpenSearchFeature opensearchFeature) { + expect: + Category.SEARCH == opensearchFeature.getCategory() + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } + + void "test opensearch feature #opensearchFeature.name documentation links"(OpenSearchFeature opensearchFeature) { + expect: + opensearchFeature.getMicronautDocumentation() == 'https://micronaut-projects.github.io/micronaut-opensearch/latest/guide/' + opensearchFeature.getThirdPartyDocumentation() == 'https://opensearch.org/docs/latest/clients/java/' + + where: + [opensearchFeature, buildTool] << [beanContext.getBeansOfType(OpenSearchFeature), BuildTool.values()].combinations() + } +}