<commit_before>= Talend Component Kit Extension Points
:page-talend_skipindexation:

This pages lists most of the extension points the framework provides for integrators.

== Customize the isolation

This can be useful to customize which libraries are shared accross all components - to inject a new global service - or prevent some libraries to be loaded from components even if provided in the `dependencies.txt`.

The entry point to do that is the `org.talend.sdk.component.runtime.manager.ComponentManager.Customizer` SPI:

[source,java]
----
// don't forget the META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer file containing the fully qualified name of this class
public class MyCustomizer implements ComponentManager.Customizer {
    @Override
    public Stream<String> containerClassesAndPackages() {
        return asList("com.company.shared", "com.othercompany.sharedtoo");
    }
}
----

== Handle the beam isolation in a custom fashion

If you import `component-runtime-beam`, Apache Beam SDK will be isolated by default. However, in some cases or some environment,
you will desire to handle it yourself in a more precise manner.

If you want to prevent Talend Component Kit to isolate itself Apache Beam from components, you can implement a `Customizer` - see previous part,
and the `ignoreBeamClassLoaderExclusions` method:

[source,java]
----
// don't forget the META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer file containing the fully qualified name of this class
public class MyCustomizer implements ComponentManager.Customizer {
    @Override
    public Stream<String> containerClassesAndPackages() {
        return singletonList("org.apache.beam."); // likely too wide since IO are generally isolated
    }

    @Override
    public boolean ignoreBeamClassLoaderExclusions() {
        return true;
    }
}
----

=== Override default packages/classes without a customizer

`org.talend.sdk.component.runtime.beam.customizer.Indices` now reads the exclusions for the current environment (Direct Runner and Spark supported) from a resource file.
It can be overriden adding into the classpath (beam one) the resource `TALEND-INF/classloader/indices/${artifactId}.overriden` file.
Each line is a package/class belonging to the runner infrastructure (and skipped from component specific classloader).

== ParameterExtensionEnricher

The option model of the configuration of the component is pluggable to enable to add any custom metadata needed.
It relies on `ParameterExtensionEnricher` SPI which can be seen as a visitor API for annotations on options.
Each annotation is then converted in a map of properties.

IMPORTANT: it is highly recommended to scope the entries in the map using a dedicated prefix.

Some meta annotation - like `@Ui` - enable to add metadata without adding an enricher.
Typically if you have an annotation with `@Ui` on it, then your annotation will be processed by the default ui enricher and will not need to register a custom one.

Finally, this API enables to add implicitly annotation on options based on their type. For instance, for `ZonedDateTime` we add implicitly - no user action - the annotation `@DateTime`.

== Handle component dependencies in a custom fashion

If you want to read the dependencies of the component in a fully custom fashion, you can disable it through the `Customizer` returning `true` in `ignoreDefaultDependenciesDescriptor`.
Then, you will need to implement `org.talend.sdk.component.runtime.manager.ComponentManager$ContainerClasspathContributor` (it is a SPI too).

TIP: the contributor is used even if no customizer disabled dependencies, this means you can use it to *enrich* component classpath and not only redefine it.

== Change the way Component are mapped to a model

This part is very useful for component using a potential other API - but not generic, i.e. 1 class == 1 component.

The SPI is `org.talend.sdk.component.spi.component.ComponentExtension`.

It enables to:

1. Add specific dependencies (for instance beam for beam components),
2. Add transformers (to modify the bytecode of the component + dependencies),
3. Provide an alternative way to instantiate components,
4. Disable the validation of components - if you know you used an incompatible programming model.

== Activate component specific transformers to patch the dependencies code

Use the SPI `org.talend.sdk.component.container.AutoClassFileTransformer` from the component itself
and enable the component to depend on ASM - a shade is provided by the framework.

== Enrich the classpath of the server

The component server is a plain link:http://openwebbeans.apache.org/meecrowave/[Apache Meecrowave] server and therefore a plain Java process.

To add your custom extensions to it, you just have to add your `.jar` in its classpath.

For the docker image, you can use the `/opt/talend/component-kit/custom` folder to host all the extensions (+ their dependencies if neeed).

WARNING: if you add extensions which are required at rutime too - like modifying the way Apache Beam is handled or the isolation is defined, don't forget to also add your extension to your runtime.

== Modify the way the UiSpec is generated

`component-form` enables to generate to UiSpec for a component configuration. It has good defaults aligned on `@talend/ui`, however if you have some advanced needs, you can customize the way it computes the specification.

First, the `org.talend.sdk.component.form.api.UiSpecService#withConverter` method of the service enables to add custom handlers for property mapping.
A converter will be responsible to convert a component option to its rendering specification if it supports the property.
It can also reuse existing converters if needed:

