Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f692cad
chore(QTDI-1914): Sample dynamic schema connector.
ypiel-talend Oct 22, 2025
e53256c
Add 2 params
yyin-talend Oct 23, 2025
b4705a0
chore(QTDI-1914): remove unused option in dso, environment info manag…
ypiel-talend Oct 23, 2025
1a76af5
Add 2 connectors: dataset, datastore with tests
yyin-talend Oct 27, 2025
8c10ae1
Add 2 connectors: dataset, datastore with tests
yyin-talend Oct 27, 2025
189ac9e
chore(QTDI-1914): Some adjustments.
ypiel-talend Oct 27, 2025
51c2838
chore(QTDI-1914): Working unit test.
ypiel-talend Oct 27, 2025
a921b04
chore(QTDI-1914): working dynamic dependencies connectors.
ypiel-talend Oct 27, 2025
54714b7
fix labels
yyin-talend Oct 28, 2025
d52d6eb
chore(QTDI-1914): fix artifact group id for dependency.
ypiel-talend Oct 28, 2025
e55a7a4
refactor junits
yyin-talend Oct 29, 2025
0c8e974
add working directory in output
yyin-talend Oct 29, 2025
3b18693
chore(QTDI-1914): Improve and unit test and fix labels.
ypiel-talend Oct 29, 2025
360f13d
chore(QTDI-1914): Add a connector with same behavior as datapreprun.
ypiel-talend Oct 30, 2025
136b654
fix layout for dieOnError
yyin-talend Oct 31, 2025
c3e7ad0
Fix dataprepRunAnnotation connector
yyin-talend Oct 31, 2025
2417f80
feat(QTDI-1914): Cleanings.
ypiel-talend Nov 4, 2025
fdde448
Add Readme
yyin-talend Nov 5, 2025
55bd365
Merge branch 'master' into ypiel/QTDI-1914_sample_connector_dyndeps
yyin-talend Nov 10, 2025
0572b53
feat(QTDI-1914): try to execute a TCK connector to check if it is wel…
ypiel-talend Nov 10, 2025
6ff4e06
Merge branch 'ypiel/QTDI-1914_sample_connector_dyndeps' of github.com…
ypiel-talend Nov 10, 2025
06da286
Add function to load depended component's depends
yyin-talend Nov 12, 2025
fe550fc
# Conflicts:
yyin-talend Nov 18, 2025
caef44a
rename
yyin-talend Nov 18, 2025
15c4e2d
fix junit
yyin-talend Nov 18, 2025
132e0d9
fix(QTDI-1914): some refactoring.
ypiel-talend Nov 18, 2025
578c338
feat(QTDI-1914): Add a connector taht uses a SPI.
ypiel-talend Nov 25, 2025
2dc763d
feat(QTDI-1914): remove unnecessary dependency.
ypiel-talend Nov 25, 2025
fabc258
feat(QTDI-1914): Add a test on the spi.
ypiel-talend Nov 25, 2025
15759e1
feat(QTDI-1914): Change the SPI interface and add a unit test.
ypiel-talend Nov 26, 2025
9bb8698
Merge branch 'master' into ypiel/QTDI-1914_sample_connector_dyndeps
ypiel-talend Nov 26, 2025
bc2ded4
feat(QTDI-1914): Update pom version in dynamic-dependencies modules.
ypiel-talend Nov 26, 2025
d282b18
feat(QTDI-1914): Clean pom.xml in dynamic-dependencies sample module.
ypiel-talend Nov 27, 2025
07e2722
feat(QTDI-1914): try to add a classloader customizer.
ypiel-talend Nov 27, 2025
208067a
feat(QTDI-1914): Fix customizer SPI resource file.
ypiel-talend Nov 27, 2025
646d9ab
feat(QTDI-1914): Add some resources to be loaded.
ypiel-talend Nov 27, 2025
cad9132
feat(QTDI-1914): Add multiple resources load.
ypiel-talend Nov 27, 2025
e94f6ce
feat(QTDI-1914): Add SPI resource for classloader customizer.
ypiel-talend Nov 28, 2025
08548c9
feat(QTDI-1914): Rename StringMapTransformer t o StringListTransformer.
ypiel-talend Nov 28, 2025
2d94660
feat(QTDI-1914): Refactoring + external dependency.
ypiel-talend Dec 1, 2025
103c741
feat(QTDI-1914): Add a class from standard dependency.
ypiel-talend Dec 4, 2025
9e50baf
feat(QTDI-1914): Complete the readme.md.
ypiel-talend Dec 4, 2025
4239689
feat(QTDI-1914): Complete the readme.md.
ypiel-talend Dec 4, 2025
33dd8e2
feat(QTDI-1914): fix json2Map and record builder
undx Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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";
}
2 changes: 1 addition & 1 deletion sample-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
211 changes: 211 additions & 0 deletions sample-parent/sample-features/dynamic-dependencies/README.md
Original file line number Diff line number Diff line change
@@ -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 <studio-path>
```
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 <studio-path>
java -jar dynamic-dependencies-with-datastore-1.88.0-SNAPSHOT.car studio-deploy --location <studio-path>
java -jar dynamic-dependencies-with-dynamicDependenciesConfiguration-1.88.0-SNAPSHOT.car studio-deploy --location <studio-path>
java -jar dynamic-dependencies-with-dataprepRunAnnotation-1.88.0-SNAPSHOT.car studio-deploy --location <studio-path>
java -jar dynamic-dependencies-with-spi-1.88.0-SNAPSHOT.car studio-deploy --location <studio-path>
```

### 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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.talend.sdk.samplefeature.dynamicdependencies</groupId>
<artifactId>dynamic-dependencies</artifactId>
<version>1.88.0-SNAPSHOT</version>
</parent>

<artifactId>classloader-test-library</artifactId>

<packaging>jar</packaging>
<name>Component Runtime :: Sample Feature @DynamicDependency :: a classloader test library</name>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>dynamic.dependencies.classloadertestlibrary</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -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 {

List<String> getStringsFromExternalSPI();

}
Original file line number Diff line number Diff line change
@@ -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 {

List<String> getStringsFromDependency();

}
Original file line number Diff line number Diff line change
@@ -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 {

List<String> getStringsFromASPIAsDynamicDependency();

}
Loading
Loading