Skip to content

Conversation

@ypiel-talend
Copy link
Contributor

Requirements

https://qlik-dev.atlassian.net/browse/QTDI-1914

  • Any code change adding any logic MUST be tested through a unit test executed with the default build
  • Any API addition MUST be done with a documentation update if relevant

Why this PR is needed?

What does this PR adds (design/code thoughts)?

ypiel-talend and others added 30 commits October 23, 2025 00:32
…:Talend/component-runtime into ypiel/QTDI-1914_sample_connector_dyndeps
#	sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/config/Dependency.java
#	sample-parent/sample-features/dynamic-dependencies/dynamic-dependencies-common/src/main/java/org/talend/sdk/component/sample/feature/dynamicdependencies/service/AbstractDynamicDependenciesService.java
ypiel-talend and others added 20 commits November 28, 2025 15:31
# Conflicts:
#	sample-parent/sample-features/pom.xml
…st log + add an error messae in returned strings.
…st log + add an error messae in returned strings.
@ypiel-talend ypiel-talend requested a review from Copilot February 2, 2026 16:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a comprehensive sample connector module demonstrating dynamic dependency loading capabilities. The implementation showcases how to use the @DynamicDependencies annotation with various configuration types (datastore, dataset, and custom configuration) and validates SPI loading from different dependency scopes.

Changes:

  • Added new dynamic-dependencies module with multiple sample connectors demonstrating @DynamicDependencies feature
  • Introduced DynamicDependenciesConfiguration annotation for marking configuration types that compute dynamic dependencies
  • Created supporting modules for SPI testing and classloader validation

Reviewed changes

Copilot reviewed 99 out of 110 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
sample-parent/sample-features/pom.xml Added dynamic-dependencies module to the build
component-api/src/main/java/.../DynamicDependenciesConfiguration.java New annotation for marking dynamic dependency configuration types
sample-parent/sample-features/dynamic-dependencies/pom.xml Parent POM defining the dynamic-dependencies module structure
sample-parent/sample-features/dynamic-dependencies/README.md Comprehensive documentation explaining the dynamic dependencies feature and test scenarios
sample-parent/sample-features/dynamic-dependencies/*/pom.xml Module-specific POM files for various sample connectors
sample-parent/sample-features/dynamic-dependencies//src/main/java/**/.java Implementation classes for sample connectors, services, and configuration
sample-parent/sample-features/dynamic-dependencies//src/test/java/**/.java Test classes validating dynamic dependency loading

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sonar-eks
Copy link

sonar-eks bot commented Feb 2, 2026

Failed Quality Gate failed

  • 3.15% Duplicated Lines (%) on New Code (is greater than 3.00%)
  • 72 New Issues (is greater than 0)

Project ID: org.talend.sdk.component:component-runtime

View in SonarQube

@ypiel-talend ypiel-talend changed the title chore(QTDI-1914): Sample dynamic schema connector. feat(QTDI-1914): Sample dynamic schema connector. Feb 6, 2026
@ypiel-talend ypiel-talend requested a review from Copilot February 9, 2026 17:28
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 99 out of 110 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +68 to +74
public List<String> getDynamicDependencies(@Option("theDataset") final Dataset dataset) {
String dep = "org.talend.sdk.samplefeature.dynamicdependencies:service-provider-from-dynamic-dependency:"
+ loadVersion();
List<String> strings = Collections.singletonList(dep);
log.info("Dynamic dependencies with SPI: {}", strings.stream().collect(Collectors.joining(";")));
return strings;
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The returned Maven coordinate uses a groupId (org.talend.sdk.samplefeature.dynamicdependencies) that doesn’t match the groupId declared by the modules in this PR (org.talend.sdk.component.loading-analysis). This will make the runtime/designtime resolver look for a non-existent artifact. Update the coordinate to match the actual groupId/artifactId of service-provider-from-dynamic-dependency.

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +51
return Stream.of(
// Implementation should come from a dynamic dependency
"org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDependency",
// Implementation should come from runtime
"org.talend.sdk.component.sample.feature.dynamicdependencies.classloadertestlibrary.serviceInterfaces.StringProviderSPIAsDynamicDependency");
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The returned class names reference ...sample.feature.dynamicdependencies... but the actual packages added in this PR are ...sample.feature.loadinganalysis.... With the current values, the customizer won’t match the intended classes/packages, so the classloader customization won’t take effect. Replace these strings with the correct org.talend.sdk.component.sample.feature.loadinganalysis... FQNs.

Copilot uses AI. Check for mistakes.
}

