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/dynamic-dependencies/README.md b/sample-parent/sample-features/dynamic-dependencies/README.md new file mode 100644 index 0000000000000..1a9914a75edc8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/README.md @@ -0,0 +1,211 @@ +# Dynamic Dependencies Module Documentation + +## Overview + +The `dynamic-dependencies` module provides several TCK connector plugins designed to validate the `@DynamicDependencies` feature in the Talend Component Kit. It contains 5 test connectors organized into two categories: dependencies checking and SPI (_Service Provider Interface_) checking. + +## Dependency Checking Connectors +All `dynamic-dependencies-with-*` provide a TCK connector that will get a list of dynamic dependencies (_defined with maven GAV_) and a list of dynamic loaded TCK connectors. They all rely on `dynamic-dependencies-common` to generate same kind of records. + +Each `dynamic-dependencies-with-*` module proposes its own implementation of a `@DynamicSchema` service, that serves a list of GAV, each expect a different kind of TCK configuration as parameter: +- `dynamic-dependencies-with-datastore` has a `@DynamicSchema` that expect a `@Datastore` +- `dynamic-dependencies-with-dataset` has a `@DynamicSchema` that expect a `@Dataset` +- `dynamic-dependencies-with-dynamicDependenciesConfiguration` has a `@DynamicSchema` that expect a `@DynamicDependenciesConfiguration` +- `dynamic-dependencies-with-dataPrepRunAnnotation` has a `@DynamicSchema` that expect a `@DynamicDependencySupported`. this annotation is cuurently provided and used in connectors-se/dataprep, and that should be removed afterward + +### Generated Records for Dependency Checkers + +All dependency checking connectors generate records through `AbstractDynamicDependenciesService.loadIterator()`. +Each record contains: + +- `maven`: GAV coordinate of the dependency (_this is set by the user in the connectors' configuration_) +- `class`: Class name being loaded (_this is set by the user in the connectors' configuration_) +- `is_loaded`: Whether the class was successfully loaded +- `connector_classloader`: Classloader ID of the connector +- `clazz_classloader`: Classloader ID of the loaded class +- `from_location`: JAR location where the class was found +- `is_tck_container`: Whether this is a TCK container +- `first_record`: First record from additional connectors (if any). If a record is retrieved, it means the connectors has been well loaded. +- `root_repository`: Maven repository path (if environment info enabled) +- `runtime_classpath`: Runtime classpath (if environment info enabled) +- `working_directory`: Current working directory (if environment info enabled) + +## SPI Checking Connector +The `jvm` provides the `Service Provider Interface` (_SPI_) mechanism. It allows to load implementations of interfaces without explicitly specifying them. The classloader search for all resource files in `META-INF/services/` that have the same name as the full qualified name of the interface you want some implementation. See more information in [ServiceLoader javadoc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html). The goal is to check that SPI implementations can be loaded in several case, for instance when the implementation is provided by a dynamic dependency or by te runtime, etc... + +### The dynamic-dependencies-with-spi module +It provides a connector that has `classloader-test-library` as dependency. This library contains several interfaces that have their implementations provided by `SPI` mechanism, loading them from `service-provided-from-*` modules. The connector will also try to load some resources from those modules: + +- `service-provider-from-dependency` is a direct dependency of `dynamic-dependencies-with-spi` + - It proposes those resource files to load: + - `FROM_DEPENDENCY/resource.properties` + - `MULTIPLE_RESOURCE/common.properties` +- `service-provider-from-dynamic-dependency` is a dynamic dependency returned by `DynamicDependenciesWithSPIService#getDynamicDependencies` service that is annotated with `@DynamicDependencies` + - It proposes those resource files to load: + - `FROM_DYNAMIC_DEPENDENCY/resource.properties` + - `MULTIPLE_RESOURCE/common.properties` +- `service-provider-from-external-dependency` is a library that should be loaded and provided by the runtime, for instance in a studio job, it should be loaded by a `tLibraryLoad` + - It proposes those resource files to load: + - `FROM_EXTERNAL_DEPENDENCY/resource.properties` + - `MULTIPLE_RESOURCE/common.properties` + +The connector in `dynamic-dependencies-with-spi` tries to load `FROM_xxxx/resource.properties` resources with `classloadOfTheDependency.getResourceAsStream(resource)`, and, it tries to load `MULTIPLE_RESOURCE/common.properties` with `classloadOfTheDependency.getResources("MULTIPLE_RESOURCE/common.properties")`. + +### Generated Records for SPI Checker + +The SPI connector generates 9 records total (3 from each SPI type) through `DynamicDependenciesWithSPIService.getRecordIterator()` [11](#3-10) . Each record contains: + +- `value`: Value from the SPI implementation + - Records 0-2: `ServiceProviderFromDependency_1`, `_2`, `_3` + - Records 3-5: `ServiceProviderFromDynamicDependency_1`, `_2`, `_3` + - Records 6-8: `ServiceProviderFromExternalDependency_1`, `_2`, `_3` +- `contentFromResourceDependency`: Content from `FROM_DEPENDENCY/resource.properties` +- `contentFromResourceDynamicDependency`: Content from `FROM_DYNAMIC_DEPENDENCY/resource.properties` +- `contentFromResourceExternalDependency`: Content from `FROM_EXTERNAL_DEPENDENCY/resource.properties` +- `contentFromMultipleResources`: Combined content from `MULTIPLE_RESOURCE/common.properties` + +## Module Structure + +### Core Module +- **dynamic-dependencies-common**: Shared library containing: + - `AbstractDynamicDependenciesService`: Base service for dependency loading and record generation [12](#3-11) + - Configuration interfaces (`DynamicDependencyConfig`, `Dependency`, `Connector`) + +### SPI Testing Modules +- **classloader-test-library**: Library providing SPI consumers for testing [13](#3-12) +- **service-provider-from-dependency**: SPI provider as standard dependency [14](#3-13) +- **service-provider-from-dynamic-dependency**: SPI provider loaded dynamically [15](#3-14) +- **service-provider-from-external-dependency**: SPI provider from runtime [16](#3-15) + +## Usage + +### Building +```bash +mvn clean install -am -pl :dynamicdependencies +``` + +### Testing in Studio +1. Deploy any connector CAR file to Studio: +```bash +java -jar dynamic-dependencies-with-dataset-1.88.0-SNAPSHOT.car studio-deploy --location +``` +2. Create a job with the connector +3. Click "Guess schema" to trigger dynamic dependency loading +4. Run the job to see generated diagnostic records [17](#3-16) + +## Using Connectors in Talend Studio Jobs + +This section provides step-by-step instructions for testing each dynamic dependencies connector in Talend Studio to validate all use cases. + +### Prerequisites + +1. Build all connectors: +```bash +mvn clean install -am -pl :dynamicdependencies +``` + +2. Deploy each connector CAR file to Studio: +```bash +java -jar dynamic-dependencies-with-dataset-1.88.0-SNAPSHOT.car studio-deploy --location +java -jar dynamic-dependencies-with-datastore-1.88.0-SNAPSHOT.car studio-deploy --location +java -jar dynamic-dependencies-with-dynamicDependenciesConfiguration-1.88.0-SNAPSHOT.car studio-deploy --location +java -jar dynamic-dependencies-with-dataprepRunAnnotation-1.88.0-SNAPSHOT.car studio-deploy --location +java -jar dynamic-dependencies-with-spi-1.88.0-SNAPSHOT.car studio-deploy --location +``` + +### Testing Dependency Checking Connectors + +#### Step 1: Create Test Job +1. Create a new Standard Job in Studio +2. Add the connector to test (e.g., `DynamicDependenciesWithDataset` > `Input`) +3. Add a `tLogRow` component to view output +4. Connect the connector to `tLogRow` + +#### Step 2: Configure Dependencies +For each dependency checking connector, configure the test dependency: + +1. Open the component configuration +2. In the **Dependencies** table, add: + - **Group ID**: `org.apache.commons` + - **Artifact ID**: `commons-numbers-primes` + - **Version**: `1.2` + - **Class**: `org.apache.commons.numbers.primes.SmallPrimes` + +3. Enable **Environment Information** to see additional diagnostic data + +#### Step 3: Validate Dynamic Loading +1. Click **Guess Schema** on the connector + - This triggers the `@DynamicDependencies` service + - Validates that the dependency is loaded dynamically +2. Check Studio logs for dependency loading messages +3. Run the job to generate diagnostic records + +#### Step 4: Verify Output Records +Check the `tLogRow` output for these fields: +- `maven`: Should show `org.apache.commons:commons-numbers-primes:1.2` +- `class`: Should show `org.apache.commons.numbers.primes.SmallPrimes` +- `is_loaded`: Should be `true` +- `from_location`: Path to the downloaded JAR +- Additional fields if environment info is enabled + +### Testing SPI Connector + +#### Step 1: Create SPI Test Job +1. Create a new Standard Job +2. Add `DynamicDependenciesWithSPI` > `Input` component +3. Add `tLogRow` component +4. Connect them + +#### Step 2: Validate SPI Loading +1. Click **Guess Schema** to trigger dynamic dependency loading +2. The connector will: + - Load `service-provider-from-dynamic-dependency` dynamically + - Discover SPI implementations from all three scopes +3. Run the job + +#### Step 3: Verify SPI Output +Check for 9 records with this pattern: + +| Record | value Field | Expected Content | +|--------|-------------|------------------| +| 0-2 | ServiceProviderFromDependency_1/2/3 | From standard dependency | +| 3-5 | ServiceProviderFromDynamicDependency_1/2/3 | From dynamic dependency | +| 6-8 | ServiceProviderFromExternalDependency_1/2/3 | From external dependency | + +Each record should also contain: +- `contentFromResourceDependency`: Message from standard dependency resource +- `contentFromResourceDynamicDependency`: Message from dynamic dependency resource +- `contentFromResourceExternalDependency`: Message from external dependency resource +- `contentFromMultipleResources`: Combined content from all dependencies + +### Validation Checklist + +For each connector, verify: + +- [ ] **Guess Schema** triggers without errors +- [ ] Dynamic dependencies are downloaded and loaded +- [ ] Generated records contain expected fields +- [ ] Class loading information is correct +- [ ] Resource loading works (for SPI connector) +- [ ] No classloader conflicts occur + +### Common Issues and Solutions + +1. **Dependency not found**: Check Maven repository configuration in Studio +2. **Class loading fails**: Verify the GAV coordinates and class name +3. **SPI not discovered**: Ensure all service provider modules are deployed +4. **Resource loading fails**: Check that resource files exist in the correct paths + +### Advanced Testing + +To test multiple dependencies or connectors: +1. Add multiple entries in the Dependencies/Connectors tables +2. Use different Maven coordinates +3. Verify that all dependencies are loaded and reported in the output + +## Notes + +- The `@DynamicDependencySupported` annotation in the dataprep module is temporary and should be removed after testing [18](#3-17) +- All modules use `org.talend.sdk.samplefeature.dynamicdependencies` as groupId to avoid automatic exclusion +- Test modules use `commons-numbers-primes` as a simulated dynamic dependency [19](#3-18) +- The SPI connector uses a custom classloader customizer to ensure proper SPI loading from different dependency scopes [20](#3-19) \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/pom.xml b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/pom.xml new file mode 100644 index 0000000000000..ab792bf04f8d7 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + classloader-test-library + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a classloader test library + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + dynamic.dependencies.classloadertestlibrary + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderFromExternalSPI.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderFromExternalSPI.java new file mode 100644 index 0000000000000..481ce4f0be810 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderFromExternalSPI.java @@ -0,0 +1,24 @@ +/** + * 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.dynamicdependencies.classloadertestlibrary.serviceInterfaces; + +import java.util.List; + +public interface StringsProviderFromExternalSPI extends StringsProviderSPI { + + List getStringsFromExternalSPI(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPI.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPI.java new file mode 100644 index 0000000000000..59b32fb7efda6 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPI.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.dynamicdependencies.classloadertestlibrary.serviceInterfaces; + +public interface StringsProviderSPI { + + int NB_VALUES = 3; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDependency.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDependency.java new file mode 100644 index 0000000000000..a911ce08ed536 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDependency.java @@ -0,0 +1,24 @@ +/** + * 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.dynamicdependencies.classloadertestlibrary.serviceInterfaces; + +import java.util.List; + +public interface StringsProviderSPIAsDependency extends StringsProviderSPI { + + List getStringsFromDependency(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDynamicDependency.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDynamicDependency.java new file mode 100644 index 0000000000000..eb30d5a7688c3 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/serviceInterfaces/StringsProviderSPIAsDynamicDependency.java @@ -0,0 +1,24 @@ +/** + * 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.dynamicdependencies.classloadertestlibrary.serviceInterfaces; + +import java.util.List; + +public interface StringsProviderSPIAsDynamicDependency extends StringsProviderSPI { + + List getStringsFromASPIAsDynamicDependency(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java new file mode 100644 index 0000000000000..4c1d6e1801b3e --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/AbstractSPIConsumer.java @@ -0,0 +1,71 @@ +/** + * 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.dynamicdependencies.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 org.talend.sdk.component.api.exception.ComponentException; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractSPIConsumer { + + private final Optional spiImpl; + + protected AbstractSPIConsumer(final Class clazz, final boolean failIfSeveralServicesFound) { + ServiceLoader serviceLoader = ServiceLoader.load(clazz); + + List stringMapProviderList = new ArrayList<>(); + serviceLoader.iterator().forEachRemaining(stringMapProviderList::add); + + if (stringMapProviderList.size() <= 0) { + log.error("No SPI service found for %s.".formatted(clazz)); + spiImpl = Optional.empty(); + return; + } + + if (stringMapProviderList.size() > 1 && failIfSeveralServicesFound) { + String join = stringMapProviderList.stream() + .map(m -> m.getClass().getName()) + .collect(Collectors.joining("\n")); + throw new ComponentException("More than one %s service has been found: %s" + .formatted(clazz, join)); + } + + this.spiImpl = Optional.of(stringMapProviderList.get(0)); + } + + public abstract List getValues(); + + public List transform(final Function function) { + List strings = this.getValues(); + return strings + .stream() + .map(function::apply) + .toList(); + } + + public Optional getSPIImpl() { + return this.spiImpl; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DependencySPIConsumer.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DependencySPIConsumer.java new file mode 100644 index 0000000000000..24b804cd8e2b7 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DependencySPIConsumer.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.dynamicdependencies.classloadertestlibrary.spiConsumers; + +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency; + +public class DependencySPIConsumer extends AbstractSPIConsumer { + + public DependencySPIConsumer(final boolean failIfSeveralServicesFound) { + super(StringsProviderSPIAsDependency.class, failIfSeveralServicesFound); + } + + public List getValues() { + return this.getSPIImpl().isPresent() ? this.getSPIImpl().get().getStringsFromDependency() + : List.of("[ERROR] StringsProviderSPIAsDependency not loaded!"); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.java new file mode 100644 index 0000000000000..6f6da8af04b11 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/DynamicDependencySPIConsumer.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.dynamicdependencies.classloadertestlibrary.spiConsumers; + +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency; + +public class DynamicDependencySPIConsumer extends AbstractSPIConsumer { + + public DynamicDependencySPIConsumer(final boolean failIfSeveralServicesFound) { + super(StringsProviderSPIAsDynamicDependency.class, failIfSeveralServicesFound); + } + + public List getValues() { + return this.getSPIImpl().isPresent() ? this.getSPIImpl().get().getStringsFromASPIAsDynamicDependency() + : List.of("[ERROR] StringsProviderSPIAsDynamicDependency not loaded!"); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.java b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.java new file mode 100644 index 0000000000000..543393a5d9ea4 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/classloadertestlibrary/spiConsumers/ExternalDependencySPIConsumer.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.dynamicdependencies.classloadertestlibrary.spiConsumers; + +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderFromExternalSPI; + +public class ExternalDependencySPIConsumer extends AbstractSPIConsumer { + + public ExternalDependencySPIConsumer(final boolean failIfSeveralServicesFound) { + super(StringsProviderFromExternalSPI.class, failIfSeveralServicesFound); + } + + public List getValues() { + return this.getSPIImpl().isPresent() ? this.getSPIImpl().get().getStringsFromExternalSPI() + : List.of("[ERROR] StringsProviderFromExternalSPI not loaded!"); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/resources/CLASSLOADER-TEST-LIBRARY/resource.properties b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/resources/CLASSLOADER-TEST-LIBRARY/resource.properties new file mode 100644 index 0000000000000..dfa17bc74aadd --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/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.dynamicdependencies.classloadertestlibrary.message=This is a resource file from classloader-test-library. \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/resources/MULTIPLE_RESOURCE/common.properties b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/src/main/resources/MULTIPLE_RESOURCE/common.properties new file mode 100644 index 0000000000000..80e0e08d4ada1 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/classloader-test-library/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/dynamic-dependencies/dynamic-dependencies-common/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/pom.xml new file mode 100644 index 0000000000000..6550a660db2b3 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + + + dynamic-dependencies-common + jar + Component Runtime :: Sample Feature @DynamicDependency Common + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + dynamic.dependencies.common + + + + + + + test-jar + + + + + + org.talend.sdk.component + talend-component-maven-plugin + ${project.version} + + + talend-component-validate + + false + false + false + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + + test-jar + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/Connector.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/Connector.java new file mode 100644 index 0000000000000..3aed79831e48e --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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 namer.") + 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/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/Dependency.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/Dependency.java new file mode 100644 index 0000000000000..08c1fde7ccc2c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/DynamicDependencyConfig.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/DynamicDependencyConfig.java new file mode 100644 index 0000000000000..ec866e68c5a19 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/DynamicDependencyConfig.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.dynamicdependencies.config; + +import java.util.List; + +public interface DynamicDependencyConfig { + + List getDependencies(); + + List getConnectors(); + + boolean isEnvironmentInformation(); + + boolean isDieOnError(); + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/service/AbstractDynamicDependenciesService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/service/AbstractDynamicDependenciesService.java new file mode 100644 index 0000000000000..62175dff7d4e1 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/service/AbstractDynamicDependenciesService.java @@ -0,0 +1,363 @@ +/** + * 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.dynamicdependencies.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.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.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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"; + + @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.samplefeature.dynamicdependencies", + "dynamic-dependencies-common", + "N/A", + "org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency")); + dependencies.addAll(dynamicDependencyConfig.getDependencies()); + for (Dependency dependency : dependencies) { + + 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); + } catch (ClassNotFoundException e) { + manageException(dynamicDependencyConfig.isDieOnError(), + "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()); + 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; + + } + + 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) { + 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); + + firstRecord.ifPresent(record -> builder.withRecord(ENTRY_FIRST_RECORD, record)); + + if (dynamicDependencyConfig.isEnvironmentInformation()) { + 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(); + } + + 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).build()); + if (dynamicDependencyConfig.isEnvironmentInformation()) { + 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()); + } + + 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 manageException(final boolean dieOnError, final String message, final Exception e) { + String msg = "Dynamic dependencies connector raised an exception: %s : %s".formatted(message, e.getMessage()); + log.error(msg, e); + if (dieOnError) { + throw new ComponentException(msg, e); + } + } + + protected List getDynamicDependencies(final List dependencies, + final List connectors) { + 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))) { + + 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(); + } + + /** + * Return true if the given path correspond to a class that has been loaded from a jar that contains + * a TALEND-INF/dependencies.txt file. + * + * @param path The clazz location + * @return true if the given path correspond to a TCK container + */ + private boolean isTCKContainer(final String path) { + // TO DO + return false; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/AbstractDynamicDependenciesServiceTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/AbstractDynamicDependenciesServiceTest.java new file mode 100644 index 0000000000000..270b228c525e1 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/AbstractDynamicDependenciesServiceTest.java @@ -0,0 +1,100 @@ +/** + * 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.dynamicdependencies; + +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_CLASS; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_CLAZZ_CLASSLOADER; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_CONNECTOR_CLASSLOADER; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_FROM_LOCATION; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_IS_LOADED; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_MAVEN; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_ROOT_REPOSITORY; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.service.AbstractDynamicDependenciesService.ENTRY_RUNTIME_CLASSPATH; +import static org.talend.sdk.component.sample.feature.dynamicdependencies.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.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.DynamicDependencyConfig; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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); + + Assertions.assertTrue(result.hasNext()); + this.assertRecord(result.next()); + Assertions.assertFalse(result.hasNext()); + } + + 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) { + Assertions.assertNotNull(record); + Assertions.assertEquals("org.apache.commons:commons-numbers-primes:1.2", record.getString(ENTRY_MAVEN)); + Assertions.assertEquals( + "org.apache.commons.numbers.primes.SmallPrimes", + record.getString(ENTRY_CLASS)); + Assertions.assertTrue(record.getBoolean(ENTRY_IS_LOADED)); + Assertions.assertNotNull(record.getString(ENTRY_CONNECTOR_CLASSLOADER)); + Assertions.assertTrue(record.getString(ENTRY_CONNECTOR_CLASSLOADER) + .startsWith("jdk.internal.loader.ClassLoaders$AppClassLoader")); + Assertions.assertNotNull(record.getString(ENTRY_CLAZZ_CLASSLOADER)); + Assertions.assertTrue(record.getString(ENTRY_CLAZZ_CLASSLOADER) + .startsWith("jdk.internal.loader.ClassLoaders$AppClassLoader")); + Assertions.assertNotNull(record.getString(ENTRY_FROM_LOCATION)); + Assertions.assertTrue(record.getString(ENTRY_FROM_LOCATION) + .endsWith( + "org/apache/commons/commons-numbers-primes/1.2/commons-numbers-primes-1.2.jar!/org/apache/commons/numbers/primes/SmallPrimes.class")); + Assertions.assertEquals("./lib/", record.getString(ENTRY_ROOT_REPOSITORY)); + Assertions.assertNotNull(record.getString(ENTRY_RUNTIME_CLASSPATH)); + Assertions.assertEquals(System.getProperty("user.dir"), record.getString(ENTRY_WORKING_DIRECTORY)); + Assertions.assertTrue(record.getString(ENTRY_RUNTIME_CLASSPATH).contains("commons-numbers-primes-1.2.jar")); + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/pom.xml new file mode 100644 index 0000000000000..09ec14904ce37 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + dynamic-dependencies-with-dataprepRunAnnotation + jar + Component Runtime :: Sample Feature @DynamicDependency with DataprepRun annotation + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + dynamic.dependencies.withDataprepRunAnnotation + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/annotation/DynamicDependencySupported.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/annotation/DynamicDependencySupported.java new file mode 100644 index 0000000000000..7c81044cfbce7 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/annotation/DynamicDependencySupported.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.sample.feature.dynamicdependencies.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/past of the annotation from tDataprepRun.") +public @interface DynamicDependencySupported { + + String value() default "default"; +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Config.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Config.java new file mode 100644 index 0000000000000..535e4b06acd90 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Config.java @@ -0,0 +1,74 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.DynamicDependencyConfig; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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" }), + @GridLayout.Row({ "environmentInformation" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "dieOnError" }) +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("Sub-configuration that contains the DynamidDependenciesConfiguration.") + private SubConfig subConfig = new SubConfig(); + + @Option + @Documentation("If enable throw an exception for any error, if not just log the error.") + private boolean dieOnError = false; + + @Option + @Documentation("More environment information.") + private boolean environmentInformation = false; + + @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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Dataset.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Dataset.java new file mode 100644 index 0000000000000..ea45a9daba395 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Dataset.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.dynamicdependencies.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.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dso" }) +}) +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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Datastore.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Datastore.java new file mode 100644 index 0000000000000..1749603106828 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/SubConfig.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/SubConfig.java new file mode 100644 index 0000000000000..97b8a8db6fb0a --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/input/DynamicDependenciesWithDataprepRunAnnotationInput.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/input/DynamicDependenciesWithDataprepRunAnnotationInput.java new file mode 100644 index 0000000000000..26ab1b60d7a09 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDataprepRunAnnotation.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/package-info.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/package-info.java new file mode 100644 index 0000000000000..f671561c7be2c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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 = "DynamicDependenciesWithDataprepAnnotation", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationService.java new file mode 100644 index 0000000000000..39f7e7ea4b08f --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..85e6a3e1e8eda --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataprepRun + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..85e6a3e1e8eda --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/icons/light/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataprepRun + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/Messages.properties new file mode 100644 index 0000000000000..6a100dc952c46 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDataprepAnnotation.datastore.dyndepsdso._displayName = Datastore for dynamic dependencies with datapreprun +DynamicDependenciesWithDataprepAnnotation.dataset.dyndepsdse._displayName = Dataset for dynamic dependencies with datapreprun \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Messages.properties new file mode 100644 index 0000000000000..1b0eda6eb9634 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/config/Messages.properties @@ -0,0 +1,24 @@ +# 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 = Dependencies +Config.dse._displayName = +Config.dieOnError._displayName = Die on error +Config.environmentInformation._displayName = Environment information +Config.subConfig._displayName = +SubConfig.dependencies._displayName = Dependencies +SubConfig.connectors._displayName = \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/input/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/input/Messages.properties new file mode 100644 index 0000000000000..a0c8970bddfa2 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDataprepAnnotation.Input._displayName = Dynamic Dependencies With DataprepRun annotation Input \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java new file mode 100644 index 0000000000000..c1097e2960ddc --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataprepRunAnnotation/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDataprepRunAnnotation/service/DynamicDependenciesDataprepRunAnnotationServiceTest.java @@ -0,0 +1,77 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDataprepRunAnnotation.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDataprepRunAnnotation.config.Dataset; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDataprepRunAnnotation.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.dynamicdependencies.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); + config.setEnvironmentInformation(true); + + return config; + } + + // use tck cnnector 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); + + // //for connector depend + // Dependency depend2 = new Dependency(); + // depend.setArtifactId("record-provider"); + // depend.setVersion("1.71.0-SNAPSHOT"); + // depend.setGroupId("org.talend.components"); + // depend.setClazz("org.talend.components.recordprovider.source.GenericMapper"); + // depends.add(depend2); + return depends; + } + + @Override + protected DynamicDependenciesDataprepRunAnnotationService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/pom.xml new file mode 100644 index 0000000000000..17ef3b9b34751 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/pom.xml @@ -0,0 +1,66 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + dynamic-dependencies-with-dataset + jar + Component Runtime :: Sample Feature @DynamicDependency with Dataset + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.component.dynamic.dependencies.withdataset + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Config.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Config.java new file mode 100644 index 0000000000000..95352ed168631 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Config.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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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({ "environmentInformation" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "dieOnError" }), +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("If enable throw an exception for any error, if not just log the error.") + private boolean dieOnError = false; + + @Option + @Documentation("More environment information.") + private boolean environmentInformation = false; + + @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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Dataset.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Dataset.java new file mode 100644 index 0000000000000..de1cd0b4ca719 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Dataset.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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }), + @GridLayout.Row({ "dependencies" }), + @GridLayout.Row({ "connectors" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dso" }) +}) +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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Datastore.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Datastore.java new file mode 100644 index 0000000000000..de540902c68ff --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/input/DynamicDependenciesWithDatasetInput.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/input/DynamicDependenciesWithDatasetInput.java new file mode 100644 index 0000000000000..30e4e53d5d897 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/package-info.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/package-info.java new file mode 100644 index 0000000000000..525faeb12ae02 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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 = "DynamicDependenciesWithDataset", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetService.java new file mode 100644 index 0000000000000..a532095bcc62b --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetService.java @@ -0,0 +1,48 @@ +/** + * 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.dynamicdependencies.withdataset.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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) { + return super.getDynamicDependencies(dataset.getDependencies(), dataset.getConnectors()); + } + + @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/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..3e6ba66a42db8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataset + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..3e6ba66a42db8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/icons/light/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataset + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/Messages.properties new file mode 100644 index 0000000000000..e2466c2844474 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDataset.datastore.dyndepsdso._displayName = Datastore for dynamic dependencies with dataset +DynamicDependenciesWithDataset.dataset.dyndepsdse._displayName = Dataset for dynamic dependencies with dataset \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/config/Messages.properties new file mode 100644 index 0000000000000..42b990411eaf6 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/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 = Dependencies +Config.dse._displayName = +Config.dieOnError._displayName = Die on error +Config.environmentInformation._displayName = Environment information +Dataset.connectors._displayName = \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/input/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/input/Messages.properties new file mode 100644 index 0000000000000..43d63aaae3a02 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDataset.Input._displayName = Dynamic Dependencies With Dataset Input \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java new file mode 100644 index 0000000000000..1602ef1a7fa83 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dataset/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdataset/service/DynamicDependenciesWithDatasetServiceTest.java @@ -0,0 +1,56 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdataset.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdataset.config.Dataset; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdataset.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.dynamicdependencies.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); + config.setEnvironmentInformation(true); + + return config; + } + + @Override + protected DynamicDependenciesWithDatasetService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/pom.xml new file mode 100644 index 0000000000000..0668afefe3c3a --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + dynamic-dependencies-with-datastore + jar + Component Runtime :: Sample Feature @DynamicDependency with Datastore + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.component.dynamic.dependencies.withdatastore + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Config.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Config.java new file mode 100644 index 0000000000000..50b8591e816f3 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Config.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.dynamicdependencies.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.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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({ "environmentInformation" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "dieOnError" }), +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("If enable throw an exception for any error, if not just log the error.") + private boolean dieOnError = false; + + @Option + @Documentation("More environment information.") + private boolean environmentInformation = false; + + @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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Dataset.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Dataset.java new file mode 100644 index 0000000000000..abc52e5ec91c4 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Dataset.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.dynamicdependencies.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.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dso" }) +}) +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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Datastore.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Datastore.java new file mode 100644 index 0000000000000..8218f4e27f7cc --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/input/DynamicDependenciesWithDatastoreInput.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/input/DynamicDependenciesWithDatastoreInput.java new file mode 100644 index 0000000000000..09159bfbc339d --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/package-info.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/package-info.java new file mode 100644 index 0000000000000..84c17f8fc511b --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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 = "DynamicDependenciesWithDatastore", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/service/DynamicDependenciesWithDatastoreService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/service/DynamicDependenciesWithDatastoreService.java new file mode 100644 index 0000000000000..ea08f69beb09c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..750d837d60cec --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDatastore + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..750d837d60cec --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/icons/light/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDatastore + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/Messages.properties new file mode 100644 index 0000000000000..54e6e670c24ff --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDatastore.datastore.dyndepsdso._displayName = Datastore for dynamic dependencies with datastore +DynamicDependenciesWithDatastore.dataset.dyndepsdse._displayName = Dataset for dynamic dependencies with datastore \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/config/Messages.properties new file mode 100644 index 0000000000000..2a933f364e575 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/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 + +Datastore.dependencies._displayName = Dependences +Dataset.dso._displayName = +Config.dse._displayName = +Config.dieOnError._displayName = Die on error +Config.environmentInformation._displayName = Environment information +Datastore.connectors._displayName = \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/input/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/input/Messages.properties new file mode 100644 index 0000000000000..686de01008376 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDatastore.Input._displayName = Dynamic Dependencies With Datastore Input \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java new file mode 100644 index 0000000000000..465e126902f54 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-datastore/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withdatastore/service/DynamicDependenciesWithDatastoreServiceTest.java @@ -0,0 +1,56 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdatastore.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdatastore.config.Dataset; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withdatastore.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents(value = "org.talend.sdk.component.sample.feature.dynamicdependencies.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); + config.setEnvironmentInformation(true); + + return config; + } + + @Override + protected DynamicDependenciesWithDatastoreService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/pom.xml new file mode 100644 index 0000000000000..77b00dd412b75 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + dynamic-dependencies-with-dynamicDependenciesConfiguration + jar + Component Runtime :: Sample Feature @DynamicDependency with DynamicDependenciesConfiguration + + + org.talend.sdk.component:dynamic-dependencies-common + include-exclude + + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + test-jar + test + + + + org.apache.commons + commons-numbers-primes + 1.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.component.dynamic.dependencies.withDynamicDependenciesConfiguration + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Config.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Config.java new file mode 100644 index 0000000000000..cd2c88cbd673b --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Config.java @@ -0,0 +1,71 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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" }), + @GridLayout.Row({ "environmentInformation" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "dieOnError" }), +}) +public class Config implements DynamicDependencyConfig, Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("Sub-configuration that contains the DynamidDependenciesConfiguration.") + private SubConfig subConfig = new SubConfig(); + + @Option + @Documentation("If enable throw an exception for any error, if not just log the error.") + private boolean dieOnError = false; + + @Option + @Documentation("More environment information.") + private boolean environmentInformation = false; + + @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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Dataset.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Dataset.java new file mode 100644 index 0000000000000..8bd5960324df2 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Dataset.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.dynamicdependencies.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.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }) +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dso" }) +}) +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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Datastore.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Datastore.java new file mode 100644 index 0000000000000..3c3dbdc92160e --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/SubConfig.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/SubConfig.java new file mode 100644 index 0000000000000..12efa3c258d42 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.config.Connector; +import org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/input/DynamicDependenciesWithDynamicDependenciesConfigurationInput.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/input/DynamicDependenciesWithDynamicDependenciesConfigurationInput.java new file mode 100644 index 0000000000000..335322e79b7fb --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.service.DynamicDependenciesWithDynamicependenciesConfigurationService; + +@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 DynamicDependenciesWithDynamicependenciesConfigurationService service; + + private Iterator recordIterator; + + public DynamicDependenciesWithDynamicDependenciesConfigurationInput(final Config config, + final DynamicDependenciesWithDynamicependenciesConfigurationService 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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/package-info.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/package-info.java new file mode 100644 index 0000000000000..fcc2ed3c55c47 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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 = "DynamicDependenciesWithDynamicDependenciesConfiguration", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationService.java new file mode 100644 index 0000000000000..3d0057a5fafec --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationService.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.dynamicdependencies.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.dynamicdependencies.service.AbstractDynamicDependenciesService; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.SubConfig; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithDynamicependenciesConfigurationService 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/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..75edf24718ba0 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDynDepConf + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..75edf24718ba0 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/icons/light/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDynDepConf + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/Messages.properties new file mode 100644 index 0000000000000..c86de8883106d --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDynamicDependenciesConfiguration.datastore.dyndepsdso._displayName = Datastore for dynamic dependencies With DynamicDependenciesConfiguration +DynamicDependenciesWithDynamicDependenciesConfiguration.dataset.dyndepsdse._displayName = Dataset for dynamic dependencies With DynamicDependenciesConfiguration \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Messages.properties new file mode 100644 index 0000000000000..2585384578ebd --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/config/Messages.properties @@ -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. +# 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.dieOnError._displayName = Die on error +Config.environmentInformation._displayName = Environment information +Config.subConfig._displayName = +SubConfig.dependencies._displayName = Dependencies +SubConfig.connectors._displayName = \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/input/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/input/Messages.properties new file mode 100644 index 0000000000000..b252d46a5697c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithDynamicDependenciesConfiguration.Input._displayName = Dynamic Dependencies With DynamicDependenciesConfiguration Input \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationServiceTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationServiceTest.java new file mode 100644 index 0000000000000..7b2bc3083c4a4 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-dynamicDependenciesConfiguration/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withDynamicDependenciesConfiguration/service/DynamicDependenciesWithDynamicependenciesConfigurationServiceTest.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.dynamicdependencies.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.dynamicdependencies.AbstractDynamicDependenciesServiceTest; +import org.talend.sdk.component.sample.feature.dynamicdependencies.config.Dependency; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.Dataset; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration.config.Datastore; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@WithComponents( + value = "org.talend.sdk.component.sample.feature.dynamicdependencies.withDynamicDependenciesConfiguration") +public class DynamicDependenciesWithDynamicependenciesConfigurationServiceTest + extends + AbstractDynamicDependenciesServiceTest { + + @Service + DynamicDependenciesWithDynamicependenciesConfigurationService 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); + config.setEnvironmentInformation(true); + + return config; + } + + @Override + protected DynamicDependenciesWithDynamicependenciesConfigurationService getService() { + return dynamicDependenciesServiceService; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/pom.xml b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/pom.xml new file mode 100644 index 0000000000000..8a9fe4bca3f7d --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/pom.xml @@ -0,0 +1,87 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + dynamic-dependencies-with-spi + jar + Component Runtime :: Sample Feature @DynamicDependency with spi + + + + org.talend.sdk.component + component-runtime-manager + ${project.version} + provided + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies-common + ${project.version} + + + org.talend.sdk.samplefeature.dynamicdependencies + classloader-test-library + ${project.version} + + + org.talend.sdk.samplefeature.dynamicdependencies + service-provider-from-dependency + ${project.version} + + + org.talend.sdk.samplefeature.dynamicdependencies + service-provider-from-dynamic-dependency + ${project.version} + test + + + org.talend.sdk.samplefeature.dynamicdependencies + service-provider-from-external-dependency + ${project.version} + test + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.component.dynamic.dependencies.withspi + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Config.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Config.java new file mode 100644 index 0000000000000..31b3b04ae1f03 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Config.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.dynamicdependencies.withspi.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; + +/** + * For this sample, the same configuration is used for all connectors input/processor/output. + */ +@Data +@GridLayout({ + @GridLayout.Row({ "dse" }), +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dse" }), + @GridLayout.Row({ "dieOnError" }), +}) +public class Config implements Serializable { + + @Option + @Documentation("The dataset configuration.") + private Dataset dse = new Dataset(); + + @Option + @Documentation("If enable throw an exception for any error, if not just log the error.") + private boolean dieOnError = false; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Dataset.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Dataset.java new file mode 100644 index 0000000000000..bbb28640b0c6b --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Dataset.java @@ -0,0 +1,46 @@ +/** + * 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.dynamicdependencies.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.GridLayout; +import org.talend.sdk.component.api.meta.Documentation; + +import lombok.Data; + +@Data +@DataSet("dyndepsdse") +@GridLayout(value = { + @GridLayout.Row({ "dso" }), + @GridLayout.Row({ "bbb" }), +}) +@GridLayout(names = GridLayout.FormType.ADVANCED, value = { + @GridLayout.Row({ "dso" }) +}) +public class Dataset implements Serializable { + + @Option + @Documentation("A datastore.") + private Datastore dso = new Datastore(); + + @Option + @Documentation("Xxxx xxx.") + private String bbb; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Datastore.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Datastore.java new file mode 100644 index 0000000000000..91d74dac3fdb6 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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("Xxxx xxx.") + private String aaa; + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/DynamicDependenciesWithSPIInput.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/DynamicDependenciesWithSPIInput.java new file mode 100644 index 0000000000000..3e26377bbed1c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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.dynamicdependencies.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.dynamicdependencies.withspi.config.Config; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.service.DynamicDependenciesWithSPIService; + +@Version +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +@Emitter(name = "Input") +@Documentation("Dynamic dependencies sample input connector.") +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/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/package-info.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/package-info.java new file mode 100644 index 0000000000000..8f684f5ab8500 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/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 = "DynamicDependenciesWithSPI", + categories = "sample") +@Icon(value = Icon.IconType.CUSTOM, custom = "icon") +package org.talend.sdk.component.sample.feature.dynamicdependencies.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/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/CustomizeClassLoader.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/CustomizeClassLoader.java new file mode 100644 index 0000000000000..2fb302a9540c8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/CustomizeClassLoader.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.dynamicdependencies.withspi.service; + +import java.util.stream.Stream; + +import org.talend.sdk.component.runtime.manager.ComponentManager; + +public class CustomizeClassLoader implements ComponentManager.Customizer { + + @Override + public Stream containerClassesAndPackages() { + return Stream.of( + // Implementation should come from a dynamic dependency + "org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency", + // Implementation should come from runtime + "org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency"); + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/DynamicDependenciesWithSPIService.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/DynamicDependenciesWithSPIService.java new file mode 100644 index 0000000000000..3d1e71c5b869c --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/service/DynamicDependenciesWithSPIService.java @@ -0,0 +1,194 @@ +/** + * 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.dynamicdependencies.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 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.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.dynamicdependencies.classloadertestlibrary.spiConsumers.DependencySPIConsumer; +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.spiConsumers.DynamicDependencySPIConsumer; +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.spiConsumers.ExternalDependencySPIConsumer; +import org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.config.Dataset; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class DynamicDependenciesWithSPIService implements Serializable { + + private static String version; + + @Service + private RecordBuilderFactory recordBuilderFactory; + + @DynamicDependencies + public List getDynamicDependencies(@Option("theDataset") final Dataset dataset) { + String dep = "org.talend.sdk.samplefeature.dynamicdependencies:service-provider-from-dynamic-dependency:" + + loadVersion(); + return Collections.singletonList(dep); + } + + @DiscoverSchema("dyndepsdse") + public Schema guessSchema4Input(final @Option("configuration") Dataset dse) { + Iterator recordIterator = getRecordIterator(); + if (!recordIterator.hasNext()) { + throw new ComponentException("No data loaded from StringMapTransformer."); + } + + Record record = recordIterator.next(); + return record.getSchema(); + } + + public Iterator getRecordIterator() { + 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 { + boolean isFirst = true; + Enumeration resources = DynamicDependenciesWithSPIService.class.getClassLoader() + .getResources("MULTIPLE_RESOURCE/common.properties"); + + StringBuilder stringBuilder = new StringBuilder(); + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + + try (InputStream is = url.openStream()) { + String content = filterComments(is); + stringBuilder.append(content); + if (!isFirst) { + stringBuilder.append(System.lineSeparator()); + } + isFirst = false; + } + } + contentFromMultipleResources = stringBuilder.toString(); + } catch (IOException e) { + throw new ComponentException("Can't retrieve multiple resources at once.", e); + } + + DependencySPIConsumer dependencySPIConsumer = new DependencySPIConsumer<>(true); + List recordsFromDependencySPI = dependencySPIConsumer + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("contentFromResourceDependency", contentFromResourceDependency) + .withString("contentFromResourceDynamicDependency", contentFromResourceDynamicDependency) + .withString("contentFromResourceExternalDependency", contentFromResourceExternalDependency) + .withString("contentFromMultipleResources", contentFromMultipleResources) + .build()); + + DynamicDependencySPIConsumer dynamicDependencySPIConsumer = new DynamicDependencySPIConsumer<>(true); + List recordsFromDynamicDependencySPI = dynamicDependencySPIConsumer + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("contentFromResourceDependency", contentFromResourceDependency) + .withString("contentFromResourceDynamicDependency", contentFromResourceDynamicDependency) + .withString("contentFromMultipleResources", contentFromMultipleResources) + .build()); + + ExternalDependencySPIConsumer externalDependencySPI = new ExternalDependencySPIConsumer<>(true); + List recordsFromExternalSPI = externalDependencySPI + .transform(s -> recordBuilderFactory.newRecordBuilder() + .withString("value", s) + .withString("contentFromResourceDependency", contentFromResourceDependency) + .withString("contentFromResourceDynamicDependency", contentFromResourceDynamicDependency) + .withString("contentFromMultipleResources", contentFromMultipleResources) + .build()); + + List values = new ArrayList<>(); + values.addAll(recordsFromDependencySPI); + values.addAll(recordsFromDynamicDependencySPI); + values.addAll(recordsFromExternalSPI); + + return values.iterator(); + } + + private static String loadVersion() { + if (version == null) { + try (InputStream is = DynamicDependenciesWithSPIService.class.getClassLoader() + .getResourceAsStream("version.properties")) { + 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) { + BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); + + String collect = reader.lines() + .filter(line -> !line.trim().startsWith("#")) + .filter(line -> !line.trim().isEmpty()) + .collect(Collectors.joining(System.lineSeparator())); + try { + reader.close(); + } catch (IOException e) { + throw new ComponentException("Can't close a resource reader.", e); + } + + return collect; + } + + 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/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer new file mode 100644 index 0000000000000..5f7ce3b1beea4 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer @@ -0,0 +1 @@ +org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.service.CustomizeClassLoader \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/dark/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/dark/icon.svg new file mode 100644 index 0000000000000..3e6ba66a42db8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/dark/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataset + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/light/icon.svg b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/light/icon.svg new file mode 100644 index 0000000000000..3e6ba66a42db8 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/icons/light/icon.svg @@ -0,0 +1,66 @@ + + + + + + DynamicDependenciesDataset + diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/Messages.properties new file mode 100644 index 0000000000000..07fabc121dc11 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithSPI.datastore.dyndepsdso._displayName = Datastore for dynamic dependencies With SPI +DynamicDependenciesWithSPI.dataset.dyndepsdse._displayName = Dataset for dynamic dependencies With SPI +DynamicDependenciesWithSPI.actions.schema.dyndepsdse._displayName = Dynamic dependencies With SPI discover schema \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/config/Messages.properties new file mode 100644 index 0000000000000..a83b1f07a4954 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/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 = +Config.dse._displayName = +Config.dieOnError._displayName =Die on error +Datastore.aaa._displayName = +Dataset.bbb._displayName = +Datastore.aaa._placeholder = +Dataset.bbb._placeholder = \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/Messages.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/Messages.properties new file mode 100644 index 0000000000000..5d3c3478cce11 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/org/talend/sdk/component/sample/feature/dynamicdependencies/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 + +DynamicDependenciesWithSPI.Input._displayName = Dynamic Dependencies With SPI Input \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/version.properties b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/main/resources/version.properties new file mode 100644 index 0000000000000..c7c8d1f0f47db --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/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/dynamic-dependencies/dynamic-dependencies-with-spi/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/DynamicDependenciesWithSPIInputTest.java b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/DynamicDependenciesWithSPIInputTest.java new file mode 100644 index 0000000000000..89c674ff52dc0 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-with-spi/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/withspi/input/DynamicDependenciesWithSPIInputTest.java @@ -0,0 +1,71 @@ +/** + * 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.dynamicdependencies.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.dynamicdependencies.withspi.config.Config; + +@WithComponents("org.talend.sdk.component.sample.feature.dynamicdependencies.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", "DynamicDependenciesWithSPI://Input?" + queryString) + .component("collector", "test://collector") + .connections() + .from("input") + .to("collector") + .build() + .run(); + + List collectedData = handler.getCollectedData(Record.class); + Assertions.assertEquals(9, collectedData.size()); + + int i = 0; + for (; i < 3; i++) { + Assertions.assertEquals("ServiceProviderFromDependency_" + (i + 1), + collectedData.get(i).getString("value")); + } + + for (; i < 6; i++) { + Assertions.assertEquals("ServiceProviderFromDynamicDependency_" + (i - 2), + collectedData.get(i).getString("value")); + } + + for (; i < 9; i++) { + Assertions.assertEquals("ServiceProviderFromExternalDependency_" + (i - 5), + collectedData.get(i).getString("value")); + } + + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/pom.xml b/sample-parent/sample-features/dynamic-dependencies/pom.xml new file mode 100644 index 0000000000000..6941d099636bc --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/pom.xml @@ -0,0 +1,53 @@ + + + + 4.0.0 + + org.talend.sdk.component + sample-features + 1.88.0-SNAPSHOT + + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + pom + + Component Runtime :: Sample Feature @DynamicDependency + + dynamic-dependencies-common + dynamic-dependencies-with-dataset + dynamic-dependencies-with-datastore + dynamic-dependencies-with-dynamicDependenciesConfiguration + dynamic-dependencies-with-dataprepRunAnnotation + dynamic-dependencies-with-spi + classloader-test-library + service-provider-from-dependency + service-provider-from-dynamic-dependency + service-provider-from-external-dependency + + + + + org.talend.sdk.component + component-runtime-junit + ${project.version} + test + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/pom.xml b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/pom.xml new file mode 100644 index 0000000000000..7cd7a8ce0a669 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + service-provider-from-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of dependencies + + + + org.talend.sdk.samplefeature.dynamicdependencies + classloader-test-library + 1.88.0-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.samplefeature.dynamicdependencies.serviceproviderfromdependency + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependency.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependency.java new file mode 100644 index 0000000000000..dad741a38bd86 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependency.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.sample.feature.dynamicdependencies.serviceproviderfromdependency; + +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency; + +public class ServiceProviderFromDependency implements StringsProviderSPIAsDependency { + + public List getStringsFromDependency() { + List values = new ArrayList<>(); + for (int i = 1; i <= NB_VALUES; i++) { + values.add("ServiceProviderFromDependency_" + i + "/" + NB_VALUES + + " loaded from classloader: " + this.getClass().getClassLoader()); + } + return values; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/resources/FROM_DEPENDENCY/resource.properties b/sample-parent/sample-features/dynamic-dependencies/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/dynamic-dependencies/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/dynamic-dependencies/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency new file mode 100644 index 0000000000000..2210f4f2d3539 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDependency @@ -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.dynamicdependencies.serviceproviderfromdependency.ServiceProviderFromDependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties new file mode 100644 index 0000000000000..8f2c010153f00 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/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 independent dependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java new file mode 100644 index 0000000000000..d05767b1904e9 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdependency/ServiceProviderFromDependencyTest.java @@ -0,0 +1,39 @@ +/** + * 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.dynamicdependencies.serviceproviderfromdependency; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.spiConsumers.DependencySPIConsumer; + +class ServiceProviderFromDependencyTest { + + @Test + void testSPI() { + DependencySPIConsumer integerListTransformer = new DependencySPIConsumer<>(true); + List transform = integerListTransformer.transform(String::valueOf); + List sorted = new ArrayList<>(transform); + sorted.sort(String::compareTo); + String collect = String.join("/", sorted); + Assertions.assertEquals("ServiceProviderFromDependency_1/" + + "ServiceProviderFromDependency_2/ServiceProviderFromDependency_3", + collect); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/pom.xml b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/pom.xml new file mode 100644 index 0000000000000..f3b6aef2f86d2 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + service-provider-from-dynamic-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of dynamic dependencies + + + + org.talend.sdk.samplefeature.dynamicdependencies + classloader-test-library + ${project.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.samplefeature.dynamicdependencies.serviceproviderfromdynamicdependency + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.java new file mode 100644 index 0000000000000..709cf29ba5ca5 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDynamicDependency.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.sample.feature.dynamicdependencies.serviceproviderfromdynamicdependency; + +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency; + +public class ServiceProviderFromDynamicDependency implements StringsProviderSPIAsDynamicDependency { + + @Override + public List getStringsFromASPIAsDynamicDependency() { + List values = new ArrayList<>(); + for (int i = 1; i <= NB_VALUES; i++) { + values.add("ServiceProviderFromDynamicDependency_" + i + "/" + NB_VALUES + + " loaded from classloader: " + this.getClass().getClassLoader()); + } + return values; + } +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/FROM_DYNAMIC_DEPENDENCY/resource.properties b/sample-parent/sample-features/dynamic-dependencies/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/dynamic-dependencies/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/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency new file mode 100644 index 0000000000000..cc4ed0ca6c8e3 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderSPIAsDynamicDependency @@ -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.dynamicdependencies.serviceproviderfromdynamicdependency.ServiceProviderFromDynamicDependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties new file mode 100644 index 0000000000000..c130ce1b42e6f --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/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 dynamic dependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.java new file mode 100644 index 0000000000000..2c38cc7ac5489 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-dynamic-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromdynamicdependency/ServiceProviderFromDependencyTest.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.dynamicdependencies.serviceproviderfromdynamicdependency; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.spiConsumers.DynamicDependencySPIConsumer; + +class ServiceProviderFromDependencyTest { + + @Test + void testSPI() { + DynamicDependencySPIConsumer useADynamicDependencySPI = new DynamicDependencySPIConsumer<>(true); + List transform = useADynamicDependencySPI.transform(Function.identity()); + List sorted = new ArrayList<>(transform); + sorted.sort(String::compareTo); + String collect = String.join("/", sorted); + Assertions.assertEquals("ServiceProviderFromDynamicDependency_1/" + + "ServiceProviderFromDynamicDependency_2/ServiceProviderFromDynamicDependency_3", + collect); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/pom.xml b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/pom.xml new file mode 100644 index 0000000000000..b1fd55d9efc99 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + org.talend.sdk.samplefeature.dynamicdependencies + dynamic-dependencies + 1.88.0-SNAPSHOT + + + service-provider-from-external-dependency + + jar + Component Runtime :: Sample Feature @DynamicDependency :: a service provider that should be part of an external dependencies + + + + org.talend.sdk.samplefeature.dynamicdependencies + classloader-test-library + 1.88.0-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.talend.sdk.samplefeature.dynamicdependencies.serviceproviderfromexternaldependency + + + + + + + + \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.java new file mode 100644 index 0000000000000..d540e7c4d28ea --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependency.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.sample.feature.dynamicdependencies.serviceproviderfromexternaldependency; + +import java.util.ArrayList; +import java.util.List; + +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderFromExternalSPI; + +public class ServiceProviderFromExternalDependency implements StringsProviderFromExternalSPI { + + public List getStringsFromExternalSPI() { + List values = new ArrayList<>(); + for (int i = 1; i <= NB_VALUES; i++) { + values.add("ServiceProviderFromExternalDependency_" + i + "/" + NB_VALUES + + " loaded from classloader: " + this.getClass().getClassLoader()); + } + return values; + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/FROM_EXTERNAL_DEPENDENCY/resource.properties b/sample-parent/sample-features/dynamic-dependencies/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/dynamic-dependencies/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/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderFromExternalSPI b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderFromExternalSPI new file mode 100644 index 0000000000000..5ad242d22eb76 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/META-INF/services/org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringsProviderFromExternalSPI @@ -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.dynamicdependencies.serviceproviderfromexternaldependency.ServiceProviderFromExternalDependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/main/resources/MULTIPLE_RESOURCE/common.properties new file mode 100644 index 0000000000000..b98702b679641 --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/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 external dependency \ No newline at end of file diff --git a/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java new file mode 100644 index 0000000000000..fb4f54b0ce84a --- /dev/null +++ b/sample-parent/sample-features/dynamic-dependencies/service-provider-from-external-dependency/src/test/java/org/talend/sdk/component/sample/feature/dynamicdependencies/serviceproviderfromexternaldependency/ServiceProviderFromExternalDependencyTest.java @@ -0,0 +1,39 @@ +/** + * 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.dynamicdependencies.serviceproviderfromexternaldependency; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.spiConsumers.ExternalDependencySPIConsumer; + +class ServiceProviderFromExternalDependencyTest { + + @Test + void testSPI() { + ExternalDependencySPIConsumer values = new ExternalDependencySPIConsumer<>(true); + List transform = values.transform(String::valueOf); + List sorted = new ArrayList<>(transform); + sorted.sort(String::compareTo); + String collect = String.join("/", sorted); + Assertions.assertEquals("ServiceProviderFromExternalDependency_1/" + + "ServiceProviderFromExternalDependency_2/ServiceProviderFromExternalDependency_3", + collect); + } + +} \ No newline at end of file diff --git a/sample-parent/sample-features/pom.xml b/sample-parent/sample-features/pom.xml index 2a62451c6b4c1..e5383b0d9083c 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 + dynamic-dependencies + - - - 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 - - + +