diff --git a/examples/pico/README.md b/examples/pico/README.md new file mode 100644 index 00000000000..ebec97c4343 --- /dev/null +++ b/examples/pico/README.md @@ -0,0 +1,12 @@ + +# Helidon Pico Examples + +Each subdirectory contains example code that highlights specific aspects of +Helidon Pico. + +Suggested path to follow: +1. [basics](./basics) +2. [providers](./providers) +3. [configdriven](./configdriven) +4. [interceptors](./interceptors) +5. [application](./application) diff --git a/examples/pico/application/README.md b/examples/pico/application/README.md new file mode 100644 index 00000000000..2d68bb49021 --- /dev/null +++ b/examples/pico/application/README.md @@ -0,0 +1,50 @@ +# Helidon Pico Application Example + +This example shows how a multi-module application can be created using Helidon Pico. The +[Main.java](./src/main/java/io/helidon/examples/pico/application/Main.java) class shows: + +* multi-module usage (i.e., this module amalgamates [basics](../basics), [providers](../providers), [configdriven](../configdriven), and [interceptors](../interceptors) ). +* compile-time generation of the DI model for the entire multi-module project using the _pico-maven-plugin_ (see [pom.xml](./pom.xml)). +* TestingSupport in [ApplicationTest](src/test/java/io/helidon/examples/pico/application/PicoApplicationTest.java) + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-pico-application.jar +``` + +Expected Output: +``` +Startup service providers (ranked according to weight, pre-activated): [ToolBox:INIT, CircularSaw:INIT, NailGun:INIT, TableSaw:INIT] +Highest weighted service provider: NailGun:INIT +----- +Nail Gun: (nail provider=NailProvider:INIT); initialized +Highest weighted service provider (after activation): io.helidon.examples.pico.providers.NailGun@7cbd9d24 +----- +Preferred Big Tool: Big Hammer +Optional Little Hammer: Optional[Little Hammer] +----- +ToolBox Contents: +Hammer:INIT +BigHammer:ACTIVE +LittleHammer:ACTIVE +Drill{root}:PENDING +AngleGrinderSaw:INIT +CircularSaw:INIT +HandSaw:INIT +NailGun:ACTIVE +TableSaw:INIT +----- +io.helidon.examples.pico.providers.CircularSaw:: will be injected with Optional.empty +Circular Saw: (blade=null); initialized +io.helidon.examples.pico.providers.TableSaw:: will be injected with Optional[LARGE Blade] +Table Saw: (blade=LARGE Blade); initialized +All service providers (after all activations): [ToolBox:ACTIVE, CircularSaw:ACTIVE, NailGun:ACTIVE, TableSaw:ACTIVE] +----- +Service lookup count: 2 +``` + +While the output of this example may look similar to the previous [providers](../providers) example, the implementation is different since this example builds (at compile time) [Application.java](target/generated-sources/annotations/io/helidon/examples/pico/application/Pico$$Application.java). This establishes direct bindings to each and every injection point in your application avoiding runtime resolution with the exception for truly dynamic runtime providers (i.e., anything that is config-driven services or _Provider_ type implementations). + +Note that the lookup count is 2 based upon the direct lookup calls used in the delegated [Main](../basics/src/main/java/io/helidon/examples/pico/basics/Main.java). diff --git a/examples/pico/application/pom.xml b/examples/pico/application/pom.xml new file mode 100644 index 00000000000..6d69509e3d1 --- /dev/null +++ b/examples/pico/application/pom.xml @@ -0,0 +1,117 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-nima + 4.0.0-SNAPSHOT + ../../../applications/nima/pom.xml + + io.helidon.examples.pico + helidon-examples-pico-application + Helidon Pico Examples Application + + + Example usages of a Pico Application. + + + + io.helidon.examples.pico.providers.Main + + + + + io.helidon.examples.pico + helidon-examples-pico-providers + ${helidon.version} + + + io.helidon.examples.pico + helidon-examples-pico-configdriven + ${helidon.version} + + + jakarta.annotation + jakarta.annotation-api + provided + + + org.hamcrest + hamcrest-all + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.helidon.pico + helidon-pico-testing + test + + + + + + + io.helidon.pico + helidon-pico-maven-plugin + ${helidon.version} + + + compile + compile + + application-create + + + + testCompile + test-compile + + test-application-create + + + + + io.helidon.examples.pico.application + + NAMED + + io.helidon.examples.pico.providers.BladeProvider + io.helidon.examples.pico.providers.NailProvider + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + diff --git a/examples/pico/application/src/main/java/io/helidon/examples/pico/application/Main.java b/examples/pico/application/src/main/java/io/helidon/examples/pico/application/Main.java new file mode 100644 index 00000000000..e1226b1246b --- /dev/null +++ b/examples/pico/application/src/main/java/io/helidon/examples/pico/application/Main.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.application; + +import io.helidon.pico.api.Metrics; +import io.helidon.pico.api.PicoServices; + +/** + * Application example. Uses the same {@code main()} as {@link io.helidon.examples.pico.basics.Main}. + */ +public class Main extends io.helidon.examples.pico.basics.Main { + + /** + * Executes the example. + * + * @param args arguments + */ + public static void main(String... args) { + io.helidon.examples.pico.basics.Main.main(args); + + Metrics metrics = PicoServices.picoServices().orElseThrow().metrics().get(); + System.out.println("Service lookup count: " + metrics.lookupCount().get()); + } + +} diff --git a/examples/pico/application/src/main/java/io/helidon/examples/pico/application/package-info.java b/examples/pico/application/src/main/java/io/helidon/examples/pico/application/package-info.java new file mode 100644 index 00000000000..27ac09e0919 --- /dev/null +++ b/examples/pico/application/src/main/java/io/helidon/examples/pico/application/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Examples of multi-module Application generation in Pico. + */ +package io.helidon.examples.pico.application; diff --git a/examples/pico/application/src/main/resources/logging.properties b/examples/pico/application/src/main/resources/logging.properties new file mode 100644 index 00000000000..bd06e0ed087 --- /dev/null +++ b/examples/pico/application/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +io.helidon.config.examples.level = FINEST diff --git a/examples/pico/application/src/test/java/io/helidon/examples/pico/application/PicoApplicationTest.java b/examples/pico/application/src/test/java/io/helidon/examples/pico/application/PicoApplicationTest.java new file mode 100644 index 00000000000..a3c45923dc0 --- /dev/null +++ b/examples/pico/application/src/test/java/io/helidon/examples/pico/application/PicoApplicationTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.application; + +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.Services; +import io.helidon.pico.testing.PicoTestingSupport; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static io.helidon.pico.testing.PicoTestingSupport.testableServices; + +class PicoApplicationTest { + + protected PicoServices picoServices; + protected Services services; + + @AfterAll + static void tearDown() { + PicoTestingSupport.resetAll(); + } + + protected void resetWith(Config config) { + PicoTestingSupport.resetAll(); + this.picoServices = testableServices(config); + this.services = picoServices.services(); + } + + @Test + void main() { + Config config = Config.builder() + .addSource(ConfigSources.classpath("application.yaml")) + .disableSystemPropertiesSource() + .disableEnvironmentVariablesSource() + .build(); + resetWith(config); + Main.main(); + } + +} diff --git a/examples/pico/basics/README.md b/examples/pico/basics/README.md new file mode 100644 index 00000000000..b91b7aae5ff --- /dev/null +++ b/examples/pico/basics/README.md @@ -0,0 +1,30 @@ +# Helidon Pico Basic Example + +This example shows the basics of using Helidon Pico. The +[Main.java](./src/main/java/io/helidon/examples/pico/basics/Main.java) class shows: + +* programmatic lookup of services in Pico's Services registry in [Main](./src/main/java/io/helidon/examples/pico/basics/Main.java). +* declarative injection in [ToolBox.java](./src/main/java/io/helidon/examples/pico/basics/ToolBox.java). +* lifecycle via PostConstruct and RunLevel in [Main](./src/main/java/io/helidon/examples/pico/basics/Main.java). +* annotation processing and source code generation (see [pom.xml](pom.xml) and [generated-sources](./target/generated-sources/annotations/io/helidon/examples/pico/basics)). + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-pico-basics.jar +``` + +Expected Output: +``` +Startup service providers (ranked according to weight, pre-activated): [ToolBox:INIT] +Highest weighted service provider: ToolBox:INIT +Preferred (highest weighted) 'Big' Tool: Big Hammer +Optional 'Little' Hammer: Optional[Little Hammer] +Tools in the virtual ToolBox: + tool: Hammer:INIT + tool: BigHammer:ACTIVE + tool: LittleHammer:ACTIVE +Highest weighted service provider (after activation): ToolBox +All service providers (after all activations): [ToolBox:ACTIVE] +``` diff --git a/examples/pico/basics/pom.xml b/examples/pico/basics/pom.xml new file mode 100644 index 00000000000..d8f944b91e6 --- /dev/null +++ b/examples/pico/basics/pom.xml @@ -0,0 +1,88 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-nima + 4.0.0-SNAPSHOT + ../../../applications/nima/pom.xml + + io.helidon.examples.pico + helidon-examples-pico-basics + Helidon Pico Examples Basics + + + Examples of programmatic and declarative usages of Pico. + + + + io.helidon.examples.pico.basics.Main + + + + + io.helidon.pico + helidon-pico-api + + + io.helidon.pico + helidon-pico-runtime + + + jakarta.annotation + jakarta.annotation-api + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -Apico.autoAddNonContractInterfaces=false + -Apico.debug=false + + true + + + io.helidon.pico + helidon-pico-processor + ${helidon.version} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Big.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Big.java new file mode 100644 index 00000000000..974cb24d366 --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Big.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.inject.Qualifier; + +/** + * Custom annotation. + */ +@Qualifier +@Retention(RetentionPolicy.CLASS) +public @interface Big { + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/BigHammer.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/BigHammer.java new file mode 100644 index 00000000000..39b3411f8dd --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/BigHammer.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import jakarta.inject.Singleton; + +@Big +@Singleton +class BigHammer extends Hammer { + + @Override + public String name() { + return "Big " + super.name(); + } + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Hammer.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Hammer.java new file mode 100644 index 00000000000..74b48ad093c --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Hammer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import io.helidon.common.Weight; +import io.helidon.common.Weighted; + +import jakarta.inject.Singleton; + +/** + * By adding the {@link Singleton} annotation results in Hammer becoming a Pico service. Services can be looked up + * programmatically or declaratively injected via {@link jakarta.inject.Inject}. + *

+ * Here {@link Weight} is used that is higher than the default, making it more preferred in weighted rankings. + */ +@Singleton +@Weight(Weighted.DEFAULT_WEIGHT + 1) +class Hammer implements Tool { + + @Override + public String name() { + return "Hammer"; + } + + @Override + public String toString() { + return name(); + } + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Little.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Little.java new file mode 100644 index 00000000000..3d2b75b8da7 --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Little.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.inject.Qualifier; + +/** + * Custom annotation. + */ +@Qualifier +@Retention(RetentionPolicy.CLASS) +public @interface Little { +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/LittleHammer.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/LittleHammer.java new file mode 100644 index 00000000000..7facc0ac59e --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/LittleHammer.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import jakarta.inject.Singleton; + +@Little +@Singleton +class LittleHammer extends Hammer { + + @Override + public String name() { + return "Little " + super.name(); + } + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Main.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Main.java new file mode 100644 index 00000000000..62275493610 --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Main.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import java.util.List; + +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.RunLevel; +import io.helidon.pico.api.ServiceInfoCriteria; +import io.helidon.pico.api.ServiceInfoCriteriaDefault; +import io.helidon.pico.api.ServiceProvider; +import io.helidon.pico.api.Services; + +/** + * Basics example. + */ +public class Main { + + /** + * Executes the example. + * + * @param args arguments + */ + public static void main(String... args) { + Services services = PicoServices.realizedServices(); + + // 0. Demonstrates programmatic lookup from Pico's Services registry. + // 1. when a service is being managed by a DI provider (like Pico) it should be "looked up" or injected instead of new'ed + // 2. Notice we get a ServiceProvider - service providers allow for lazy initialization + ServiceInfoCriteria criteria = ServiceInfoCriteriaDefault.builder() + .runLevel(RunLevel.STARTUP) + .build(); + + List> startupServiceProviders = services.lookupAll(criteria); + System.out.println("Startup service providers (ranked according to weight, pre-activated): " + startupServiceProviders); + + ServiceProvider highestWeightedServiceProvider = services.lookupFirst(criteria); + System.out.println("Highest weighted service provider: " + highestWeightedServiceProvider); + + // trigger lazy activations for the highest weighted service provider + System.out.println("Highest weighted service provider (after activation): " + highestWeightedServiceProvider.get()); + + // trigger all activations for the (remaining unactivated) startup service providers + startupServiceProviders.forEach(ServiceProvider::get); + System.out.println("All service providers (after all activations): " + startupServiceProviders); + } + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Tool.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Tool.java new file mode 100644 index 00000000000..339ae70d629 --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/Tool.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import io.helidon.pico.api.Contract; + +/** + * An example Tool interface contract. + */ +@Contract +public interface Tool { + + /** + * The name of the tool. + * + * @return name of the tool + */ + String name(); + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/ToolBox.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/ToolBox.java new file mode 100644 index 00000000000..0d167aca57f --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/ToolBox.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.basics; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import io.helidon.common.Weight; +import io.helidon.common.Weighted; +import io.helidon.pico.api.RunLevel; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Provider; +import jakarta.inject.Singleton; + +/** + * By adding the {@link Singleton} annotation results in ToolBox becoming a Pico service. Services can be looked up + * programmatically or declaratively injected via {@link jakarta.inject.Inject}. + *

+ * Here {@link Weight} is used that is higher than the default, making it more preferred in weighted rankings. + */ +@Singleton +@RunLevel(RunLevel.STARTUP) +@Weight(Weighted.DEFAULT_WEIGHT + 1) +public class ToolBox { + + private final List> allToolProviders; + private Tool preferredBigTool; + + // Pico field injection is supported for non-static, non-private methods (but not recommended) + // Here we are using it to also showcase for Optional usages. + @Inject Optional optionalLittleHammer; + + /** + * Here the constructor injects all {@link Tool} provider instances available. {@link Provider} is used to allow lazy + * activation of services until {@link Provider#get()} is called. + * + * @param allToolProviders all tool providers + */ + @Inject + ToolBox(List> allToolProviders) { + this.allToolProviders = Objects.requireNonNull(allToolProviders); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + /** + * Example of setter based injection. + * + * @param preferredBigTool the preferred big tool + */ + @Inject + @SuppressWarnings("unused") + void setPreferredBigTool(@Big Tool preferredBigTool) { + this.preferredBigTool = Objects.requireNonNull(preferredBigTool); + } + + /** + * This method will be called by Pico after this instance is lazily initialized (because this is the {@link PostConstruct} + * method). + */ + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println("Preferred (highest weighted) 'Big' Tool: " + preferredBigTool); + System.out.println("Optional 'Little' Hammer: " + optionalLittleHammer); + + printToolBoxContents(); + } + + public void printToolBoxContents() { + System.out.println("Tools in the virtual ToolBox:"); + for (Provider tool : allToolProviders) { + System.out.println(" tool: " + tool); + } + } + +} diff --git a/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/package-info.java b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/package-info.java new file mode 100644 index 00000000000..92acf790e40 --- /dev/null +++ b/examples/pico/basics/src/main/java/io/helidon/examples/pico/basics/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Examples of programmatic and declarative usages of Pico. + */ +package io.helidon.examples.pico.basics; diff --git a/examples/pico/basics/src/main/resources/logging.properties b/examples/pico/basics/src/main/resources/logging.properties new file mode 100644 index 00000000000..bd06e0ed087 --- /dev/null +++ b/examples/pico/basics/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +io.helidon.config.examples.level = FINEST diff --git a/examples/pico/configdriven/README.md b/examples/pico/configdriven/README.md new file mode 100644 index 00000000000..3d8dcd3f0a5 --- /dev/null +++ b/examples/pico/configdriven/README.md @@ -0,0 +1,28 @@ +# Helidon Pico Config-Driven Example + +This example shows the basics of using Helidon Pico's Config-Driven Services. The +[Main.java](./src/main/java/io/helidon/examples/pico/configdriven/Main.java) class shows: + +* setting up the bootstrap [configuration](./src/main/resources/application.yaml). +* [ConfigBean](src/main/java/io/helidon/examples/pico/configdriven/DrillConfig.java). +* [ConfiguredBy](src/main/java/io/helidon/examples/pico/configdriven/Drill.java) Services. +* annotation processing and source code generation (see [pom.xml](pom.xml) and [generated-sources](./target/generated-sources/annotations/io/helidon/examples/pico/configdriven)). + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-pico-configdriven.jar +``` + +Expected Output: +``` +Preferred (highest weighted) 'Big' Tool: Big Hammer +Optional 'Little' Hammer: Optional[Little Hammer] +Tools in the virtual ToolBox: + tool: Hammer:INIT + tool: BigHammer:ACTIVE + tool: LittleHammer:ACTIVE + tool: Drill{Hand}:PENDING + tool: Drill{Impact}:PENDING +``` diff --git a/examples/pico/configdriven/pom.xml b/examples/pico/configdriven/pom.xml new file mode 100644 index 00000000000..d3b18a3830a --- /dev/null +++ b/examples/pico/configdriven/pom.xml @@ -0,0 +1,96 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-nima + 4.0.0-SNAPSHOT + ../../../applications/nima/pom.xml + + io.helidon.examples.pico + helidon-examples-pico-configdriven + Helidon Pico Examples Config-Driven + + + Examples of Config-driven services in Pico. + + + + io.helidon.examples.pico.configdriven.Main + + + + + io.helidon.examples.pico + helidon-examples-pico-basics + ${helidon.version} + + + io.helidon.pico.configdriven + helidon-pico-configdriven-runtime + + + io.helidon.config + helidon-config-yaml + + + jakarta.annotation + jakarta.annotation-api + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + true + + + + io.helidon.pico.configdriven + helidon-pico-configdriven-processor + ${helidon.version} + + + + io.helidon.builder + helidon-builder-config-processor + ${helidon.version} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + diff --git a/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Drill.java b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Drill.java new file mode 100644 index 00000000000..b840af85c3a --- /dev/null +++ b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Drill.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.configdriven; + +import java.util.Objects; + +import io.helidon.examples.pico.basics.Tool; +import io.helidon.pico.configdriven.api.ConfiguredBy; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; + +@ConfiguredBy(DrillConfig.class) +class Drill implements Tool { + + private final DrillConfig cfg; + + @Inject + Drill(DrillConfig cfg) { + this.cfg = Objects.requireNonNull(cfg); + } + + @Override + public String name() { + return cfg.name(); + } + + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/DrillConfig.java b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/DrillConfig.java new file mode 100644 index 00000000000..74c7b8b82a8 --- /dev/null +++ b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/DrillConfig.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.configdriven; + +import io.helidon.builder.config.ConfigBean; + +@ConfigBean(repeatable = true) +public interface DrillConfig { + + String name(); + +} diff --git a/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Main.java b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Main.java new file mode 100644 index 00000000000..738b5ab0beb --- /dev/null +++ b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/Main.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.configdriven; + +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; +import io.helidon.examples.pico.basics.ToolBox; +import io.helidon.pico.api.BootstrapDefault; +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.Services; + +/** + * Config-driven example. + */ +public class Main { + + /** + * Executes the example. + * + * @param args arguments + */ + public static void main(String... args) { + // we need to first initialize Pico - informing Pico where to find the application's Config + Config config = Config.builder() + .addSource(ConfigSources.classpath("application.yaml")) + .disableSystemPropertiesSource() + .disableEnvironmentVariablesSource() + .build(); + BootstrapDefault bootstrap = BootstrapDefault.builder() + .config(config) + .build(); + PicoServices.globalBootstrap(bootstrap); + + // this drives config-driven service activations (see the contents of the toolbox being output) + Services services = PicoServices.realizedServices(); + + // this will trigger the PostConstruct method to display the contents of the toolbox + services.lookupFirst(ToolBox.class).get(); + } + +} diff --git a/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/package-info.java b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/package-info.java new file mode 100644 index 00000000000..0b5b1906098 --- /dev/null +++ b/examples/pico/configdriven/src/main/java/io/helidon/examples/pico/configdriven/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Examples of Config-Driven Services in Pico. + */ +package io.helidon.examples.pico.configdriven; diff --git a/examples/pico/configdriven/src/main/resources/application.yaml b/examples/pico/configdriven/src/main/resources/application.yaml new file mode 100644 index 00000000000..4c37d537241 --- /dev/null +++ b/examples/pico/configdriven/src/main/resources/application.yaml @@ -0,0 +1,25 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + +# these are only needed for unit testing - if there is a repeated setup and tear down, etc. +pico: + permits-dynamic: true + +drill: + hand: + name: "Hand" + impact: + name: "Impact" diff --git a/examples/pico/configdriven/src/main/resources/logging.properties b/examples/pico/configdriven/src/main/resources/logging.properties new file mode 100644 index 00000000000..bd06e0ed087 --- /dev/null +++ b/examples/pico/configdriven/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +io.helidon.config.examples.level = FINEST diff --git a/examples/pico/interceptors/README.md b/examples/pico/interceptors/README.md new file mode 100644 index 00000000000..57e31529381 --- /dev/null +++ b/examples/pico/interceptors/README.md @@ -0,0 +1,21 @@ +# Helidon Pico Providers Example + +This example shows how interceptors can be leveraged to develop using Helidon Pico. The +[Main.java](./src/main/java/io/helidon/examples/pico/providers/Main.java) class shows: + +* Interception basics of Pico. + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-pico-interceptors.jar +``` + +Expected Output: +``` +Screw Driver (1st turn): +Screw Driver turning right +Screw Driver (2nd turn): +Screw Driver turning right +``` diff --git a/examples/pico/interceptors/pom.xml b/examples/pico/interceptors/pom.xml new file mode 100644 index 00000000000..990b5bce979 --- /dev/null +++ b/examples/pico/interceptors/pom.xml @@ -0,0 +1,91 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-nima + 4.0.0-SNAPSHOT + ../../../applications/nima/pom.xml + + io.helidon.examples.pico + helidon-examples-pico-interceptors + Helidon Pico Examples Interceptors + + + Example usages of Pico Interceptors. + + + + io.helidon.examples.pico.interceptors.Main + + + + + io.helidon.examples.pico + helidon-examples-pico-basics + ${helidon.version} + + + jakarta.annotation + jakarta.annotation-api + provided + + + org.hamcrest + hamcrest-all + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + true + + + io.helidon.pico + helidon-pico-processor + ${helidon.version} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Main.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Main.java new file mode 100644 index 00000000000..ab9f6dd2176 --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Main.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.interceptors; + +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.ServiceProvider; +import io.helidon.pico.api.Services; + +/** + * Interceptors example. + */ +public class Main { + + /** + * Executes the example. + * + * @param args arguments + */ + public static void main(String... args) { + Services services = PicoServices.realizedServices(); + + // use the intercepted screwdriver - note that hashCode(), equals(), and toString() are not intercepted + ServiceProvider screwDriver = services.lookupFirst(ScrewDriver.class); + System.out.println(screwDriver.get() + " (1st turn): "); + screwDriver.get().turn("left"); + + // use the intercepted screwdriver turning tool - note that hashCode(), equals(), and toString() are not intercepted + ServiceProvider turningTool = services.lookupFirst(TurningTool.class); + System.out.println(turningTool.get() + " (2nd turn): "); + turningTool.get().turn("left"); + } + +} diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/ScrewDriver.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/ScrewDriver.java new file mode 100644 index 00000000000..f4f0eb0e26c --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/ScrewDriver.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.interceptors; + +import jakarta.inject.Singleton; + +@Singleton +class ScrewDriver implements TurningTool { + + @Override + public String name() { + return "Screw Driver"; + } + + @Turn + @Override + public void turn(String direction) { + System.out.println(name() + " turning " + direction); + } + + @Override + public String toString() { + return name(); + } + +} diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Turn.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Turn.java new file mode 100644 index 00000000000..54241cce136 --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/Turn.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.interceptors; + +import io.helidon.pico.api.InterceptedTrigger; + +@InterceptedTrigger +public @interface Turn { +} diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurnInterceptor.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurnInterceptor.java new file mode 100644 index 00000000000..8b53e52ed1b --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurnInterceptor.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.interceptors; + +import io.helidon.pico.api.ClassNamed; +import io.helidon.pico.api.InvocationContext; + +import jakarta.inject.Singleton; + +@ClassNamed(Turn.class) +@Singleton +@SuppressWarnings("unused") +class TurnInterceptor implements io.helidon.pico.api.Interceptor { + + @Override + @SuppressWarnings("unchecked") + public V proceed(InvocationContext ctx, + Chain chain, + Object... args) { + // in "real life" you'd use the ctx to determine the best decision - this is just for simple demonstration only! + if (args.length == 1) { + // this is the call to turn() + args[0] = "right"; + } else if (args.length == 0 && ctx.elementInfo().elementName().equals("name")) { + return (V) ("intercepted: " + chain.proceed(args)); + } + + return chain.proceed(args); + } + +} diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurningTool.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurningTool.java new file mode 100644 index 00000000000..3d3a296d469 --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/TurningTool.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.interceptors; + +import io.helidon.examples.pico.basics.Tool; +import io.helidon.pico.api.Contract; + +@Contract +public interface TurningTool extends Tool { + + void turn(String direction); + +} diff --git a/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/package-info.java b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/package-info.java new file mode 100644 index 00000000000..a337af36d05 --- /dev/null +++ b/examples/pico/interceptors/src/main/java/io/helidon/examples/pico/interceptors/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Examples of Intercepted services in Pico. + */ +package io.helidon.examples.pico.interceptors; diff --git a/examples/pico/interceptors/src/main/resources/logging.properties b/examples/pico/interceptors/src/main/resources/logging.properties new file mode 100644 index 00000000000..bd06e0ed087 --- /dev/null +++ b/examples/pico/interceptors/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +io.helidon.config.examples.level = FINEST diff --git a/examples/pico/pom.xml b/examples/pico/pom.xml new file mode 100644 index 00000000000..aaf8c818dd4 --- /dev/null +++ b/examples/pico/pom.xml @@ -0,0 +1,41 @@ + + + + + 4.0.0 + + io.helidon.examples + helidon-examples-project + 4.0.0-SNAPSHOT + + io.helidon.examples.pico + helidon-examples-pico-project + pom + Helidon Pico Examples + + + basics + providers + configdriven + interceptors + application + + + diff --git a/examples/pico/providers/README.md b/examples/pico/providers/README.md new file mode 100644 index 00000000000..3014fb949e4 --- /dev/null +++ b/examples/pico/providers/README.md @@ -0,0 +1,38 @@ +# Helidon Pico Providers Example + +This example shows how providers can be leveraged to develop using Helidon Pico. The +[Main.java](./src/main/java/io/helidon/examples/pico/providers/Main.java) class shows: + +* multi-module usage (i.e., this example extends [basics](../basics)). +* [standard Providers](src/main/java/io/helidon/examples/pico/providers/NailProvider.java). +* [InjectionPoint Providers](src/main/java/io/helidon/examples/pico/providers/BladeProvider.java). +* additional lifecycle examples via PostConstruct and RunLevel. + +## Build and run + +```bash +mvn package +java -jar target/helidon-examples-pico-providers.jar +``` + +Expected Output: +``` +Startup service providers (ranked according to weight, pre-activated): [ToolBox:INIT, CircularSaw:INIT, NailGun:INIT, TableSaw:INIT] +Preferred (highest weighted) 'Big' Tool: Big Hammer +Optional 'Little' Hammer: Optional[Little Hammer] +Tools in the virtual ToolBox: + tool: Hammer:INIT + tool: BigHammer:ACTIVE + tool: LittleHammer:ACTIVE + tool: AngleGrinderSaw:INIT + tool: CircularSaw:INIT + tool: HandSaw:INIT + tool: NailGun:INIT + tool: TableSaw:INIT +io.helidon.examples.pico.providers.CircularSaw:: will be injected with Optional.empty +Circular Saw: (blade=null); initialized +Nail Gun: (nail provider=NailProvider:INIT); initialized +io.helidon.examples.pico.providers.TableSaw:: will be injected with Optional[LARGE Blade] +Table Saw: (blade=LARGE Blade); initialized +All service providers (after all activations): [ToolBox:ACTIVE, CircularSaw:ACTIVE, NailGun:ACTIVE, TableSaw:ACTIVE] +``` diff --git a/examples/pico/providers/pom.xml b/examples/pico/providers/pom.xml new file mode 100644 index 00000000000..3faf2de02d8 --- /dev/null +++ b/examples/pico/providers/pom.xml @@ -0,0 +1,95 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-nima + 4.0.0-SNAPSHOT + ../../../applications/nima/pom.xml + + io.helidon.examples.pico + helidon-examples-pico-providers + Helidon Pico Examples Providers + + + Example usages of Pico Providers. + + + + io.helidon.examples.pico.providers.Main + + + + + io.helidon.examples.pico + helidon-examples-pico-basics + ${helidon.version} + + + jakarta.annotation + jakarta.annotation-api + provided + + + org.hamcrest + hamcrest-all + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + true + + -Apico.autoAddNonContractInterfaces=true + -Apico.debug=false + + + + io.helidon.pico + helidon-pico-processor + ${helidon.version} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/AngleGrinderSaw.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/AngleGrinderSaw.java new file mode 100644 index 00000000000..a133dae5a49 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/AngleGrinderSaw.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Optional; + +import io.helidon.examples.pico.basics.Little; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +@Singleton +class AngleGrinderSaw implements Saw { + + private final Blade blade; + + @Inject + AngleGrinderSaw(@Little Optional blade) { + this.blade = blade.orElse(null); + } + + @Override + public String name() { + return "Angle Grinder Saw: (blade=" + blade + ")"; + } + + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Blade.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Blade.java new file mode 100644 index 00000000000..ab906b7021f --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Blade.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +/** + * Normally, one would need to place {@link io.helidon.pico.api.Contract} on interfaces. Here, however, we used + * {@code -Apico.autoAddNonContractInterfaces=true} in the {@code pom.xml} thereby making all interfaces into contracts that + * can be found via {@link io.helidon.pico.api.Services#lookup}. + */ +//@Contract +public interface Blade { + + String name(); + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/BladeProvider.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/BladeProvider.java new file mode 100644 index 00000000000..c53b5d567c6 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/BladeProvider.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.Optional; + +import io.helidon.common.LazyValue; +import io.helidon.examples.pico.basics.Big; +import io.helidon.examples.pico.basics.Little; +import io.helidon.pico.api.ContextualServiceQuery; +import io.helidon.pico.api.InjectionPointInfo; +import io.helidon.pico.api.InjectionPointProvider; +import io.helidon.pico.api.QualifierAndValue; +import io.helidon.pico.api.ServiceInfoCriteria; + +import jakarta.inject.Singleton; + +import static io.helidon.common.LazyValue.create; + +@Singleton +public class BladeProvider implements InjectionPointProvider { + + static final LazyValue> LARGE_BLADE = create(() -> Optional.of(new SizedBlade(SizedBlade.Size.LARGE))); + static final LazyValue> SMALL_BLADE = create(() -> Optional.of(new SizedBlade(SizedBlade.Size.SMALL))); + + /** + * Here we are creating the right sized blade based upon the injection point's criteria. Note that the scope/cardinality + * is still (0..1), meaning there will be at most 1 LARGE and at most 1 SMALL blades provided. + * All {@code Provider}s control the scope of the service instances they provide. + * + * @param query the service query + * @return the blade appropriate for the injection point, or empty if nothing matches + * + * @see NailProvider + */ + @Override + public Optional first(ContextualServiceQuery query) { + ServiceInfoCriteria criteria = query.serviceInfoCriteria(); + if (contains(criteria.qualifiers(), Big.class)) { + return logAndReturn(LARGE_BLADE.get(), query); + } else if (contains(criteria.qualifiers(), Little.class)) { + return logAndReturn(SMALL_BLADE.get(), query); + } + return logAndReturn(Optional.empty(), query); + } + + static Optional logAndReturn(Optional result, + ContextualServiceQuery query) { + InjectionPointInfo ip = query.injectionPointInfo().orElse(null); + // note: a "regular" service lookup via Pico will not have an injection point associated with it + if (ip != null) { + System.out.println(ip.serviceTypeName() + "::" + ip.elementName() + " will be injected with " + result); + } + return result; + } + + static boolean contains(Collection qualifiers, + Class anno) { + return qualifiers.stream().anyMatch(it -> it.typeName().name().equals(anno.getName())); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/CircularSaw.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/CircularSaw.java new file mode 100644 index 00000000000..e529ca3eb40 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/CircularSaw.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Optional; + +import io.helidon.pico.api.RunLevel; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +@Singleton +@RunLevel(RunLevel.STARTUP) +class CircularSaw implements Saw { + + private final Blade blade; + + @Inject + CircularSaw(Optional blade) { + this.blade = blade.orElse(null); + } + + @Override + public String name() { + return "Circular Saw: (blade=" + blade + ")"; + } + + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/HandSaw.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/HandSaw.java new file mode 100644 index 00000000000..07dff59e9bb --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/HandSaw.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Optional; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; + +@Singleton +class HandSaw implements Saw { + + private final Blade blade; + + @Inject + HandSaw(@Named("replacement-blade-that-does-not-exist") Optional blade) { + this.blade = blade.orElse(null); + } + + @Override + public String name() { + return "Hand Saw: (blade=" + blade + ")"; + } + + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Main.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Main.java new file mode 100644 index 00000000000..0a044ac3ebf --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Main.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.List; + +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.RunLevel; +import io.helidon.pico.api.ServiceInfoCriteria; +import io.helidon.pico.api.ServiceInfoCriteriaDefault; +import io.helidon.pico.api.ServiceProvider; +import io.helidon.pico.api.Services; + +/** + * Providers example. + */ +public class Main { + + /** + * Executes the example. + * + * @param args arguments + */ + public static void main(String... args) { + Services services = PicoServices.realizedServices(); + + ServiceInfoCriteria criteria = ServiceInfoCriteriaDefault.builder() + .runLevel(RunLevel.STARTUP) + .build(); + + List> startupServiceProviders = services.lookupAll(criteria); + System.out.println("Startup service providers (ranked according to weight, pre-activated): " + startupServiceProviders); + + // trigger all activations for startup service providers + startupServiceProviders.forEach(ServiceProvider::get); + System.out.println("All service providers (after all activations): " + startupServiceProviders); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Nail.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Nail.java new file mode 100644 index 00000000000..c1ddcf9143e --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Nail.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +/** + * Normally, one would need to place {@link io.helidon.pico.api.Contract} on interfaces. Here, however, we used + * {@code -Apico.autoAddNonContractInterfaces=true} in the {@code pom.xml} thereby making all interfaces into contracts that + * can be found via {@link io.helidon.pico.api.Services#lookup}. + */ +//@Contract +public interface Nail { + + int id(); + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailGun.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailGun.java new file mode 100644 index 00000000000..21921f20cd2 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailGun.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Objects; + +import io.helidon.examples.pico.basics.Tool; +import io.helidon.pico.api.RunLevel; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Provider; +import jakarta.inject.Singleton; + +@Singleton +@RunLevel(RunLevel.STARTUP) +class NailGun implements Tool { + + private final Provider nailProvider; + + @Inject + NailGun(Provider nailProvider) { + this.nailProvider = Objects.requireNonNull(nailProvider); + } + + @Override + public String name() { + return "Nail Gun: (nail provider=" + nailProvider + ")"; + } + + /** + * This method will be called by Pico after this instance is lazily initialized (because this is the {@link PostConstruct} + * method). + */ + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailProvider.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailProvider.java new file mode 100644 index 00000000000..77f54b7eac3 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/NailProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import jakarta.inject.Provider; +import jakarta.inject.Singleton; + +/** + * Showcases dependent scope-creating a nail for caller's demand for a {@link Nail} to be provided. + * All {@code Provider}s control the scope of the service instances they provide. + * + * @see BladeProvider + */ +@Singleton +class NailProvider implements Provider { + + /** + * Creates a new nail every its called. + * + * @return a new nail instance + */ + @Override + public Nail get() { + return new StandardNail(); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Saw.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Saw.java new file mode 100644 index 00000000000..317a85b5759 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/Saw.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import io.helidon.examples.pico.basics.Tool; + +/** + * Normally, one would need to place {@link io.helidon.pico.api.Contract} on interfaces. Here, however, we used + * {@code -Apico.autoAddNonContractInterfaces=true} in the {@code pom.xml} thereby making all interfaces into contracts that + * can be found via {@link io.helidon.pico.api.Services#lookup}. + */ +//@Contract +public interface Saw extends Tool { + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/SizedBlade.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/SizedBlade.java new file mode 100644 index 00000000000..2593c5b6524 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/SizedBlade.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Objects; + +/** + * See {@link Blade} + */ +class SizedBlade implements Blade { + + private final Size size; + + public enum Size { + SMALL, + LARGE + } + + public SizedBlade(Size size) { + this.size = Objects.requireNonNull(size); + } + + @Override + public String name() { + return size + " Blade"; + } + + @Override + public String toString() { + return name(); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/StandardNail.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/StandardNail.java new file mode 100644 index 00000000000..75103a3c842 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/StandardNail.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.concurrent.atomic.AtomicInteger; + +class StandardNail implements Nail { + + private static final AtomicInteger counter = new AtomicInteger(); + private final int id = counter.incrementAndGet(); + + StandardNail() { + } + + @Override + public int id() { + return id; + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/TableSaw.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/TableSaw.java new file mode 100644 index 00000000000..006e59694eb --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/TableSaw.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import java.util.Optional; + +import io.helidon.examples.pico.basics.Big; +import io.helidon.pico.api.RunLevel; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +@Singleton +@RunLevel(RunLevel.STARTUP) +class TableSaw implements Saw { + + private final Blade blade; + + @Inject + TableSaw(@Big Optional blade) { + this.blade = blade.orElse(null); + } + + @Override + public String name() { + return "Table Saw: (blade=" + blade + ")"; + } + + @PostConstruct + @SuppressWarnings("unused") + void init() { + System.out.println(name() + "; initialized"); + } + +} diff --git a/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/package-info.java b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/package-info.java new file mode 100644 index 00000000000..117b5eef258 --- /dev/null +++ b/examples/pico/providers/src/main/java/io/helidon/examples/pico/providers/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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. + */ + +/** + * Examples of providers in Pico. + */ +package io.helidon.examples.pico.providers; diff --git a/examples/pico/providers/src/main/resources/logging.properties b/examples/pico/providers/src/main/resources/logging.properties new file mode 100644 index 00000000000..bd06e0ed087 --- /dev/null +++ b/examples/pico/providers/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# http://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. +# + + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +io.helidon.config.examples.level = FINEST diff --git a/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/AllenWrench.java b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/AllenWrench.java new file mode 100644 index 00000000000..d984d1c61f0 --- /dev/null +++ b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/AllenWrench.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import jakarta.inject.Singleton; + +@Singleton +@SuppressWarnings("unused") +public class AllenWrench implements Wrench { + + @Override + public String name() { + return "Allen Wrench"; + } + +} diff --git a/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/ProvidersTest.java b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/ProvidersTest.java new file mode 100644 index 00000000000..880762ee70c --- /dev/null +++ b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/ProvidersTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import org.junit.jupiter.api.Test; + +class ProvidersTest { + + /** + * Through testing, this will additionally have an {@link AllenWrench} in the {@link io.helidon.examples.pico.basics.ToolBox}. + */ + @Test + void main() { + Main.main(); + } + +} diff --git a/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/Wrench.java b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/Wrench.java new file mode 100644 index 00000000000..f8cd0580ba2 --- /dev/null +++ b/examples/pico/providers/src/test/java/io/helidon/examples/pico/providers/Wrench.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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.helidon.examples.pico.providers; + +import io.helidon.examples.pico.basics.Tool; + +public interface Wrench extends Tool { + +} diff --git a/examples/pom.xml b/examples/pom.xml index 532c70d3e3d..f14135d77aa 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -63,6 +63,7 @@ metrics jbatch nima + pico