log.info(
"org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.service.CustomizeClassLoader is enable,\n"
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct grammar in the log message: “is enable” → “is enabled”.

Suggested change
"org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.service.CustomizeClassLoader is enable,\n"
"org.talend.sdk.component.sample.feature.dynamicdependencies.withspi.service.CustomizeClassLoader is enabled,\n"

Copilot uses AI. Check for mistakes.
Comment on lines +230 to +242
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;
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getResourceAsStream("version.properties") can return null (missing resource or wrong filtering), and props.load(is) will throw a NullPointerException which is not caught here. Throw a ComponentException with a clear message when is == null, and consider also handling missing "version" property.

Copilot uses AI. Check for mistakes.

Properties prop = new Properties();
prop.load(resourceStreamFromDependency);
return prop.getProperty(property);
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prop.getProperty(property) can return null when the property key is missing, and later JsonObjectBuilder.add(key, value) will throw if value is null. Return a non-null fallback (similar to the “resource not found” branch) or throw a ComponentException when the property is absent.

Suggested change
return prop.getProperty(property);
final String value = prop.getProperty(property);
if (value == null) {
return "The property '%s' has not been found in resource '%s', it can't retrieve its value."
.formatted(property, resource);
}
return value;

Copilot uses AI. Check for mistakes.

private final Optional<S> spiImpl;

protected AbstractSPIConsumer(final Class clazz) {
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses a raw Class type, losing type safety (and it will generate warnings). Change the signature to accept a parameterized type (for example, Class<S>) and pass that through to ServiceLoader.load(...) so the consumer can be used safely without unchecked operations.

Suggested change
protected AbstractSPIConsumer(final Class clazz) {
protected AbstractSPIConsumer(final Class<S> clazz) {

Copilot uses AI. Check for mistakes.

public static final String ENTRY_RUNTIME_CLASSPATH = "runtime_classpath";

public static final String ENTRY_WORKING_DIRECTORY = "Working_directory";
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entry name is inconsistent with the rest of the schema keys (ENTRY_RUNTIME_CLASSPATH, ENTRY_ROOT_REPOSITORY, etc.) which are lower snake-case. Consider changing it to working_directory (and keep README/tests aligned) to avoid surprising API consumers and reduce schema/key mismatches.

Suggested change
public static final String ENTRY_WORKING_DIRECTORY = "Working_directory";
public static final String ENTRY_WORKING_DIRECTORY = "working_directory";

Copilot uses AI. Check for mistakes.

@Slf4j
@Service
public class DynamicDependenciesWithDynamicependenciesConfigurationService extends AbstractDynamicDependenciesService
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class name contains a typo (“Dynamicependencies”). Since this is part of a sample/public surface area, it will propagate into generated docs, logs, and code references. Rename to DynamicDependenciesWithDynamicDependenciesConfigurationService (and align related test/class references) to keep naming consistent and searchable.

Suggested change
public class DynamicDependenciesWithDynamicependenciesConfigurationService extends AbstractDynamicDependenciesService
public class DynamicDependenciesWithDynamicDependenciesConfigurationService extends AbstractDynamicDependenciesService

Copilot uses AI. Check for mistakes.
@Target(TYPE)
@Retention(RUNTIME)
@ConfigurationType("configuration")
@Documentation("Copy/past of the annotation from tDataprepRun." +
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in documentation text: “Copy/past” → “Copy/paste”.

Suggested change
@Documentation("Copy/past of the annotation from tDataprepRun." +
@Documentation("Copy/paste of the annotation from tDataprepRun." +

Copilot uses AI. Check for mistakes.
```

## Check SPI and resource loading
The `dynamic-depdencies-with-spi` provides an input connector that will try to load:
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in module name: “dynamic-depdencies-with-spi” → “dynamic-dependencies-with-spi”.

Suggested change
The `dynamic-depdencies-with-spi` provides an input connector that will try to load:
The `dynamic-dependencies-with-spi` provides an input connector that will try to load:

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants