diff --git a/component-api/src/main/java/org/talend/sdk/component/api/configuration/type/DynamicDependenciesConfiguration.java b/component-api/src/main/java/org/talend/sdk/component/api/configuration/type/DynamicDependenciesConfiguration.java new file mode 100644 index 0000000000000..f7f01ec74d5b3 --- /dev/null +++ b/component-api/src/main/java/org/talend/sdk/component/api/configuration/type/DynamicDependenciesConfiguration.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.api.configuration.type; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.talend.sdk.component.api.configuration.type.meta.ConfigurationType; +import org.talend.sdk.component.api.meta.Documentation; + +@Target(TYPE) +@Retention(RUNTIME) +@ConfigurationType("dynamicDependenciesConfiguration") +@Documentation("Mark a model (complex object) as being the configuration expected to compute dynamic dependencies.") +public @interface DynamicDependenciesConfiguration { + + String value() default "default"; +} \ No newline at end of file diff --git a/sample-parent/pom.xml b/sample-parent/pom.xml index 69fab1e06e67f..69b7e58d97773 100644 --- a/sample-parent/pom.xml +++ b/sample-parent/pom.xml @@ -97,4 +97,4 @@ - + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/README.md b/sample-parent/sample-features/loading-analysis/README.md new file mode 100644 index 0000000000000..98b4c411e4d9d --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/README.md @@ -0,0 +1,317 @@ +# Loading Analysis Module + +## Overview + +The `loading-analysis` module provides several TCK connector plugins designed to validate the `@DynamicDependencies` feature integration, at design time and runtime. It contains several connectors organized into two categories: + +- First are connectors with a service that inherits `AbstractDynamicDependenciesService` and that check: + - All supported ways to call `@DynamicDependencies` annotated services, according to expected configuration types + - Loading of static, dynamic and provided dependencies + - Load a TCK connectors as dynamic dependencies and retrieve data from them +- The other one is `DynamicDependenciesWithSPIInput`, and it checks: + - `Service Provider Interface` (_SPI_) loading from different dependency scopes: + - Standard dependency + - Dynamic dependency + - Provided by the runtime + - Loading of resources from those dependencies + - Loading a single resource as stream + - Loading multiple resources at once + +## Check dynamic dependencies loading +When TCK connectors are built, a file `TALEND-INF/dependencies.txt` is generated in the `jar`, that contains all its dependencies as a list of maven coordinates (_group:artifactId:version:scope_): + +**dependencies.txt** +``` +net.datafaker:datafaker:jar:2.4.2:compile +org.yaml:snakeyaml:jar:2.4:compile +com.github.curious-odd-man:rgxgen:jar:2.0:compile +com.googlecode.libphonenumber:libphonenumber:jar:8.13.50:compile +org.talend.components.extension:polling:jar:1.2512.0:compile +``` + +It happens that some dependencies can only be computed at design time, because, it depends on the connector's configuration. To support this, TCK provides the `@DynamicDependencies` annotation that can be used on a service. The annotated service should return a list of maven coordinates as strings: +```java + @DynamicDependencies() + public List getDynamicDependencies(@Option("theDataset") final Dataset dataset) { + List dynamicDependencies = new ArrayList<>(); + if(dataset.hasASpecialOption()){ + dynamicDependencies.add("org.company:special-dependency:1.0.0"); + dynamicDependencies.add("org.company:another-special-dependency:2.1.0"); + } + return dynamicDependencies; + } +``` +Then, the final application that integrates TCK, call the service with the configuration the user set, load those dependencies and provide them for the runtime. + +### Connectors in this module +As you can see in the previous example, the annotated `@DynamicDependencies` service expect a parameter. This parameter can be of 3 different types: +- A datastore +- A dataset +- Any configuration annotated with `DynamicDependenciesConfiguration` + +(_This documentation will not mention the deprecated `DynamicDependencySupported` provided by the `tDataprepRun` connector._) + +So, 3 TCK modules have been designed, each one provide a service with one of those parameter types: +- loading-dependencies-with-datastore +- loading-dependencies-with-dataset +- loading-dependencies-with-dynamicDependenciesConfiguration +Those 3 modules has the module `loading-dependencies-common` as dependency. They all have a service that inherits `AbstractDynamicDependenciesService`, that implements the `@DynamicDependencies` annotated method. + +#### How to configure them? +Each of those TCK modules provide an input connector in which you can configure: +- A list of maven coordinate that will be returned as dynamic dependencies. + - The user has to set the maven coordinate and a class to load coming from this dependency. If the class is successfully loaded, it means that the dependency is well loaded. + - The coordinate `org.apache.maven.resolver:maven-resolver-api:2.0.14` is also returned by the `@DynamicDependencies`, the class to load is `org.eclipse.aether.artifact.DefaultArtifact`. +- A list of maven coordinates that references a TCK connector. + - For each of them, the user has to set the connector's family, its name, its version and the configuration to use to retrieve data from it. + - A boolean option `useDynamicDependencyLoading` is also provided to indicate that we also want to load dependencies coming from the configured connector. + +Here is an example of connector's configuration: +``` +- groupId: org.talend.components +- artifactId: data-generator +- version: 1.2512.0 +- connector's family: DataGenerator +- connector's name: DataGeneratorInput +- Connector's version: 1 +- load transitive dependencies: true +- connector's configuration: + { + "configuration.minimumRows": "1000", + "configuration.maximumRows": "10000", + "configuration.dataset.seed": "123456", + "configuration.dataset.customLocale": "false", + "configuration.dataset.customSeed": "false", + "configuration.dataset.rows": "10000", + "configuration.dataset.fields[0].name": "name", + "configuration.dataset.fields[0].type": "LASTNAME", + "configuration.dataset.fields[0].$type_name": "Last name", + "configuration.dataset.fields[0].blank": "0", + "configuration.randomRows": "false" + } +``` + +#### Output of those connectors +All of those connectors generate the same output. Only the configuration type of the `@DynamicDependencies` annotated service is different. + +It will generate TCK/records containing those fields: +- `maven`: the maven coordinate of the dependency +- `clazz`: the class that we tried to load from this dependency +- `is_loaded`: a boolean indicating if the class has been successfully loaded +- `connector_classloader`: the classloader name of the dynamic dependency connector +- `clazz_classloader`: the classloader name of the loaded class +- `from_location`: the location from which the class has been loaded +- `is_tck_container`: a boolean indicating if the dependency is a standard dependency or a TCK plugin +- `first_record`: if the dependency is a TCK plugin, this is the first record retrieve from the loaded connector +- `root_repository`: The value of the property `talend.component.manager.m2.repository` +- `runtime_classpath`: the value of the property `java.class.path` +- `working_directory`: the value of the property `user.dir` +- `comment`: a comment + +##### The first record is the result of the class loading from a static dependency, the generated record should be something like: +``` ++-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| maven | org.talend.sdk.component.loading-analysis:loading-dependencies-common:N/A | +| clazz | org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency | +| is_loaded | true | +| connector_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@9ebe38b | +| clazz_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@9ebe38b | +| from_location | jar:file:/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/talend/sdk/component/loading-analysis/loading-dependencies-common/1.89.0-SNAPSHOT/loading-dependencies-common-1.89.0-SNAPSHOT.jar!/org/talend/sdk/component/sample/feature/loadinganalysis/config/Dependency.class | +| is_tck_container | false | +| first_record | null | +| root_repository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| runtime_classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| working_directory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | +| comment | Check static dependency. | ++-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +In this example we can see that we try to load the class `org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency` from the dependency `org.talend.sdk.component.loading-analysis:loading-dependencies-common`. +The version is `N/A` since it is not needed, the dependency is a static one and is loaded at build time. +The `DynamicDependencyWithXxxInput` is well loaded from `org.talend.sdk.component.classloader.ConfigurableClassLoader` as the class to test. + +##### The second record is the result when it tries to load a class from the runtime. It tries to load `org.talend.sdk.component.api.service.asyncvalidation.ValidationResult` that is provided by TCK: +``` ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| maven | org.talend.sdk.component:component-runtime:N/A | +| clazz | org.talend.sdk.component.api.service.asyncvalidation.ValidationResult | +| is_loaded | true | +| connector_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@9ebe38b | +| clazz_classloader | jdk.internal.loader.ClassLoaders$AppClassLoader@73d16e93 | +| from_location | jar:file:/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/talend/sdk/component/component-api/1.89.0-QTDI-2134-YPL-SNAPSHOT/component-api-1.89.0-QTDI-2134-YPL-SNAPSHOT.jar!/org/talend/sdk/component/api/service/asyncvalidation/ValidationResult.class | +| is_tck_container | false | +| first_record | null | +| root_repository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| runtime_classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| working_directory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | +| comment | Check provided dependency. | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +In this example, we can see that the class `org.talend.sdk.component.api.service.asyncvalidation.ValidationResult` is loaded from the `AppClassLoader`, meaning that it is provided by the runtime and not loaded from the `ConfigurableClassLoader` of the TCK container. + +##### The third record is the result of loading a class from a dynamic dependency: +``` ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| maven | org.apache.maven.resolver:maven-resolver-api:2.0.14 | +| clazz | org.eclipse.aether.artifact.DefaultArtifact | +| is_loaded | true | +| connector_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@9ebe38b | +| clazz_classloader | jdk.internal.loader.ClassLoaders$AppClassLoader@73d16e93 | +| from_location | jar:file:/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/maven/resolver/maven-resolver-api/2.0.14/maven-resolver-api-2.0.14.jar!/org/eclipse/aether/artifact/DefaultArtifact.class | +| is_tck_container | false | +| first_record | null | +| root_repository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| runtime_classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| working_directory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | +| comment | An instance has been instantiated and assigned. | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +This is the result of the default dynamic dependency loading. We can see that the class `org.eclipse.aether.artifact.DefaultArtifact` has been successfully loaded from the dynamic dependency `org.apache.maven.resolver:maven-resolver-api:2.0.14`. +In this environment, it has been loaded from the `AppClassLoader`. It happens when all dependencies are flatten in single folder, and not organized as a maven repository. + +##### Example of a record when loading a TCK connector as dynamic dependency +``` ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| maven | org.talend.components:data-generator:1.2512.0 | +| clazz | N/A | +| is_loaded | true | +| connector_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@9ebe38b | +| clazz_classloader | N/A | +| from_location | N/A | +| is_tck_container | true | +| first_record | {"name":"Rogahn"} | +| root_repository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| runtime_classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| working_directory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | +| comment | | ++-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +In that example, we can see that we don't try to load a class, `clazz: N/A`, but TCK plugin, `is_tck_container: true`. It has been well loaded since we retrieve some data from it: +``` +| first_record | {"name":"Rogahn"} +``` + +## Check SPI and resource loading +The `loading-services-and-resources` provides an input connector that will try to load: +- The SPI implementation from a static dependency +- The SPI implementation from a dynamic dependency +- The SPI implementation provided by the runtime +- A resource as stream from a static dependency +- A resource as stream from a dynamic dependency +- A resource as stream provided by the runtime +- Multiple resources at once from a static, dynamic and provided dependencies + +There is no configuration to set in that connector. + +It generates TCK records containing those fields: +- `value`: a string value returned by the loaded SPI implementation or values from resources forthe last record +- `SPI_Interface`: the SPI interface class name +- `SPI_Interface_classloader`: the classloader name that loaded the SPI interface +- `SPI_Impl`: the SPI implementation class name +- `SPI_Impl_classloader`: the classloader name that loaded the SPI implementation +- `comment`: a comment +- `rootRepository`: The value of the property `talend.component.manager.m2.repository` +- `classpath`: the value of the property `java.class.path` +- `workingDirectory`: the value of the property `user.dir` + +### The first record checks SPI implementation provided by a static dependency +The SPI implementation is provided by the dependency `org.talend.sdk.component.loading-analysis:service-provider-from-dependency`. +``` ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| value | ServiceProviderFromDependency value | +| SPI_Interface | interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency | +| SPI_Interface_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@6457a08f | +| SPI_Impl | class org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdependency.ServiceProviderFromDependency | +| SPI_Impl_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@6457a08f | +| comment | SPI implementation loaded from a dependency. | +| rootRepository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_withspi_service_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| workingDirectory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +We can see that the SPI implementation has been well loaded, since the value is retrieved, and has been loaded by the container classloader `ConfigurableClassLoader` as expected. + +### The second record checks SPI implementation provided by a dynamic dependency +The spi implementation is provided by the dependency `org.talend.sdk.component.loading-analysis:service-provider-from-dynamic-dependency`. It is returned by the `@DynamicDependency` service. +``` ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| value | ServiceProviderFromDynamicDependency value | +| SPI_Interface | interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency | +| SPI_Interface_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@6457a08f | +| SPI_Impl | class org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdynamicdependency.ServiceProviderFromDynamicDependency | +| SPI_Impl_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@6457a08f | +| comment | SPI implementation loaded from a dynamic dependency. | +| rootRepository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_withspi_service_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| workingDirectory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +In this second record, we see that the SPI implementation has been loaded from the `ConfigurableClassLoader`. + +### The third record checks SPI implementation provided by the runtime +The spi implementation is provided by the dependency `org.talend.sdk.component.loading-analysis:service-provider-from-external-dependency`. In the studio, we can add this library using the `tLibraryLoad` connector. +``` ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| value | [ERROR] StringProviderFromExternalSPI not loaded! | +| SPI_Interface | interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI | +| SPI_Interface_classloader | org.talend.sdk.component.classloader.ConfigurableClassLoader@6457a08f | +| SPI_Impl | Not found | +| SPI_Impl_classloader | Not found | +| comment | SPI implementation loaded from a runtime/provided dependency. | +| rootRepository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_withspi_service_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| workingDirectory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | ++---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +In this thirds record, we can see that the connector were not able to find implementation for this SPI whereas it should be available in the runtime. + +### The fourth record checks resource loading from dependencies +The last record is quite different. Only the `value` field is interesting. It contains a json document with resources loading results: +``` ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| key | value | ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| value | {"contentFromResourceDependency":"Message from a dependency resource.","contentFromResourceDynamicDependency":"Message from a dynamic dependency resource.","contentFromResourceExternalDependency":"Message from an external dependency resource.","contentFromMultipleResources":"There should be 3 different values:\nContent from static dependency\nContent from dynamic dependency\nContent from static dependency\nContent from dynamic dependency"} | +| SPI_Interface | N/A | +| SPI_Interface_classloader | N/A | +| SPI_Impl | N/A | +| SPI_Impl_classloader | N/A | +| comment | Resources loading. | +| rootRepository | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository | +| classpath | C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/workspace/AAAA/poms/jobs/process/qtdi2134_dyndeps_withspi_service_0.1/target/classpath.jar;/C:/tmp/202601_dyndeps_exports/Talend-Studio-20260121_1719-V8.0.1/configuration/.m2/repository/org/apache/commons/commons-lang3/3.18.0/commons-lang3-3.18.0.jar; | +| workingDirectory | C:\tmp\202601_dyndeps_exports\Talend-Studio-20260121_1719-V8.0.1 | ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +``` +Here is the json documentation contained in the `value` field: +``` +{ + "contentFromResourceDependency": "Message from a dependency resource.", + "contentFromResourceDynamicDependency": "Message from a dynamic dependency resource.", + "contentFromResourceExternalDependency": "Message from an external dependency resource.", + "contentFromMultipleResources": "There should be 3 different values:\nContent from static dependency\nContent from dynamic dependency\nContent from static dependency\nContent from dynamic dependency" +} +``` +The `DynamicDependenciesWithSPIInput` connector tries to load some resources using `DynamicDependenciesWithSPIService.class.getClassLoader().getResourceAsStream(resource)`: +- `FROM_DEPENDENCY/resource.properties`: this resource exists only in `org.talend.sdk.component.loading-analysis:service-provider-from-dependency` module. The resource value is copied in the `contentFromResourceDependency` field of the record. +- `FROM_DYNAMIC_DEPENDENCY/resource.properties`: this resource exists only in `org.talend.sdk.component.loading-analysis:service-provider-from-dynamic-dependency` module. The resource value is copied in the `contentFromResourceDynamicDependency` field of the record. +- `FROM_EXTERNAL_DEPENDENCY/resource.properties`: this resource exists only in `org.talend.sdk.component.loading-analysis:service-provider-from-external-dependency` module. The resource value is copied in the `contentFromResourceExternalDependency` field of the record. + +All those three resources are successfully loaded in this example. + +The last field, `contentFromMultipleResources` contain the result of loading multiple resources at once using `DynamicDependenciesWithSPIService.class.getClassLoader().getResources(resource)` for the resource path `FROM_MULTIPLE/resource.txt`. +This resource exists in all the three modules `org.talend.sdk.component.loading-analysis:service-provider-from-dependency`, `org.talend.sdk.component.loading-analysis:service-provider-from-dynamic-dependency`, `org.talend.sdk.component.loading-analysis:service-provider-from-external-dependency`. +So, 3 values should be concatenated in this field if everything were loaded. In the example, the content of this resource is successfully loaded from static and dynamic dependencies, but twice for each! And, the `FROM_MULTIPLE/resource.txt` +in `org.talend.sdk.component.loading-analysis:service-provider-from-external-dependency` is not found. \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/pom.xml b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/pom.xml new file mode 100644 index 0000000000000..f27556ea8f5c1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/pom.xml @@ -0,0 +1,112 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + + + loading-dependencies-common + jar + Component Runtime :: Sample Feature loading dependencies common + + + + org.apache.maven.resolver + maven-resolver-api + 2.0.14 + provided + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.dependencies.common + + + + + + + test-jar + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + create-TALEND-INF/dependencies.txt + + list + + none + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + talend-dependencies + + dependencies + + none + + + talend-component-bundle + + car + + none + + + talend-scan-descriptor + + scan-descriptor + + none + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Connector.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Connector.java new file mode 100644 index 0000000000000..d2fa4a1038025 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Connector.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@GridLayout(value = { + @GridLayout.Row({ "groupId", "artifactId", "version", "connectorFamily", "connectorName", "connectorVersion", + "loadTransitiveDependencies", "connectorConfiguration" }) +}) +public class Connector implements Serializable { + + @Option + @Documentation("The connector's group id.") + private String groupId; + + @Option + @Documentation("The connector's artifact id.") + private String artifactId; + + @Option + @Documentation("The connector's artifact version.") + private String version; + + @Option + @Documentation("The connector's family.") + private String connectorFamily; + + @Option + @Documentation("The connector's name.") + private String connectorName; + + @Option + @Documentation("The connector's version.") + private int connectorVersion; + + @Option + @Documentation("Load transitive dependencies from TALEND-INF/dependencies.txt.") + private boolean loadTransitiveDependencies; + + @Option + @Documentation("The connector's configuration.") + private String connectorConfiguration; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Dependency.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Dependency.java new file mode 100644 index 0000000000000..7f07f2e7269dd --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/Dependency.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@GridLayout(value = { + @GridLayout.Row({ "groupId", "artifactId", "version", "clazz" }) +}) +public class Dependency implements Serializable { + + @Option + @Documentation("The groupId of the dependency.") + private String groupId; + + @Option + @Documentation("The artifactId of the dependency.") + private String artifactId; + + @Option + @Documentation("The version of the dependency.") + private String version; + + @Option + @Documentation("The class to try to load from this dependency.") + private String clazz; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/DynamicDependencyConfig.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/DynamicDependencyConfig.java new file mode 100644 index 0000000000000..d7a36f4f34ecc --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/config/DynamicDependencyConfig.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.config; + +import java.util.List; + +public interface DynamicDependencyConfig { + + List getDependencies(); + + List getConnectors(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/service/AbstractDynamicDependenciesService.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/service/AbstractDynamicDependenciesService.java new file mode 100644 index 0000000000000..f3d00e48d6494 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/service/AbstractDynamicDependenciesService.java @@ -0,0 +1,411 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.service; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.io.StringReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; + +import org.eclipse.aether.artifact.DefaultArtifact; +import org.talend.sdk.component.api.exception.ComponentException; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.api.record.Record.Builder; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.record.Schema.Type; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.Resolver; +import org.talend.sdk.component.api.service.record.RecordBuilderFactory; +import org.talend.sdk.component.api.service.source.ProducerFinder; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractDynamicDependenciesService implements Serializable { + + public static final String ENTRY_MAVEN = "maven"; + + public static final String ENTRY_CLASS = "clazz"; + + public static final String ENTRY_IS_LOADED = "is_loaded"; + + public static final String ENTRY_CONNECTOR_CLASSLOADER = "connector_classloader"; + + public static final String ENTRY_CLAZZ_CLASSLOADER = "clazz_classloader"; + + public static final String ENTRY_FROM_LOCATION = "from_location"; + + public static final String ENTRY_IS_TCK_CONTAINER = "is_tck_container"; + + public static final String ENTRY_FIRST_RECORD = "first_record"; + + public static final String ENTRY_ROOT_REPOSITORY = "root_repository"; + + public static final String ENTRY_RUNTIME_CLASSPATH = "runtime_classpath"; + + public static final String ENTRY_WORKING_DIRECTORY = "working_directory"; + + public static final String ENTRY_COMMENT = "comment"; + + @Service + private RecordBuilderFactory factory; + + @Service + private ProducerFinder finder; + + @Service + private Resolver resolver; + + public Iterator loadIterator(final DynamicDependencyConfig dynamicDependencyConfig) { + Schema schema = buildSchema(dynamicDependencyConfig); + + List standardDependencies = loadStandardDependencies(dynamicDependencyConfig, schema); + List additionalConnectors = loadConnectors(dynamicDependencyConfig, schema); + + return Stream.concat(standardDependencies.stream(), additionalConnectors.stream()).iterator(); + } + + private List loadStandardDependencies(final DynamicDependencyConfig dynamicDependencyConfig, + final Schema schema) { + List records = new ArrayList<>(); + + List dependencies = new ArrayList<>(); + // Add a class that should be imported by a 'standard' dependency (not a dynamic one) + // to have an example from which classloaded it is loaded + // In that case the version doesn't matter. + dependencies.add(new Dependency("org.talend.sdk.component.loading-analysis", + "loading-dependencies-common", + "N/A", + "org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency")); + + // This is a hardcoded dependency to check how are loaded dependencies + // provided by the runtime + dependencies.add(new Dependency("org.talend.sdk.component", + "component-runtime", + "N/A", + "org.talend.sdk.component.api.service.asyncvalidation.ValidationResult")); + + dependencies.addAll(additionalDependencies()); + + dependencies.addAll(dynamicDependencyConfig.getDependencies()); + for (Dependency dependency : dependencies) { + String comment = ""; + String maven = String.format("%s:%s:%s", dependency.getGroupId(), dependency.getArtifactId(), + dependency.getVersion()); + + boolean isLoaded = false; + String connectorClassLoaderId = this.getClass().getClassLoader().toString(); + String clazzClassLoaderId = "N/A"; + String fromLocation = "N/A"; + try { + Class clazz = Class.forName(dependency.getClazz()); + isLoaded = true; + clazzClassLoaderId = clazz.getClassLoader().toString(); + + // This way to retrieve the location works even if the jar from where clazz comes from + // is nested into another jar (uber jar scenario) + String classPath = clazz.getName().replace('.', '/') + ".class"; + URL url = clazz.getClassLoader().getResource(classPath); + fromLocation = String.valueOf(url); + + if ("maven-resolver-api".equals(dependency.getArtifactId())) { + // This dependency is automatically added by additionalDependencies() + checkAssignmentFromDynamicDependency(); + comment = "An instance has been instantiated and assigned."; + } else if ("dynamic-dependencies-common".equals(dependency.getArtifactId())) { + comment = "Check static dependency."; + } else if ("component-runtime".equals(dependency.getArtifactId())) { + comment = "Check provided dependency."; + } + + } catch (ClassNotFoundException e) { + logError("Cannot load class %s from system classloader".formatted(dependency.getClazz()), e); + } + + Record record = buildRecord(schema, + dynamicDependencyConfig, + maven, + dependency.getClazz(), + isLoaded, + connectorClassLoaderId, + clazzClassLoaderId, + fromLocation, + false, + Optional.empty(), + comment); + records.add(record); + } + + return records; + } + + private List loadConnectors(final DynamicDependencyConfig dynamicDependencyConfig, final Schema schema) { + List records = new ArrayList<>(); + for (Connector connector : dynamicDependencyConfig.getConnectors()) { + + String maven = String.format("%s:%s:%s", connector.getGroupId(), connector.getArtifactId(), + connector.getVersion()); + + String connectorClassLoaderId = this.getClass().getClassLoader().toString(); + String clazzClassLoaderId = "N/A"; + String fromLocation = "N/A"; + Optional optionalRecord = testLoadingData(connector); + boolean isLoaded = optionalRecord.isPresent(); + + Record record = buildRecord(schema, + dynamicDependencyConfig, + maven, + "N/A", + isLoaded, + connectorClassLoaderId, + clazzClassLoaderId, + fromLocation, + true, + optionalRecord, + ""); + records.add(record); + } + + return records; + + } + + // Checkstyle off to let have 11 parameters to this method (normally 10 max) + // CHECKSTYLE:OFF + private Record buildRecord(final Schema schema, + final DynamicDependencyConfig dynamicDependencyConfig, + final String maven, + final String clazz, + final boolean isLoaded, + final String connectorClassLoaderId, + final String clazzClassLoaderId, + final String fromLocation, + final boolean isTckContainer, + final Optional firstRecord, + final String comment) { + + Builder builder = factory.newRecordBuilder(schema); + Builder recordBuilder = builder + .withString(ENTRY_MAVEN, maven) + .withString(ENTRY_CLASS, clazz) + .withBoolean(ENTRY_IS_LOADED, isLoaded) + .withString(ENTRY_CONNECTOR_CLASSLOADER, connectorClassLoaderId) + .withString(ENTRY_CLAZZ_CLASSLOADER, clazzClassLoaderId) + .withString(ENTRY_FROM_LOCATION, fromLocation) + .withBoolean(ENTRY_IS_TCK_CONTAINER, isTckContainer) + .withString(ENTRY_COMMENT, comment); + + firstRecord.ifPresent(record -> builder.withRecord(ENTRY_FIRST_RECORD, record)); + + String rootRepository = System.getProperty("talend.component.manager.m2.repository"); + String runtimeClasspath = System.getProperty("java.class.path"); + String workDirectory = System.getProperty("user.dir"); + + recordBuilder = recordBuilder + .withString(ENTRY_ROOT_REPOSITORY, rootRepository) + .withString(ENTRY_RUNTIME_CLASSPATH, runtimeClasspath) + .withString(ENTRY_WORKING_DIRECTORY, workDirectory); + + return recordBuilder.build(); + } + // CHECKSTYLE:ON + + private Optional testLoadingData(final Connector connector) { + Iterator recordIterator = this.loadData(connector.getConnectorFamily(), connector.getConnectorName(), + connector.getConnectorVersion(), json2Map(connector.getConnectorConfiguration())); + return Optional.ofNullable( + recordIterator.hasNext() ? recordIterator.next() : null); + } + + private Map json2Map(final String json) { + // Transform the given json to map + if (json == null || json.isBlank()) { + return Collections.emptyMap(); + } + try (JsonReader reader = Json.createReader(new StringReader(json))) { + JsonObject jsonObject = reader.readObject(); + Map map = new HashMap<>(); + for (String key : jsonObject.keySet()) { + map.put(key, jsonObject.getString(key, null)); + } + return map; + } catch (Exception e) { + log.error("conversion JSON: {}", e.getMessage(), e); + return Collections.emptyMap(); + } + } + + protected Schema buildSchema(final DynamicDependencyConfig dynamicDependencyConfig) { + Schema.Builder builder = factory.newSchemaBuilder(Type.RECORD) + .withEntry(factory.newEntryBuilder().withName(ENTRY_MAVEN).withType(Type.STRING).build()) + .withEntry(factory.newEntryBuilder().withName(ENTRY_CLASS).withType(Type.STRING).build()) + .withEntry(factory.newEntryBuilder().withName(ENTRY_IS_LOADED).withType(Type.BOOLEAN).build()) + .withEntry( + factory.newEntryBuilder().withName(ENTRY_CONNECTOR_CLASSLOADER).withType(Type.STRING).build()) + .withEntry(factory.newEntryBuilder().withName(ENTRY_CLAZZ_CLASSLOADER).withType(Type.STRING).build()) + .withEntry(factory.newEntryBuilder().withName(ENTRY_FROM_LOCATION).withType(Type.STRING).build()) + .withEntry(factory.newEntryBuilder().withName(ENTRY_IS_TCK_CONTAINER).withType(Type.BOOLEAN).build()) + .withEntry(factory.newEntryBuilder() + .withName(ENTRY_FIRST_RECORD) + .withType(Type.RECORD) + .withNullable(true) + .build()); + + builder = builder + .withEntry(factory.newEntryBuilder().withName(ENTRY_ROOT_REPOSITORY).withType(Type.STRING).build()) + .withEntry( + factory.newEntryBuilder().withName(ENTRY_RUNTIME_CLASSPATH).withType(Type.STRING).build()) + .withEntry( + factory.newEntryBuilder().withName(ENTRY_WORKING_DIRECTORY).withType(Type.STRING).build()); + + builder = builder.withEntry(factory.newEntryBuilder().withName(ENTRY_COMMENT).withType(Type.STRING).build()); + + return builder.build(); + } + + protected Iterator loadData(final String family, final String name, final int version, + final Map parameters) { + return finder.find(family, name, version, parameters); + } + + private void logError(final String message, final Exception e) { + String msg = "Dynamic dependencies connector raised an exception: %s : %s".formatted(message, e.getMessage()); + log.error(msg, e); + } + + private List additionalDependencies() { + List additionalDependencies = new ArrayList<>(); + + // This dynamic dependency is hardcoded since we test assignment in checkAssignmentFromDynamicDependency + // It is a dependency without any transitive dependency + additionalDependencies.add(new Dependency("org.apache.maven.resolver", + "maven-resolver-api", + "2.0.14", + "org.eclipse.aether.artifact.DefaultArtifact")); + + return additionalDependencies; + } + + protected List getDynamicDependencies(final List dependenciesFromConfiguration, + final List connectors) { + + List dependencies = new ArrayList<>(); + dependencies.addAll(dependenciesFromConfiguration); + dependencies.addAll(additionalDependencies()); + + List standardDependencies = dependencies + .stream() + .map(d -> String.format("%s:%s:%s", d.getGroupId(), d.getArtifactId(), d.getVersion())) + .toList(); + + List additionalConnectors = connectors + .stream() + .map(c -> String.format("%s:%s:%s", c.getGroupId(), c.getArtifactId(), c.getVersion())) + .toList(); + + List connectorsDependencies = connectors + .stream() + .flatMap(this::getConnectorDependencies) + .toList(); + List all = Stream.of(standardDependencies, additionalConnectors, connectorsDependencies) + .flatMap(Collection::stream) + .toList(); + + if (log.isInfoEnabled()) { + String collect = all.stream().collect(Collectors.joining("\n- ", "- ", "")); + log.info("All identified dependencies:\n" + collect); + } + + return all; + } + + private Stream getConnectorDependencies(final Connector connector) { + if (!connector.isLoadTransitiveDependencies()) { + return Stream.empty(); + } + + List result; + + String gav = String.format("%s:%s:%s", connector.getGroupId(), + connector.getArtifactId(), + connector.getVersion()); + Collection jarFiles = resolver.resolveFromDescriptor( + Collections.singletonList(gav)); + + if (jarFiles == null || jarFiles.size() <= 0) { + throw new ComponentException("Can't find additional connector '%s'.".formatted(gav)); + } + if (jarFiles.size() > 1) { + String join = jarFiles.stream().map(File::getAbsolutePath).collect(Collectors.joining(",")); + throw new ComponentException("Several files have been found to resolve '%s': %s".formatted(gav, join)); + } + + File jarFile = jarFiles.iterator().next(); + + try (JarFile jar = new JarFile(jarFile)) { + JarEntry entry = jar.getJarEntry("TALEND-INF/dependencies.txt"); + if (entry == null) { + throw new ComponentException("TALEND-INF/dependencies.txt not found in JAR"); + } + + try (InputStream is = jar.getInputStream(entry); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + + result = reader.lines() + .filter(line -> !line.isBlank()) // skip empty lines + .map(line -> line.substring(0, line.lastIndexOf(":"))) // remove last ':xxx' + .collect(Collectors.toList()); + } + + } catch (IOException e) { + throw new ComponentException("Can't load dependencies for %s: %s".formatted(gav, e.getMessage()), e); + } + return result.stream(); + } + + private void checkAssignmentFromDynamicDependency() { + DefaultArtifact defaultArtifact = new DefaultArtifact("g:a:v"); + // Do nothing, just check assignment + // commons-net should be provided by a dynamic dependency + // to validate the test. + log.info("Successful assignment from a class loaded from a dynamic dependency."); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/AbstractDynamicDependenciesServiceTest.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/AbstractDynamicDependenciesServiceTest.java new file mode 100644 index 0000000000000..db92ab9fc8240 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/AbstractDynamicDependenciesServiceTest.java @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis; + +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_CLASS; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_CLAZZ_CLASSLOADER; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_CONNECTOR_CLASSLOADER; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_FROM_LOCATION; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_IS_LOADED; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_IS_TCK_CONTAINER; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_MAVEN; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_ROOT_REPOSITORY; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_RUNTIME_CLASSPATH; +import static org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService.ENTRY_WORKING_DIRECTORY; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; + +import lombok.Getter; + +public abstract class AbstractDynamicDependenciesServiceTest { + + @Getter + private C config; + + protected abstract C buildConfig(); + + protected abstract S getService(); + + @BeforeEach + void setUp() { + this.config = this.buildConfig(); + } + + @Test + void testLoadIterator() { + System.setProperty("talend.component.manager.m2.repository", "./lib/"); + + final Iterator result = getService().loadIterator(config); + + List records = new ArrayList<>(); + result.forEachRemaining(records::add); + Assertions.assertEquals(4, records.size()); + + Record fourth = records.get(3); + ResultDetails expected = new ResultDetails( + false, + "./lib/", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "org.apache.commons:commons-numbers-primes:1.2", + System.getProperty("user.dir"), + true, + "org/apache/commons/commons-numbers-primes/1.2/commons-numbers-primes-1.2.jar!/org/apache/commons/numbers/primes/SmallPrimes.class", + null, + "org.apache.commons.numbers.primes.SmallPrimes", + "commons-numbers-primes-1.2.jar"); + this.assertRecord(fourth, expected); + } + + protected List getDependList() { + List depends = new ArrayList<>(); + Dependency depend = new Dependency(); + depend.setArtifactId("commons-numbers-primes"); + depend.setVersion("1.2"); + depend.setGroupId("org.apache.commons"); + depend.setClazz("org.apache.commons.numbers.primes.SmallPrimes"); + depends.add(depend); + return depends; + } + + private void assertRecord(Record record, ResultDetails expected) { + Assertions.assertNotNull(record); + + Assertions.assertEquals(expected.isTckContainer(), record.getBoolean(ENTRY_IS_TCK_CONTAINER)); + Assertions.assertEquals(expected.rootRepository(), record.getString(ENTRY_ROOT_REPOSITORY)); + Assertions.assertTrue(record.getString(ENTRY_CONNECTOR_CLASSLOADER) + .startsWith(expected.connectorClassloader())); + Assertions.assertTrue(record.getString(ENTRY_CLAZZ_CLASSLOADER).startsWith(expected.clazzClassloader())); + Assertions.assertEquals(expected.maven(), record.getString(ENTRY_MAVEN)); + Assertions.assertEquals(expected.workingDirectory(), record.getString(ENTRY_WORKING_DIRECTORY)); + Assertions.assertEquals(expected.isLoaded(), record.getBoolean(ENTRY_IS_LOADED)); + Assertions.assertTrue(record.getString(ENTRY_FROM_LOCATION).endsWith(expected.fromLocation())); + Assertions.assertEquals(expected.clazz(), record.getString(ENTRY_CLASS)); + Assertions.assertTrue(record.getString(ENTRY_RUNTIME_CLASSPATH).contains(expected.runtimeClasspath())); + + } + + public record ResultDetails( + boolean isTckContainer, + String rootRepository, + String connectorClassloader, + String clazzClassloader, + String maven, + String workingDirectory, + boolean isLoaded, + String fromLocation, + String comment, + String clazz, + String runtimeClasspath + ) { + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/pom.xml b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/pom.xml new file mode 100644 index 0000000000000..01dc1b66987cf --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-dependencies-with-dataprepRunAnnotation + jar + Component Runtime :: Sample Feature @DynamicDependency with DataprepRun annotation + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.dependencies.with.datapreprunannotation + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/annotation/DynamicDependencySupported.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/annotation/DynamicDependencySupported.java new file mode 100644 index 0000000000000..509ccd19ad2b0 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/annotation/DynamicDependencySupported.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.annotation; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.talend.sdk.component.api.configuration.type.meta.ConfigurationType; +import org.talend.sdk.component.api.meta.Documentation; + +@Target(TYPE) +@Retention(RUNTIME) +@ConfigurationType("configuration") +@Documentation("Copy/paste of the annotation from tDataprepRun." + + "It should be removed soon and replaced by the 'DynamicDependenciesConfiguration' provided by the framework.") +@Deprecated +public @interface DynamicDependencySupported { + + String value() default "default"; +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Config.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Config.java new file mode 100644 index 0000000000000..59f3803202a38 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Config.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.annotation.DynamicDependencySupported; + +import lombok.Data; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@DynamicDependencySupported +@GridLayout({ + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "subConfig" }) +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("Sub-configuration that contains the DynamicDependenciesConfiguration.") + private SubConfig subConfig = new SubConfig(); + + @Override + public List getDependencies() { + return new ArrayList<>(this.getSubConfig().getDependencies()); + } + + @Override + public List getConnectors() { + return new ArrayList<>(this.getSubConfig().getConnectors()); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Dataset.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Dataset.java new file mode 100644 index 0000000000000..e13a09434c9d1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Dataset.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataSet; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@AutoLayout +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Datastore.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Datastore.java new file mode 100644 index 0000000000000..419150614759f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Datastore.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.type.DataStore; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; + +import lombok.Data; + +@Data +@DataStore("dyndepsdso") +@AutoLayout +public class Datastore implements Serializable { + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/SubConfig.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/SubConfig.java new file mode 100644 index 0000000000000..5e9198d9cea07 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/SubConfig.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; + +import lombok.Data; + +@Data +@GridLayout({ + @GridLayout.Row({ "dependencies" }), + @GridLayout.Row({ "connectors" }) +}) +public class SubConfig implements Serializable { + + @Option + @Documentation("The dependencies to load dynamically.") + private List dependencies = new ArrayList<>(); + + @Option + @Documentation("The connectors to load dynamically.") + private List connectors = new ArrayList<>(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/DynamicDependenciesWithDataprepRunAnnotationInput.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/DynamicDependenciesWithDataprepRunAnnotationInput.java new file mode 100644 index 0000000000000..ab100250c6e6c --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/DynamicDependenciesWithDataprepRunAnnotationInput.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.input; + +import java.io.Serializable; +import java.util.Iterator; + +import javax.annotation.PostConstruct; + +import org.talend.sdk.component.api.component.Icon; +import org.talend.sdk.component.api.component.Version; +import org.talend.sdk.component.api.input.Emitter; +import org.talend.sdk.component.api.input.Producer; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.service.DynamicDependenciesDataprepRunAnnotationService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Dynamic dependencies sample input connector.") +public class DynamicDependenciesWithDataprepRunAnnotationInput extends AbstractDynamicDependenciesService + implements Serializable { + + private final Config config; + + private final DynamicDependenciesDataprepRunAnnotationService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithDataprepRunAnnotationInput(final Config config, + final DynamicDependenciesDataprepRunAnnotationService service) { + this.config = config; + this.service = service; + } + + @PostConstruct + public void init() { + this.recordIterator = this.service.loadIterator(this.config); + } + + @Producer + public Record next() { + if (recordIterator == null || !recordIterator.hasNext()) { + return null; + } + + return recordIterator.next(); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/package-info.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/package-info.java new file mode 100644 index 0000000000000..5b22dad0bd6d6 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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. + */ +@Components( + family = "LoadingDependenciesWithDataprepAnnotation", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation; + +import org.talend.sdk.component.api.component.Components; +import org.talend.sdk.component.api.component.Icon; \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationService.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationService.java new file mode 100644 index 0000000000000..4da3bab42fbf5 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationService.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.service; + +import java.io.Serializable; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.DynamicDependencies; +import org.talend.sdk.component.api.service.schema.DiscoverSchemaExtended; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config.Config; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesDataprepRunAnnotationService extends AbstractDynamicDependenciesService + implements Serializable { + + public final static String DEPENDENCY_WITHDATAPREPRUN_ACTION = "DEPENDENCY_WITHDATAPREPRUN_ACTION"; + + public static final String DEPENDENCY_ACTION = "dataprep-dependencies"; + + @DynamicDependencies(DEPENDENCY_ACTION) + public List getDynamicDependencies(@Option("theConfig") final Config config) { + return super.getDynamicDependencies(config.getDependencies(), config.getConnectors()); + } + + @DiscoverSchemaExtended(DEPENDENCY_WITHDATAPREPRUN_ACTION) + public Schema guessSchema4Input(final @Option("configuration") Config config) { + return super.buildSchema(config); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..07c7f2c71c358 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDataprepRun + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..07c7f2c71c358 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDataprepRun + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/Messages.properties new file mode 100644 index 0000000000000..62e3a6a2606b7 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/Messages.properties @@ -0,0 +1,18 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDataprepAnnotation.datastore.dyndepsdso._displayName = Datastore for loading dependencies with datapreprun +LoadingDependenciesWithDataprepAnnotation.dataset.dyndepsdse._displayName = Dataset for loading dependencies with datapreprun \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Messages.properties new file mode 100644 index 0000000000000..0077cce1a4842 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/config/Messages.properties @@ -0,0 +1,22 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +Dataset.dso._displayName = +Dataset.dependencies._displayName = Dynamic dependencies +Config.dse._displayName = +Config.subConfig._displayName = +SubConfig.dependencies._displayName = Dependencies +SubConfig.connectors._displayName = Connectors dynamically loaded \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/Messages.properties new file mode 100644 index 0000000000000..f7ce2ac4833be --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/input/Messages.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDataprepAnnotation.Input._displayName = Loading Dependencies With DataprepRun annotation Input \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java new file mode 100644 index 0000000000000..c6b5537e1e3d9 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.service; + +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.junit5.WithComponents; +import org.talend.sdk.component.sample.feature.loadinganalysis.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config.Dataset; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.loadinganalysis.withDataprepRunAnnotation") +public class DynamicDependenciesDataprepRunAnnotationServiceTest + extends AbstractDynamicDependenciesServiceTest { + + @Service + DynamicDependenciesDataprepRunAnnotationService dynamicDependenciesServiceService; + + @Override + protected Config buildConfig() { + Config config = new Config(); + Dataset dse = new Dataset(); + Datastore dso = new Datastore(); + List depends = this.getDependList(); + config.getSubConfig().setDependencies(depends); + dse.setDso(dso); + config.setDse(dse); + + return config; + } + + // use tck connector as dependency + protected List getDependList() { + List depends = new ArrayList<>(); + Dependency depend = new Dependency(); + depend.setArtifactId("commons-numbers-primes"); + depend.setVersion("1.2"); + depend.setGroupId("org.apache.commons"); + depend.setClazz("org.apache.commons.numbers.primes.SmallPrimes"); + depends.add(depend); + + return depends; + } + + @Override + protected DynamicDependenciesDataprepRunAnnotationService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/pom.xml b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/pom.xml new file mode 100644 index 0000000000000..58683ddc49eb1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/pom.xml @@ -0,0 +1,66 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-dependencies-with-dataset + jar + Component Runtime :: Sample Feature @DynamicDependency with Dataset + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.dependencies.with.dataset + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Config.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Config.java new file mode 100644 index 0000000000000..41e4ff402298f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Config.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; + +import lombok.Data; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@GridLayout({ + @GridLayout.Row({ "dse" }) +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Override + public List getDependencies() { + return new ArrayList<>(this.getDse().getDependencies()); + } + + public List getConnectors() { + return new ArrayList<>(this.getDse().getConnectors()); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Dataset.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Dataset.java new file mode 100644 index 0000000000000..12cd79d2656c8 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Dataset.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataSet; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }), + @GridLayout.Row({ "dependencies" }), + @GridLayout.Row({ "connectors" }) +}) +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + + @Option + @Documentation("The dependencies to load dynamically.") + private List dependencies = new ArrayList<>(); + + @Option + @Documentation("The connectors to load dynamically.") + private List connectors = new ArrayList<>(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Datastore.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Datastore.java new file mode 100644 index 0000000000000..5d6f87cd70893 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Datastore.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.type.DataStore; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; + +import lombok.Data; + +@Data +@DataStore("dyndepsdso") +@AutoLayout +public class Datastore implements Serializable { + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/DynamicDependenciesWithDatasetInput.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/DynamicDependenciesWithDatasetInput.java new file mode 100644 index 0000000000000..ac64fcd822109 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/DynamicDependenciesWithDatasetInput.java @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.input; + +import java.io.Serializable; +import java.util.Iterator; + +import javax.annotation.PostConstruct; + +import org.talend.sdk.component.api.component.Icon; +import org.talend.sdk.component.api.component.Version; +import org.talend.sdk.component.api.input.Emitter; +import org.talend.sdk.component.api.input.Producer; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.service.DynamicDependenciesWithDatasetService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Dynamic dependencies sample input connector.") +public class DynamicDependenciesWithDatasetInput implements Serializable { + + private final Config config; + + private final DynamicDependenciesWithDatasetService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithDatasetInput(final Config config, + final DynamicDependenciesWithDatasetService service) { + this.config = config; + this.service = service; + } + + @PostConstruct + public void init() { + this.recordIterator = this.service.loadIterator(this.config); + } + + @Producer + public Record next() { + if (recordIterator == null || !recordIterator.hasNext()) { + return null; + } + + return recordIterator.next(); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/package-info.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/package-info.java new file mode 100644 index 0000000000000..44694ff960200 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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. + */ +@Components( + family = "LoadingDependenciesWithDataset", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.loadinganalysis.withdataset; + +import org.talend.sdk.component.api.component.Components; +import org.talend.sdk.component.api.component.Icon; \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetService.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetService.java new file mode 100644 index 0000000000000..390e53713ba06 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetService.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.service; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.DynamicDependencies; +import org.talend.sdk.component.api.service.schema.DiscoverSchemaExtended; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Dataset; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithDatasetService extends AbstractDynamicDependenciesService implements Serializable { + + public final static String DEPENDENCY_WITHDATASET_ACTION = "DEPENDENCY_WITHDATASET_ACTION"; + + @DynamicDependencies() + public List getDynamicDependencies(@Option("theDataset") final Dataset dataset) { + List dynamicDependencies = + super.getDynamicDependencies(dataset.getDependencies(), dataset.getConnectors()); + log.info("Dynamic dependencies with dataset: {}", + dynamicDependencies.stream().collect(Collectors.joining(";"))); + return dynamicDependencies; + } + + @DiscoverSchemaExtended(DEPENDENCY_WITHDATASET_ACTION) + public Schema guessSchema4Input(final @Option("configuration") Config config) { + return super.buildSchema(config); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..6138ac205b130 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,67 @@ + + + + + + LoadingDependenciesDataset + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..6138ac205b130 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/icons/light/icon.svg @@ -0,0 +1,67 @@ + + + + + + LoadingDependenciesDataset + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/Messages.properties new file mode 100644 index 0000000000000..5d28ccff924ca --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/Messages.properties @@ -0,0 +1,18 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDataset.datastore.dyndepsdso._displayName = Datastore for loading dependencies with dataset +LoadingDependenciesWithDataset.dataset.dyndepsdse._displayName = Dataset for loading dependencies with dataset \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Messages.properties new file mode 100644 index 0000000000000..6ff15c7c12dab --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/config/Messages.properties @@ -0,0 +1,20 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +Dataset.dso._displayName = +Dataset.dependencies._displayName = Dynamic dependencies +Config.dse._displayName = +Dataset.connectors._displayName = Connectors dynamically loaded \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/Messages.properties new file mode 100644 index 0000000000000..67ee7e933d662 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/input/Messages.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDataset.Input._displayName = Loading Dependencies With Dataset Input \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java new file mode 100644 index 0000000000000..412a913d72640 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.service; + +import java.util.List; + +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.junit5.WithComponents; +import org.talend.sdk.component.sample.feature.loadinganalysis.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Dataset; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdataset.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.loadinganalysis.withdataset") +public class DynamicDependenciesWithDatasetServiceTest + extends AbstractDynamicDependenciesServiceTest { + + @Service + private DynamicDependenciesWithDatasetService dynamicDependenciesServiceService; + + @Override + protected Config buildConfig() { + Config config = new Config(); + Dataset dse = new Dataset(); + Datastore dso = new Datastore(); + List depends = this.getDependList(); + dse.setDependencies(depends); + dse.setDso(dso); + config.setDse(dse); + + return config; + } + + @Override + protected DynamicDependenciesWithDatasetService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/pom.xml b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/pom.xml new file mode 100644 index 0000000000000..fa451b9b2097f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/pom.xml @@ -0,0 +1,67 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-dependencies-with-datastore + jar + Component Runtime :: Sample Feature @DynamicDependency with Datastore + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.dependencies.with.datastore + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Config.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Config.java new file mode 100644 index 0000000000000..d657d2c2da1ef --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Config.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; + +import lombok.Data; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@AutoLayout +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Override + public List getDependencies() { + return new ArrayList<>(this.getDse().getDso().getDependencies()); + } + + public List getConnectors() { + return new ArrayList<>(this.getDse().getDso().getConnectors()); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Dataset.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Dataset.java new file mode 100644 index 0000000000000..5900b07597260 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Dataset.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataSet; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@AutoLayout +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Datastore.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Datastore.java new file mode 100644 index 0000000000000..dc8016507e0f6 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Datastore.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataStore; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; + +import lombok.Data; + +@Data +@DataStore("dyndepsdso") +@GridLayout({ + @GridLayout.Row({ "dependencies" }), + @GridLayout.Row({ "connectors" }) +}) +public class Datastore implements Serializable { + + @Option + @Documentation("The dependencies to load dynamically.") + private List dependencies = new ArrayList<>(); + + @Option + @Documentation("The connectors to load dynamically.") + private List connectors = new ArrayList<>(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/DynamicDependenciesWithDatastoreInput.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/DynamicDependenciesWithDatastoreInput.java new file mode 100644 index 0000000000000..512a8ce035f73 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/DynamicDependenciesWithDatastoreInput.java @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.input; + +import java.io.Serializable; +import java.util.Iterator; + +import javax.annotation.PostConstruct; + +import org.talend.sdk.component.api.component.Icon; +import org.talend.sdk.component.api.component.Version; +import org.talend.sdk.component.api.input.Emitter; +import org.talend.sdk.component.api.input.Producer; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.service.DynamicDependenciesWithDatastoreService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Dynamic dependencies sample input connector.") +public class DynamicDependenciesWithDatastoreInput implements Serializable { + + private final Config config; + + private final DynamicDependenciesWithDatastoreService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithDatastoreInput(final Config config, + final DynamicDependenciesWithDatastoreService service) { + this.config = config; + this.service = service; + } + + @PostConstruct + public void init() { + this.recordIterator = this.service.loadIterator(this.config); + } + + @Producer + public Record next() { + if (recordIterator == null || !recordIterator.hasNext()) { + return null; + } + + return recordIterator.next(); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/package-info.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/package-info.java new file mode 100644 index 0000000000000..b76c7e0b5da83 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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. + */ +@Components( + family = "LoadingDependenciesWithDatastore", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore; + +import org.talend.sdk.component.api.component.Components; +import org.talend.sdk.component.api.component.Icon; \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreService.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreService.java new file mode 100644 index 0000000000000..3290aa9123cb4 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreService.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.service; + +import java.io.Serializable; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.DynamicDependencies; +import org.talend.sdk.component.api.service.schema.DiscoverSchemaExtended; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithDatastoreService extends AbstractDynamicDependenciesService + implements Serializable { + + public final static String DEPENDENCY_WITHDATASTORE_ACTION = "DEPENDENCY_WITHDATASTORE_ACTION"; + + @DynamicDependencies() + public List getDynamicDependencies(@Option("theDatastore") final Datastore datastore) { + return super.getDynamicDependencies(datastore.getDependencies(), datastore.getConnectors()); + } + + @DiscoverSchemaExtended(DEPENDENCY_WITHDATASTORE_ACTION) + public Schema guessSchema4Input(final @Option("configuration") Config config) { + return super.buildSchema(config); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..65cc253cb8b26 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDatastore + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..65cc253cb8b26 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/icons/light/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDatastore + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/Messages.properties new file mode 100644 index 0000000000000..e90ed545331a6 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/Messages.properties @@ -0,0 +1,18 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDatastore.datastore.dyndepsdso._displayName = Datastore for loading dependencies with datastore +LoadingDependenciesWithDatastore.dataset.dyndepsdse._displayName = Dataset for loading dependencies with datastore \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Messages.properties new file mode 100644 index 0000000000000..77cc931d41588 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/config/Messages.properties @@ -0,0 +1,20 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +Datastore.dependencies._displayName = Dynamic dependencies +Dataset.dso._displayName = +Config.dse._displayName = +Datastore.connectors._displayName = Connectors dynamically loaded \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/Messages.properties new file mode 100644 index 0000000000000..e7f7b3ab6a475 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/input/Messages.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDatastore.Input._displayName = Loading Dependencies With Datastore Input \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java new file mode 100644 index 0000000000000..6f45698aee49d --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.service; + +import java.util.List; + +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.junit5.WithComponents; +import org.talend.sdk.component.sample.feature.loadinganalysis.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Dataset; +import org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.loadinganalysis.withdatastore") +public class DynamicDependenciesWithDatastoreServiceTest + extends AbstractDynamicDependenciesServiceTest { + + @Service + DynamicDependenciesWithDatastoreService dynamicDependenciesServiceService; + + @Override + protected Config buildConfig() { + Config config = new Config(); + Dataset dse = new Dataset(); + Datastore dso = new Datastore(); + List depends = this.getDependList(); + dso.setDependencies(depends); + dse.setDso(dso); + config.setDse(dse); + + return config; + } + + @Override + protected DynamicDependenciesWithDatastoreService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/pom.xml b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/pom.xml new file mode 100644 index 0000000000000..8fbce9e38a8d6 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-dependencies-with-dynamicDependenciesConfiguration + jar + Component Runtime :: Sample Feature @DynamicDependency with DynamicDependenciesConfiguration + + + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + + + + org.talend.sdk.component.loading-analysis + loading-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.dependencies.with.dynamicdependenciesconfiguration + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Config.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Config.java new file mode 100644 index 0000000000000..1cf45df85fe1c --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Config.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.DynamicDependencyConfig; + +import lombok.Data; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@GridLayout({ + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "subConfig" }) +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("Sub-configuration that contains the DynamicDependenciesConfiguration.") + private SubConfig subConfig = new SubConfig(); + + @Override + public List getDependencies() { + return new ArrayList<>(this.getSubConfig().getDependencies()); + } + + public List getConnectors() { + return new ArrayList<>(this.getSubConfig().getConnectors()); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Dataset.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Dataset.java new file mode 100644 index 0000000000000..22f330ea6e549 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Dataset.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataSet; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@AutoLayout +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Datastore.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Datastore.java new file mode 100644 index 0000000000000..cdf5cde6dd492 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Datastore.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.type.DataStore; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; + +import lombok.Data; + +@Data +@DataStore("dyndepsdso") +@AutoLayout +public class Datastore implements Serializable { + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/SubConfig.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/SubConfig.java new file mode 100644 index 0000000000000..9e30856de1a5e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/SubConfig.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DynamicDependenciesConfiguration; +import org.talend.sdk.component.api.configuration.ui.layout.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Connector; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; + +import lombok.Data; + +@Data +@DynamicDependenciesConfiguration +@GridLayout({ + @GridLayout.Row({ "dependencies" }), + @GridLayout.Row({ "connectors" }) +}) +public class SubConfig implements Serializable { + + @Option + @Documentation("The dependencies to load dynamically.") + private List dependencies = new ArrayList<>(); + + @Option + @Documentation("The connectors to load dynamically.") + private List connectors = new ArrayList<>(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/DynamicDependenciesWithDynamicDependenciesConfigurationInput.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/DynamicDependenciesWithDynamicDependenciesConfigurationInput.java new file mode 100644 index 0000000000000..b2e6376f015e1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/DynamicDependenciesWithDynamicDependenciesConfigurationInput.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.input; + +import java.io.Serializable; +import java.util.Iterator; + +import javax.annotation.PostConstruct; + +import org.talend.sdk.component.api.component.Icon; +import org.talend.sdk.component.api.component.Version; +import org.talend.sdk.component.api.input.Emitter; +import org.talend.sdk.component.api.input.Producer; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.service.DynamicDependenciesWithDynamicDependenciesConfigurationService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Dynamic dependencies sample input connector.") +public class DynamicDependenciesWithDynamicDependenciesConfigurationInput extends AbstractDynamicDependenciesService + implements Serializable { + + private final Config config; + + private final DynamicDependenciesWithDynamicDependenciesConfigurationService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithDynamicDependenciesConfigurationInput(final Config config, + final DynamicDependenciesWithDynamicDependenciesConfigurationService service) { + this.config = config; + this.service = service; + } + + @PostConstruct + public void init() { + this.recordIterator = this.service.loadIterator(this.config); + } + + @Producer + public Record next() { + if (recordIterator == null || !recordIterator.hasNext()) { + return null; + } + + return recordIterator.next(); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/package-info.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/package-info.java new file mode 100644 index 0000000000000..906151c47499d --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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. + */ +@Components( + family = "LoadingDependenciesWithDynamicDependenciesConfiguration", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration; + +import org.talend.sdk.component.api.component.Components; +import org.talend.sdk.component.api.component.Icon; \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationService.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationService.java new file mode 100644 index 0000000000000..66bbbe0e54a9f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationService.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.service; + +import java.io.Serializable; +import java.util.List; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.DynamicDependencies; +import org.talend.sdk.component.api.service.schema.DiscoverSchemaExtended; +import org.talend.sdk.component.sample.feature.loadinganalysis.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.SubConfig; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithDynamicDependenciesConfigurationService extends AbstractDynamicDependenciesService + implements Serializable { + + public final static String DEPENDENCY_WITHDYNDEPSCONFIG_ACTION = "DEPENDENCY_WITHDYNDEPSCONFIG_ACTION"; + + @DynamicDependencies() + public List getDynamicDependencies(@Option("theSubConfig") final SubConfig subConfig) { + return super.getDynamicDependencies(subConfig.getDependencies(), subConfig.getConnectors()); + } + + @DiscoverSchemaExtended(DEPENDENCY_WITHDYNDEPSCONFIG_ACTION) + public Schema guessSchema4Input(final @Option("configuration") Config config) { + return super.buildSchema(config); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..95722d546500e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDynDepConf + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..95722d546500e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg @@ -0,0 +1,64 @@ + + + + + + LoadingDependenciesDynDepConf + diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/Messages.properties new file mode 100644 index 0000000000000..62da09f3ac0a3 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/Messages.properties @@ -0,0 +1,18 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDynamicDependenciesConfiguration.datastore.dyndepsdso._displayName = Datastore for loading dependencies With DynamicDependenciesConfiguration +LoadingDependenciesWithDynamicDependenciesConfiguration.dataset.dyndepsdse._displayName = Dataset for loading dependencies With DynamicDependenciesConfiguration \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Messages.properties new file mode 100644 index 0000000000000..0ec73f3cfdcee --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/config/Messages.properties @@ -0,0 +1,21 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +Dataset.dso._displayName = +Config.dse._displayName = +Config.subConfig._displayName = +SubConfig.dependencies._displayName = Dynamic dependencies +SubConfig.connectors._displayName = Connectors dynamically loaded \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/Messages.properties new file mode 100644 index 0000000000000..de8ef027494a1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/input/Messages.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingDependenciesWithDynamicDependenciesConfiguration.Input._displayName = Dynamic Dependencies With DynamicDependenciesConfiguration Input \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationServiceTest.java b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationServiceTest.java new file mode 100644 index 0000000000000..0c5a879b7e3f4 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicDependenciesConfigurationServiceTest.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.service; + +import java.util.List; + +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.junit5.WithComponents; +import org.talend.sdk.component.sample.feature.loadinganalysis.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.loadinganalysis.config.Dependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.Dataset; +import org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents( + value = "org.talend.sdk.component.sample.feature.loadinganalysis.withDynamicDependenciesConfiguration") +public class DynamicDependenciesWithDynamicDependenciesConfigurationServiceTest + extends + AbstractDynamicDependenciesServiceTest { + + @Service + DynamicDependenciesWithDynamicDependenciesConfigurationService dynamicDependenciesServiceService; + + @Override + protected Config buildConfig() { + Config config = new Config(); + Dataset dse = new Dataset(); + Datastore dso = new Datastore(); + List depends = this.getDependList(); + config.getSubConfig().setDependencies(depends); + dse.setDso(dso); + config.setDse(dse); + + return config; + } + + @Override + protected DynamicDependenciesWithDynamicDependenciesConfigurationService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/pom.xml b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/pom.xml new file mode 100644 index 0000000000000..3ae9024c381aa --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/pom.xml @@ -0,0 +1,87 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-services-and-resources-lib + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a classloader test library + + + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + service.provider.from.dependency.lib + + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + talend-dependencies + + dependencies + + none + + + talend-component-bundle + + car + + none + + + talend-scan-descriptor + + scan-descriptor + + none + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderFromExternalSPI.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderFromExternalSPI.java new file mode 100644 index 0000000000000..8070eb304534e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderFromExternalSPI.java @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces; + +public interface StringProviderFromExternalSPI { + + String getValueFromExternalSPI(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDependency.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDependency.java new file mode 100644 index 0000000000000..b1d75fe287574 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDependency.java @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces; + +public interface StringProviderSPIAsDependency { + + String getValueFromDependency(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDynamicDependency.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDynamicDependency.java new file mode 100644 index 0000000000000..aaddc8483b4fb --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/serviceInterfaces/StringProviderSPIAsDynamicDependency.java @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces; + +public interface StringProviderSPIAsDynamicDependency { + + String getValueFromASPIAsDynamicDependency(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java new file mode 100644 index 0000000000000..3b357ffe14d90 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.function.Function; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractSPIConsumer { + + private final Optional spiImpl; + + protected AbstractSPIConsumer(final Class clazz) { + ServiceLoader serviceLoader = ServiceLoader.load(clazz, AbstractSPIConsumer.class.getClassLoader()); + + List implProvider = new ArrayList<>(); + + try { + serviceLoader.iterator().forEachRemaining(implProvider::add); + } catch (Throwable e) { + log.error("Can't load %s spi implementation: %s.".formatted(clazz, e.getMessage()), e); + } + + if (implProvider.size() <= 0) { + log.error("No SPI service found for %s.".formatted(clazz)); + spiImpl = Optional.empty(); + return; + } + + if (implProvider.size() > 1) { + String join = implProvider.stream() + .map(m -> m.getClass().getName()) + .collect(Collectors.joining("\n")); + log.error("More than one %s service has been found: %s.".formatted(clazz, join)); + // For testing purpose (the goal of this connector), better to fail in that case. + spiImpl = Optional.empty(); + return; + } + + this.spiImpl = Optional.of(implProvider.get(0)); + } + + public abstract String getValue(); + + public T transform(final Function function) { + String value = this.getValue(); + return function.apply(value); + } + + public Optional getSPIImpl() { + return this.spiImpl; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DependencySPIConsumer.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DependencySPIConsumer.java new file mode 100644 index 0000000000000..437a147a47774 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DependencySPIConsumer.java @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency; + +public class DependencySPIConsumer extends AbstractSPIConsumer { + + public DependencySPIConsumer() { + super(StringProviderSPIAsDependency.class); + } + + public String getValue() { + if (this.getSPIImpl().isPresent()) { + StringProviderSPIAsDependency impl = this.getSPIImpl().get(); + return impl.getValueFromDependency(); + } else { + return "[ERROR] StringProviderSPIAsDependency not loaded!"; + } + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.java new file mode 100644 index 0000000000000..b68b4012b90cb --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.java @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency; + +public class DynamicDependencySPIConsumer extends AbstractSPIConsumer { + + public DynamicDependencySPIConsumer() { + super(StringProviderSPIAsDynamicDependency.class); + } + + public String getValue() { + if (this.getSPIImpl().isPresent()) { + StringProviderSPIAsDynamicDependency impl = this.getSPIImpl().get(); + return impl.getValueFromASPIAsDynamicDependency(); + } else { + return "[ERROR] StringProviderSPIAsDynamicDependency not loaded!"; + } + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.java new file mode 100644 index 0000000000000..bbf63d0d9aa74 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.java @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI; + +public class ExternalDependencySPIConsumer extends AbstractSPIConsumer { + + public ExternalDependencySPIConsumer() { + super(StringProviderFromExternalSPI.class); + } + + public String getValue() { + if (this.getSPIImpl().isPresent()) { + StringProviderFromExternalSPI impl = this.getSPIImpl().get(); + return impl.getValueFromExternalSPI(); + } else { + return "[ERROR] StringProviderFromExternalSPI not loaded!"; + } + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/CLASSLOADER-TEST-LIBRARY/resource.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/CLASSLOADER-TEST-LIBRARY/resource.properties new file mode 100644 index 0000000000000..21823376343ce --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/CLASSLOADER-TEST-LIBRARY/resource.properties @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.message=This is a resource file from classloader-test-library. \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/MULTIPLE_RESOURCE/common.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/MULTIPLE_RESOURCE/common.properties new file mode 100644 index 0000000000000..80e0e08d4ada1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources-lib/src/main/resources/MULTIPLE_RESOURCE/common.properties @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +content=from dependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/pom.xml b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/pom.xml new file mode 100644 index 0000000000000..7a9cabdb31b6a --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + loading-services-and-resources + jar + Component Runtime :: Sample Feature @DynamicDependency with spi + + + + org.talend.sdk.component + component-runtime-manager + ${project.version} + provided + + + org.talend.sdk.component.loading-analysis + loading-services-and-resources-lib + ${project.version} + + + org.talend.sdk.component.loading-analysis + service-provider-from-dependency + ${project.version} + + + org.talend.sdk.component.loading-analysis + service-provider-from-dynamic-dependency + ${project.version} + test + + + org.talend.sdk.component.loading-analysis + service-provider-from-external-dependency + ${project.version} + test + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + loading.services.and.resources + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Config.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Config.java new file mode 100644 index 0000000000000..c69e5ed5bbfe2 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Config.java @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@AutoLayout +public class Config implements Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("Unused option to force dependency inclusion.") + private String unusedOption; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Dataset.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Dataset.java new file mode 100644 index 0000000000000..f0a343cfb35e4 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Dataset.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataSet; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@AutoLayout +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + + @Option + @Documentation("Unused option to force dependency inclusion.") + private String unusedOption; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Datastore.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Datastore.java new file mode 100644 index 0000000000000..bf825ddc9af51 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Datastore.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config; + +import java.io.Serializable; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.configuration.type.DataStore; +import org.talend.sdk.component.api.configuration.ui.layout.AutoLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataStore("dyndepsdso") +@AutoLayout +public class Datastore implements Serializable { + + @Option + @Documentation("Unused option to force dependency inclusion.") + private String unusedOption; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInput.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInput.java new file mode 100644 index 0000000000000..cb3eaec051234 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInput.java @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.input; + +import java.io.Serializable; +import java.util.Iterator; + +import javax.annotation.PostConstruct; + +import org.talend.sdk.component.api.component.Icon; +import org.talend.sdk.component.api.component.Version; +import org.talend.sdk.component.api.input.Emitter; +import org.talend.sdk.component.api.input.Producer; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config.Config; +import org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service.DynamicDependenciesWithSPIService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Loading SPIs and resources.") +public class DynamicDependenciesWithSPIInput implements Serializable { + + private final Config config; + + private final DynamicDependenciesWithSPIService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithSPIInput(final Config config, + final DynamicDependenciesWithSPIService service) { + this.config = config; + this.service = service; + } + + @PostConstruct + public void init() { + this.recordIterator = this.service.getRecordIterator(); + } + + @Producer + public Record next() { + if (recordIterator == null || !recordIterator.hasNext()) { + return null; + } + + return recordIterator.next(); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/package-info.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/package-info.java new file mode 100644 index 0000000000000..ea6c6fe3fd24d --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/package-info.java @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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. + */ +@Components( + family = "LoadingSPIsAndResources", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.loadinganalysis.withspi; + +import org.talend.sdk.component.api.component.Components; +import org.talend.sdk.component.api.component.Icon; \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/CustomizeClassLoader.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/CustomizeClassLoader.java new file mode 100644 index 0000000000000..97f35af1aa04f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/CustomizeClassLoader.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service; + +import java.util.stream.Stream; + +import org.talend.sdk.component.runtime.manager.ComponentManager; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CustomizeClassLoader implements ComponentManager.Customizer { + + private static final String DISABLE_CUSTOMIZE_PROPERTY = + "org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service.CustomizeClassLoader.disabled"; + + private static final boolean DISABLE_CUSTOMIZE = Boolean.parseBoolean( + System.getProperty(DISABLE_CUSTOMIZE_PROPERTY, "true")); + + @Override + public Stream containerClassesAndPackages() { + if (DISABLE_CUSTOMIZE) { + log.info( + "org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service.CustomizeClassLoader is disabled.\n" + + "use \"" + DISABLE_CUSTOMIZE_PROPERTY + "=false\"" + + " property to enable it."); + return Stream.empty(); + } + + log.info( + "org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service.CustomizeClassLoader is enabled,\n" + + "use \"" + DISABLE_CUSTOMIZE_PROPERTY + "=true\"" + + " property to disable it."); + return Stream.of( + // Implementation should come from a dynamic dependency + "org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency", + // Implementation should come from runtime + "org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency"); + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/DynamicDependenciesWithSPIService.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/DynamicDependenciesWithSPIService.java new file mode 100644 index 0000000000000..3c0f3f6159650 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/service/DynamicDependenciesWithSPIService.java @@ -0,0 +1,277 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +import javax.json.JsonBuilderFactory; +import javax.json.JsonObject; + +import org.talend.sdk.component.api.configuration.Option; +import org.talend.sdk.component.api.exception.ComponentException; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.api.record.Schema; +import org.talend.sdk.component.api.record.Schema.Type; +import org.talend.sdk.component.api.service.Service; +import org.talend.sdk.component.api.service.dependency.DynamicDependencies; +import org.talend.sdk.component.api.service.record.RecordBuilderFactory; +import org.talend.sdk.component.api.service.schema.DiscoverSchema; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.DependencySPIConsumer; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.DynamicDependencySPIConsumer; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.ExternalDependencySPIConsumer; +import org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config.Dataset; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithSPIService implements Serializable { + + private static String version; + + @Service + private RecordBuilderFactory recordBuilderFactory; + + @Service + private JsonBuilderFactory jsonBuilderFactory; + + @DynamicDependencies + public List getDynamicDependencies(@Option("theDataset") final Dataset dataset) { + String dep = "org.talend.sdk.component.loading-analysis:service-provider-from-dynamic-dependency:" + + loadVersion(); + List strings = Collections.singletonList(dep); + log.info("Loading SPI: {}", strings.stream().collect(Collectors.joining(";"))); + return strings; + } + + @DiscoverSchema("dyndepsdse") + public Schema guessSchema4Input(final @Option("configuration") Dataset dse) { + return recordBuilderFactory.newSchemaBuilder(Type.RECORD) + .withEntry(recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("value").build()) + .withEntry( + recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("SPI_Interface").build()) + .withEntry(recordBuilderFactory.newEntryBuilder() + .withType(Type.STRING) + .withName("SPI_Interface_classloader") + .build()) + .withEntry(recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("SPI_Impl").build()) + .withEntry(recordBuilderFactory.newEntryBuilder() + .withType(Type.STRING) + .withName("SPI_Impl_classloader") + .build()) + .withEntry(recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("comment").build()) + .withEntry( + recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("rootRepository").build()) + .withEntry(recordBuilderFactory.newEntryBuilder().withType(Type.STRING).withName("classpath").build()) + .withEntry(recordBuilderFactory.newEntryBuilder() + .withType(Type.STRING) + .withName("workingDirectory") + .build()) + .build(); + } + + public Iterator getRecordIterator() { + String rootRepository = System.getProperty("talend.component.manager.m2.repository"); + String runtimeClasspath = System.getProperty("java.class.path"); + String workDirectory = System.getProperty("user.dir"); + + String contentFromResourceDependency = loadAPropertyFromResource("FROM_DEPENDENCY/resource.properties", + "ServiceProviderFromDependency.message"); + + String contentFromResourceDynamicDependency = loadAPropertyFromResource( + "FROM_DYNAMIC_DEPENDENCY/resource.properties", + "ServiceProviderFromDynamicDependency.message"); + + String contentFromResourceExternalDependency = loadAPropertyFromResource( + "FROM_EXTERNAL_DEPENDENCY/resource.properties", + "ServiceProviderFromExternalDependency.message"); + + String contentFromMultipleResources; + try { + Enumeration resources = DynamicDependenciesWithSPIService.class.getClassLoader() + .getResources("MULTIPLE_RESOURCE/content.txt"); + + StringBuilder stringBuilder = new StringBuilder("There should be 3 different values:"); + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + + try (InputStream is = url.openStream()) { + String content = filterComments(is); + stringBuilder.append("\n"); + stringBuilder.append(content); + } + } + contentFromMultipleResources = stringBuilder.toString(); + } catch (IOException e) { + throw new ComponentException("Can't retrieve multiple resources at once.", e); + } + + DependencySPIConsumer dependencySPIConsumer = new DependencySPIConsumer<>(); + Record recordsFromDependencySPI = dependencySPIConsumer + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("SPI_Interface", String.valueOf(StringProviderSPIAsDependency.class)) + .withString("SPI_Impl", + dependencySPIConsumer.getSPIImpl().isPresent() + ? String.valueOf(dependencySPIConsumer.getSPIImpl().get().getClass()) + : "Not found") + .withString("SPI_Interface_classloader", + String.valueOf(StringProviderSPIAsDependency.class.getClassLoader())) + .withString("SPI_Impl_classloader", + dependencySPIConsumer.getSPIImpl().isPresent() + ? String.valueOf( + dependencySPIConsumer.getSPIImpl().get().getClass().getClassLoader()) + : "Not found") + .withString("comment", "SPI implementation loaded from a dependency.") + .withString("rootRepository", rootRepository) + .withString("classpath", runtimeClasspath) + .withString("workingDirectory", workDirectory) + .build()); + + DynamicDependencySPIConsumer dynamicDependencySPIConsumer = new DynamicDependencySPIConsumer<>(); + Record recordsFromDynamicDependencySPI = dynamicDependencySPIConsumer + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("SPI_Interface", String.valueOf(StringProviderSPIAsDynamicDependency.class)) + .withString("SPI_Impl", + dynamicDependencySPIConsumer.getSPIImpl().isPresent() + ? String.valueOf(dynamicDependencySPIConsumer.getSPIImpl().get().getClass()) + : "Not found") + .withString("SPI_Interface_classloader", + String.valueOf(StringProviderSPIAsDynamicDependency.class.getClassLoader())) + .withString("SPI_Impl_classloader", + dynamicDependencySPIConsumer.getSPIImpl().isPresent() ? String.valueOf( + dynamicDependencySPIConsumer.getSPIImpl().get().getClass().getClassLoader()) + : "Not found") + .withString("comment", "SPI implementation loaded from a dynamic dependency.") + .withString("rootRepository", rootRepository) + .withString("classpath", runtimeClasspath) + .withString("workingDirectory", workDirectory) + .build()); + + ExternalDependencySPIConsumer externalDependencySPI = new ExternalDependencySPIConsumer<>(); + Record recordsFromExternalSPI = externalDependencySPI + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("SPI_Interface", String.valueOf(StringProviderFromExternalSPI.class)) + .withString("SPI_Impl", + externalDependencySPI.getSPIImpl().isPresent() + ? String.valueOf(externalDependencySPI.getSPIImpl().get().getClass()) + : "Not found") + .withString("SPI_Interface_classloader", + String.valueOf(StringProviderFromExternalSPI.class.getClassLoader())) + .withString("SPI_Impl_classloader", + externalDependencySPI.getSPIImpl().isPresent() + ? String.valueOf( + externalDependencySPI.getSPIImpl().get().getClass().getClassLoader()) + : "Not found") + .withString("comment", "SPI implementation loaded from a runtime/provided dependency.") + .withString("rootRepository", rootRepository) + .withString("classpath", runtimeClasspath) + .withString("workingDirectory", workDirectory) + .build()); + + JsonObject contentFromResources = jsonBuilderFactory.createObjectBuilder() + .add("contentFromResourceDependency", contentFromResourceDependency) + .add("contentFromResourceDynamicDependency", contentFromResourceDynamicDependency) + .add("contentFromResourceExternalDependency", contentFromResourceExternalDependency) + .add("contentFromMultipleResources", contentFromMultipleResources) + .build(); + Record recordWithContentFromResources = recordBuilderFactory.newRecordBuilder() + .withString("value", contentFromResources.toString()) + .withString("SPI_Interface", "N/A") + .withString("SPI_Impl", "N/A") + .withString("SPI_Interface_classloader", "N/A") + .withString("SPI_Impl_classloader", "N/A") + .withString("comment", "Resources loading.") + .withString("rootRepository", rootRepository) + .withString("classpath", runtimeClasspath) + .withString("workingDirectory", workDirectory) + .build(); + + List values = new ArrayList<>(); + values.add(recordsFromDependencySPI); + values.add(recordsFromDynamicDependencySPI); + values.add(recordsFromExternalSPI); + values.add(recordWithContentFromResources); + + return values.iterator(); + } + + private static String loadVersion() { + if (version == null) { + try (InputStream is = DynamicDependenciesWithSPIService.class.getClassLoader() + .getResourceAsStream("version.properties")) { + if (is == null) { + throw new ComponentException("Can't retrieve version.properties resource."); + } + Properties props = new Properties(); + props.load(is); + version = props.getProperty("version"); + } catch (IOException e) { + throw new ComponentException("Unable to load project version", e); + } + } + return version; + } + + private String filterComments(final InputStream stream) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + return reader.lines() + .map(String::trim) + .filter(line -> !line.trim().startsWith("#")) + .filter(line -> !line.trim().isEmpty()) + .collect(Collectors.joining("\n")); + } catch (IOException e) { + throw new ComponentException("Can't close a resource reader.", e); + } + + } + + private String loadAPropertyFromResource(final String resource, final String property) { + try (InputStream resourceStreamFromDependency = DynamicDependenciesWithSPIService.class.getClassLoader() + .getResourceAsStream(resource)) { + + if (resourceStreamFromDependency == null) { + return "The resource '%s' has not been found, it can't retrieve the '%s' property value." + .formatted(resource, property); + } + + Properties prop = new Properties(); + prop.load(resourceStreamFromDependency); + return prop.getProperty(property); + } catch (IOException e) { + throw new ComponentException("Can't retrieve resource from a dependency.", e); + } + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer new file mode 100644 index 0000000000000..1bbc17b34e21f --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer @@ -0,0 +1 @@ +org.talend.sdk.component.sample.feature.loadinganalysis.withspi.service.CustomizeClassLoader \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..09ae5f65a3b5e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,65 @@ + + + + + + LoadingSPIs andResources + diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..09ae5f65a3b5e --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/icons/light/icon.svg @@ -0,0 +1,65 @@ + + + + + + LoadingSPIs andResources + diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/Messages.properties new file mode 100644 index 0000000000000..41969523f58f4 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/Messages.properties @@ -0,0 +1,19 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingSPIsAndResources.datastore.dyndepsdso._displayName = Datastore +LoadingSPIsAndResources.dataset.dyndepsdse._displayName = Dataset +LoadingSPIsAndResources.actions.schema.dyndepsdse._displayName = Discover schema \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Messages.properties new file mode 100644 index 0000000000000..0df2b952a75f0 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/config/Messages.properties @@ -0,0 +1,25 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +Dataset.dso._displayName = +Config.dse._displayName = + +Config.unusedOption._displayName = Unused in config +Dataset.unusedOption._displayName = Unused in dataset +Datastore.unusedOption._displayName = Unused in datastore + +Config.unusedOption._placeholder = +Dataset.unusedOption._placeholder = +Datastore.unusedOption._placeholder = \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/Messages.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/Messages.properties new file mode 100644 index 0000000000000..9db7d6bf07fe1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/Messages.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +LoadingSPIsAndResources.Input._displayName = Loading SPIs and Resources \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/version.properties b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/version.properties new file mode 100644 index 0000000000000..c7c8d1f0f47db --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/main/resources/version.properties @@ -0,0 +1,17 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example + +version=${project.version} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInputTest.java b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInputTest.java new file mode 100644 index 0000000000000..7dc0e859b7316 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/loading-services-and-resources/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/withspi/input/DynamicDependenciesWithSPIInputTest.java @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.withspi.input; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.api.record.Record; +import org.talend.sdk.component.junit.BaseComponentsHandler; +import org.talend.sdk.component.junit.SimpleFactory; +import org.talend.sdk.component.junit5.Injected; +import org.talend.sdk.component.junit5.WithComponents; +import org.talend.sdk.component.runtime.manager.chain.Job; +import org.talend.sdk.component.sample.feature.loadinganalysis.withspi.config.Config; + +@WithComponents("org.talend.sdk.component.sample.feature.loadinganalysis.withspi") +class DynamicDependenciesWithSPIInputTest { + + @Injected + protected BaseComponentsHandler handler; + + @Test + public void testGeneratedRecord() { + Config config = new Config(); + String queryString = SimpleFactory.configurationByExample().forInstance(config).configured().toQueryString(); + + Job.components() + .component("input", "LoadingSPIsAndResources://Input?" + queryString) + .component("collector", "test://collector") + .connections() + .from("input") + .to("collector") + .build() + .run(); + + List records = handler.getCollectedData(Record.class); + Assertions.assertEquals(4, records.size()); + + Result expected0 = new Result( + "interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency", + "class org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdependency.ServiceProviderFromDependency", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "SPI implementation loaded from a dependency.", + "ServiceProviderFromDependency value"); + validate(expected0, records.get(0)); + + Result expected1 = new Result( + "interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency", + "class org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdynamicdependency.ServiceProviderFromDynamicDependency", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "SPI implementation loaded from a dynamic dependency.", + "ServiceProviderFromDynamicDependency value"); + validate(expected1, records.get(1)); + + Result expected2 = new Result( + "interface org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI", + "class org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromexternaldependency.ServiceProviderFromExternalDependency", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "jdk.internal.loader.ClassLoaders$AppClassLoader", + "SPI implementation loaded from a runtime/provided dependency.", + "ServiceProviderFromExternalDependency value"); + validate(expected2, records.get(2)); + + Result expected3 = new Result( + "N/A", + "N/A", + "N/A", + "N/A", + "Resources loading.", + "{\"contentFromResourceDependency\":\"Message from a dependency resource.\",\"contentFromResourceDynamicDependency\":\"Message from a dynamic dependency resource.\",\"contentFromResourceExternalDependency\":\"Message from an external dependency resource.\",\"contentFromMultipleResources\":\"There should be 3 different values:\\nContent from static dependency\\nContent from dynamic dependency\\nContent from external dependency\"}"); + validate(expected3, records.get(3)); + } + + private void validate(Result expected, Record record) { + Assertions.assertEquals(expected.spiInterface(), record.getString("SPI_Interface")); + Assertions.assertEquals(expected.spiImpl(), record.getString("SPI_Impl")); + Assertions.assertTrue( + record.getString("SPI_Interface_classloader").startsWith(expected.spiInterfaceClassloader())); + Assertions.assertTrue(record.getString("SPI_Impl_classloader").startsWith(expected.spiImplClassloader())); + Assertions.assertEquals(expected.comment(), record.getString("comment")); + Assertions.assertEquals(expected.value(), record.getString("value")); + } + + private record Result( + String spiInterface, + String spiImpl, + String spiInterfaceClassloader, + String spiImplClassloader, + String comment, + String value + ) { + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/pom.xml b/sample-parent/sample-features/loading-analysis/pom.xml new file mode 100644 index 0000000000000..4120d821bde02 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + org.talend.sdk.component + sample-features + 1.89.0-SNAPSHOT + + + org.talend.sdk.component.loading-analysis + loading-analysis + pom + + Component Runtime :: Sample Feature @DynamicDependency + + loading-dependencies-common + loading-dependencies-with-dataset + loading-dependencies-with-datastore + loading-dependencies-with-dynamicDependenciesConfiguration + loading-dependencies-with-dataprepRunAnnotation + loading-services-and-resources + loading-services-and-resources-lib + service-provider-from-dependency + service-provider-from-dynamic-dependency + service-provider-from-external-dependency + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/pom.xml b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/pom.xml new file mode 100644 index 0000000000000..90731e6142670 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + service-provider-from-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of dependencies + + + true + + + + + org.talend.sdk.component.loading-analysis + loading-services-and-resources-lib + ${project.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + service.provider.from.dependency + + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + talend-dependencies + + dependencies + + none + + + talend-component-bundle + + car + + none + + + talend-scan-descriptor + + scan-descriptor + + none + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependency.java b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependency.java new file mode 100644 index 0000000000000..df6cf5fabb3ec --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependency.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdependency; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency; + +public class ServiceProviderFromDependency implements StringProviderSPIAsDependency { + + @Override + public String getValueFromDependency() { + return "ServiceProviderFromDependency value"; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/FROM_DEPENDENCY/resource.properties b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/FROM_DEPENDENCY/resource.properties new file mode 100644 index 0000000000000..7e542381a7a66 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/FROM_DEPENDENCY/resource.properties @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +ServiceProviderFromDependency.message=Message from a dependency resource. \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency new file mode 100644 index 0000000000000..027a1015a0ef4 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdependency.ServiceProviderFromDependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt new file mode 100644 index 0000000000000..766bcf3e32d20 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +Content from static dependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java new file mode 100644 index 0000000000000..fdd86cff545d7 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java @@ -0,0 +1,32 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdependency; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.DependencySPIConsumer; + +class ServiceProviderFromDependencyTest { + + @Test + void testSPI() { + DependencySPIConsumer dependencySPIConsumer = new DependencySPIConsumer<>(); + String transform = dependencySPIConsumer.transform(String::valueOf); + + Assertions.assertTrue(transform.startsWith("ServiceProviderFromDependency value")); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/pom.xml b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/pom.xml new file mode 100644 index 0000000000000..875bd62954f29 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + service-provider-from-dynamic-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of dynamic dependencies + + + true + + + + + org.talend.sdk.component.loading-analysis + loading-services-and-resources-lib + ${project.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + service.provider.from.dynamic.dependency + + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + talend-dependencies + + dependencies + + none + + + talend-component-bundle + + car + + none + + + talend-scan-descriptor + + scan-descriptor + + none + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.java b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.java new file mode 100644 index 0000000000000..24aae314ba952 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdynamicdependency; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency; + +public class ServiceProviderFromDynamicDependency implements StringProviderSPIAsDynamicDependency { + + @Override + public String getValueFromASPIAsDynamicDependency() { + return "ServiceProviderFromDynamicDependency value"; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/FROM_DYNAMIC_DEPENDENCY/resource.properties b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/FROM_DYNAMIC_DEPENDENCY/resource.properties new file mode 100644 index 0000000000000..2d3b4c75218c1 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/FROM_DYNAMIC_DEPENDENCY/resource.properties @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +ServiceProviderFromDynamicDependency.message=Message from a dynamic dependency resource. \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency new file mode 100644 index 0000000000000..915ba5a722d08 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdynamicdependency.ServiceProviderFromDynamicDependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt new file mode 100644 index 0000000000000..279c4384fed42 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +Content from dynamic dependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.java b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.java new file mode 100644 index 0000000000000..26ba4e69e6c81 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromdynamicdependency; + +import java.util.function.Function; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.DynamicDependencySPIConsumer; + +class ServiceProviderFromDependencyTest { + + @Test + void testSPI() { + DynamicDependencySPIConsumer useADynamicDependencySPI = new DynamicDependencySPIConsumer<>(); + String transform = useADynamicDependencySPI.transform(Function.identity()); + Assertions.assertTrue(transform.startsWith("ServiceProviderFromDynamicDependency value")); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/pom.xml b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/pom.xml new file mode 100644 index 0000000000000..3ee848b1b68d2 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + org.talend.sdk.component.loading-analysis + loading-analysis + 1.89.0-SNAPSHOT + + + service-provider-from-external-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of an external dependencies + + + true + + + + + org.talend.sdk.component.loading-analysis + loading-services-and-resources-lib + ${project.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + service.provider.from.external.dependency + + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + talend-dependencies + + dependencies + + none + + + talend-component-bundle + + car + + none + + + talend-scan-descriptor + + scan-descriptor + + none + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.java b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.java new file mode 100644 index 0000000000000..3d2deb857a77a --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromexternaldependency; + +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI; + +public class ServiceProviderFromExternalDependency implements StringProviderFromExternalSPI { + + @Override + public String getValueFromExternalSPI() { + return "ServiceProviderFromExternalDependency value"; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/FROM_EXTERNAL_DEPENDENCY/resource.properties b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/FROM_EXTERNAL_DEPENDENCY/resource.properties new file mode 100644 index 0000000000000..218bf5fc1676d --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/FROM_EXTERNAL_DEPENDENCY/resource.properties @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +ServiceProviderFromExternalDependency.message=Message from an external dependency resource. \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI new file mode 100644 index 0000000000000..066e53ef9a920 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.serviceInterfaces.StringProviderFromExternalSPI @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromexternaldependency.ServiceProviderFromExternalDependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt new file mode 100644 index 0000000000000..be53e984e90a0 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/main/resources/MULTIPLE_RESOURCE/content.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2006-2025 Talend Inc. - www.talend.com +# +# 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. +# Here you can change all your configuration display names to use more explicit labels +# You can also translate your configuration by adding one file by local Messages_fr.properties for french for example +Content from external dependency \ No newline at end of file diff --git a/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java new file mode 100644 index 0000000000000..1fd397ae79134 --- /dev/null +++ b/sample-parent/sample-features/loading-analysis/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/loadinganalysis/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2006-2025 Talend Inc. - www.talend.com + * + * 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 org.talend.sdk.component.sample.feature.loadinganalysis.serviceproviderfromexternaldependency; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.loadinganalysis.classloadertestlibrary.spiConsumers.ExternalDependencySPIConsumer; + +class ServiceProviderFromExternalDependencyTest { + + @Test + void testSPI() { + ExternalDependencySPIConsumer values = new ExternalDependencySPIConsumer<>(); + String transform = values.transform(String::valueOf); + Assertions.assertTrue(transform.startsWith("ServiceProviderFromExternalDependency value")); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/pom.xml b/sample-parent/sample-features/pom.xml index 2a62451c6b4c1..bb21239c455d3 100644 --- a/sample-parent/sample-features/pom.xml +++ b/sample-parent/sample-features/pom.xml @@ -27,31 +27,32 @@ Component Runtime :: Sample Features - - fixed-schema - aftergroup-lastgroup - database-mapping - conditional-outputs - checkpoint-runner - configuration-form - entry-with-error - actions-in-forms - + + fixed-schema + aftergroup-lastgroup + database-mapping + conditional-outputs + checkpoint-runner + configuration-form + actions-in-forms + entry-with-error + loading-analysis + - - - org.talend.sdk.component - component-api - ${project.version} - provided + + + org.talend.sdk.component + component-api + ${project.version} + provided org.talend.sdk.component component-runtime-junit ${project.version} test - - + +