[source,java]
----
pulic class MyConverter implements CustomPropertyConverter {
    @Override
    public boolean supports(final PropertyContext<?> context) {
        return context.getProperty().getName().equals("entry");
    }
<commit_msg>fixed typo<commit_after>= Talend Component Kit Extension Points
:page-talend_skipindexation:

This pages lists most of the extension points the framework provides for integrators.

== Customize the isolation

This can be useful to customize which libraries are shared accross all components - to inject a new global service - or prevent some libraries to be loaded from components even if provided in the `dependencies.txt`.

The entry point to do that is the `org.talend.sdk.component.runtime.manager.ComponentManager.Customizer` SPI:

[source,java]
----
// don't forget the META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer file containing the fully qualified name of this class
public class MyCustomizer implements ComponentManager.Customizer {
    @Override
    public Stream<String> containerClassesAndPackages() {
        return asList("com.company.shared", "com.othercompany.sharedtoo");
    }
}
----

== Handle the beam isolation in a custom fashion

If you import `component-runtime-beam`, Apache Beam SDK will be isolated by default. However, in some cases or some environment,
you will desire to handle it yourself in a more precise manner.

If you want to prevent Talend Component Kit to isolate itself Apache Beam from components, you can implement a `Customizer` - see previous part,
and the `ignoreBeamClassLoaderExclusions` method:

[source,java]
----
// don't forget the META-INF/services/org.talend.sdk.component.runtime.manager.ComponentManager$Customizer file containing the fully qualified name of this class
public class MyCustomizer implements ComponentManager.Customizer {
    @Override
    public Stream<String> containerClassesAndPackages() {
        return singletonList("org.apache.beam."); // likely too wide since IO are generally isolated
    }

    @Override
    public boolean ignoreBeamClassLoaderExclusions() {
        return true;
    }
}
----

=== Override default packages/classes without a customizer

`org.talend.sdk.component.runtime.beam.customizer.Indices` now reads the exclusions for the current environment (Direct Runner and Spark supported) from a resource file.
It can be overriden adding into the classpath (beam one) the resource `TALEND-INF/classloader/indices/${artifactId}.overriden` file.
Each line is a package/class belonging to the runner infrastructure (and skipped from component specific classloader).

== ParameterExtensionEnricher

The option model of the configuration of the component is pluggable to enable to add any custom metadata needed.
It relies on `ParameterExtensionEnricher` SPI which can be seen as a visitor API for annotations on options.
Each annotation is then converted in a map of properties.

IMPORTANT: it is highly recommended to scope the entries in the map using a dedicated prefix.

Some meta annotation - like `@Ui` - enable to add metadata without adding an enricher.
Typically if you have an annotation with `@Ui` on it, then your annotation will be processed by the default ui enricher and will not need to register a custom one.

Finally, this API enables to add implicitly annotation on options based on their type. For instance, for `ZonedDateTime` we add implicitly - no user action - the annotation `@DateTime`.

== Handle component dependencies in a custom fashion

If you want to read the dependencies of the component in a fully custom fashion, you can disable it through the `Customizer` returning `true` in `ignoreDefaultDependenciesDescriptor`.
Then, you will need to implement `org.talend.sdk.component.runtime.manager.ComponentManager$ContainerClasspathContributor` (it is a SPI too).

TIP: the contributor is used even if no customizer disabled dependencies, this means you can use it to *enrich* component classpath and not only redefine it.

== Change the way Component are mapped to a model

This part is very useful for component using a potential other API - but not generic, i.e. 1 class == 1 component.

The SPI is `org.talend.sdk.component.spi.component.ComponentExtension`.

It enables to:

1. Add specific dependencies (for instance beam for beam components),
2. Add transformers (to modify the bytecode of the component + dependencies),
3. Provide an alternative way to instantiate components,
4. Disable the validation of components - if you know you used an incompatible programming model.

== Activate component specific transformers to patch the dependencies code

Use the SPI `org.talend.sdk.component.container.AutoClassFileTransformer` from the component itself
and enable the component to depend on ASM - a shade is provided by the framework.

== Enrich the classpath of the server

The component server is a plain link:http://openwebbeans.apache.org/meecrowave/[Apache Meecrowave] server and therefore a plain Java process.

To add your custom extensions to it, you just have to add your `.jar` in its classpath.

For the docker image, you can use the `/opt/talend/component-kit/custom` folder to host all the extensions (+ their dependencies if neeed).

WARNING: if you add extensions which are required at rutime too - like modifying the way Apache Beam is handled or the isolation is defined, don't forget to also add your extension to your runtime.

== Modify the way the UiSpec is generated

`component-form` enables to generate to UiSpec for a component configuration. It has good defaults aligned on `@talend/ui`, however if you have some advanced needs, you can customize the way it computes the specification.

First, the `org.talend.sdk.component.form.api.UiSpecService#withConverter` method of the service enables to add custom handlers for property mapping.
A converter will be responsible to convert a component option to its rendering specification if it supports the property.
It can also reuse existing converters if needed:

[source,java]
----
public class MyConverter implements CustomPropertyConverter {
    @Override
    public boolean supports(final PropertyContext<?> context) {
        return context.getProperty().getName().equals("entry");
    }

{'fraction_non_alphanumeric': 0.06064623032311516, 'fraction_numerical': 0.0009942004971002485, 'mean_word_length': 4.583256244218316, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1220711', 'n_tokens_mistral': 2988, 'n_tokens_neox': 2889, 'n_words': 1511}