Component server and HTTP API

HTTP API

The HTTP API intends to expose most Talend Component Kit features over HTTP. It is a standalone Java HTTP server.

The WebSocket protocol is activated for the endpoints. Endpoints then use /websocket/v1 as base instead of /api/v1. See WebSocket for more details.

Browse the API description using OpenAPI interface.

To make sure that the migration can be enabled, you need to set the version the component was created with in the execution configuration that you send to the server (component version is in component the detail endpoint). To do that, use tcomp::component::version key.

Deprecated endpoints

Endpoints that are intended to disappear will be deprecated. A X-Talend-Warning header will be returned with a message as value.

WebSocket transport

You can connect yo any endpoint by:

  1. Replacing /api with /websocket

  2. Appending /<http method> to the URL

  3. Formatting the request as:

SEND
destination: <endpoint after v1>
<headers>

<payload>^@

For example:

SEND
destination: /component/index
Accept: application/json

^@

The response is formatted as follows:

MESSAGE
status: <http status code>
<headers>

<payload>^@
All endpoints are logged at startup. You can then find them in the logs if you have a doubt about which one to use.

If you don’t want to create a pool of connections per endpoint/verb, you can use the bus endpoint: /websocket/v1/bus. This endpoint requires that you add the destinationMethod header to each request with the verb value (GET by default):

SEND
destination: /component/index
destinationMethod: GET
Accept: application/json

^@

Server configuration

the configuration is read from system properties, environment variables, …​.
talend.component.server.cache.maxSize

Default value: 1000. Maximum items a cache can store, used for index endpoints.

talend.component.server.component.coordinates

A comma separated list of gav to locate the components

talend.component.server.component.documentation.translations

Default value: ${home}/documentations. A component translation repository. This is where you put your documentation translations. Their name must follow the pattern documentation_${container-id}_language.adoc where ${container-id} is the component jar name (without the extension and version, generally the artifactId).

talend.component.server.component.extend.dependencies

Default value: true. Should the component extensions add required dependencies.

talend.component.server.component.extension.maven.repository

If you deploy some extension, where they can create their dependencies if needed.

talend.component.server.component.extension.startup.timeout

Default value: 180000. Timeout for extension initialization at startup, since it ensures the startup wait extensions are ready and loaded it allows to control the latency it implies.

talend.component.server.component.registry

A property file (or multiple comma separated) where the value is a gav of a component to register(complementary with coordinates). Note that the path can end up with or .properties to take into account all properties in a folder.

talend.component.server.documentation.active

Default value: true. Should the /documentation endpoint be activated. Note that when called on localhost the doc is always available.

talend.component.server.environment.active

Default value: true. Should the /api/v1/environment endpoint be activated. It shows some internal versions and git commit which are not always desirable over the wire.

talend.component.server.gridlayout.translation.support

Default value: false. Should the components using a @GridLayout support tab translation. Studio does not suppot that feature yet so this is not enabled by default.

talend.component.server.icon.paths

Default value: icons/%s.svg,icons/svg/%s.svg,icons/%s_icon32.png,icons/png/%s_icon32.png. These patterns are used to find the icons in the classpath(s).

talend.component.server.jaxrs.exceptionhandler.defaultMessage

Default value: false. If set it will replace any message for exceptions. Set to false to use the actual exception message.

talend.component.server.lastUpdated.useStartTime

Default value: false. Should the lastUpdated timestamp value of /environment endpoint be updated with server start time.

talend.component.server.locale.mapping

Default value: en*=en fr*=fr zh*=zh_CN ja*=ja de*=de. For caching reasons the goal is to reduce the locales to the minimum required numbers. For instance we avoid fr and fr_FR which would lead to the same entries but x2 in terms of memory. This mapping enables that by whitelisting allowed locales, default being en. If the key ends with it means all string starting with the prefix will match. For instance fr will match fr_FR but also fr_CA.

talend.component.server.maven.repository

The local maven repository used to locate components and their dependencies

talend.component.server.plugins.reloading.active

Default value: false. Should the plugins be un-deployed and re-deployed.

talend.component.server.plugins.reloading.interval

Default value: 600. Interval in seconds between each check if plugins re-loading is enabled.

talend.component.server.plugins.reloading.marker

Specify a file to check its timestamp on the filesystem. This file will take precedence of the default ones provided by the talend.component.server.component.registry property (used for timestamp method).

talend.component.server.plugins.reloading.method

Default value: timestamp. Re-deploy method on a timestamp or connectors version change. By default, the timestamp is checked on the file pointed by talend.component.server.component.registry or talend.component.server.plugins.reloading.marker variable, otherwise we inspect the content of the CONNECTORS_VERSION file. Accepted values: timestamp, anything else defaults to connectors.

talend.component.server.request.log

Default value: false. Should the all requests/responses be logged (debug purposes - only work when running with CXF).

talend.component.server.security.command.handler

Default value: securityNoopHandler. How to validate a command/request. Accepted values: securityNoopHandler.

talend.component.server.security.connection.handler

Default value: securityNoopHandler. How to validate a connection. Accepted values: securityNoopHandler.

talend.component.server.user.extensions.location

A folder available for the server - don’t forget to mount it in docker if you are using the image - which accepts subfolders named as component plugin id (generally the artifactId or jar name without the version, ex: jdbc). Each family folder can contain:

  • a user-configuration.properties file which will be merged with component configuration system (see services). This properties file enables the function userJar(xxxx) to replace the jar named xxxx by its virtual gav (groupId:artifactId:version),

  • a list of jars which will be merged with component family classpath

talend.component.server.user.extensions.provisioning.location

Default value: auto. Should the implicit artifacts be provisionned to a m2. If set to auto it tries to detect if there is a m2 to provision - recommended, if set to skip it is ignored, else it uses the value as a m2 path.

Configuration mechanism

The configuration uses Microprofile Config for most entries. It means it can be passed through system properties and environment variables (by replacing dots with underscores and making the keys uppercase).

To configure a Docker image rather than a standalone instance, Docker Config and secrets integration allows you to read the configuration from files. You can customize the configuration of these integrations through system properties.

Docker integration provides a secure: support to encrypt values and system properties, when required.

It is fully implemented using the Apache Geronimo Microprofile Config extensions.

HTTPS activation

Using the server ZIP (or Docker image), you can configure HTTPS by adding properties to _JAVA_OPTIONS. Assuming that you have a certificate in /opt/certificates/component.p12 (don’t forget to add/mount it in the Docker image if you use it), you can activate it as follows:

# use -e for Docker and `--https=8443` to set the port
#
# this skips the http port binding and only binds https on the port 8443, and setups the correct certificate
export _JAVA_OPTIONS="-Dskip-http=true -Dssl=true -Dhttps=8443 -Dkeystore-type=PKCS12 -Dkeystore-alias=talend -Dkeystore-password=talend -Dkeystore-file=/opt/certificates/component.p12"

Defining queries

You can define simple queries on the configuration types and components endpoints. These two endpoints support different parameters.

Queries on the configurationtype/index endpoint supports the following parameters:

  • type

  • id

  • name

  • metadata of the first configuration property as parameters.

Queries on the component/index endpoint supports the following parameters:

  • plugin

  • name

  • id

  • familyId

  • metadata of the first configuration property as parameters.

In both cases, you can combine several conditions using OR and AND operators. If you combine more than two conditions, note that they are evaluated in the order they are written.

Each supported parameter in a condition can be "equal to" (=) or "not equal to" (!=) a defined value (case-sensitive).

For example:

(metadata[configurationtype::type] = dataset) AND (plugin = jdbc-component) OR (name = input)

In this example, the query gets components that have a dataset and belong to the jdbc-component plugin, or components that are named input.

Web forms and REST API

The component-form library provides a way to build a component REST API facade that is compatible with React form library.

for example:

@Path("tacokit-facade")
@ApplicationScoped
public class ComponentFacade {
    private static final String[] EMPTY_ARRAY = new String[0];

    @Inject
    private Client client;

    @Inject
    private ActionService actionService;

    @Inject
    private UiSpecService uiSpecService;

    @Inject // assuming it is available in your app, use any client you want
    private WebTarget target;

    @POST
    @Path("action")
    public void action(@Suspended final AsyncResponse response, @QueryParam("family") final String family,
            @QueryParam("type") final String type, @QueryParam("action") final String action,
            final Map<String, Object> params) {
        client.action(family, type, action, params).handle((r, e) -> {
            if (e != null) {
                onException(response, e);
            } else {
                response.resume(actionService.map(type, r));
            }
            return null;
        });
    }

    @GET
    @Path("index")
    public void getIndex(@Suspended final AsyncResponse response,
            @QueryParam("language") @DefaultValue("en") final String language) {
        target
                .path("component/index")
                .queryParam("language", language)
                .request(APPLICATION_JSON_TYPE)
                .rx()
                .get(ComponentIndices.class)
                .toCompletableFuture()
                .handle((index, e) -> {
            if (e != null) {
                onException(response, e);
            } else {
                index.getComponents().stream().flatMap(c -> c.getLinks().stream()).forEach(
                        link -> link.setPath(link.getPath().replaceFirst("/component/", "/application/").replace(
                                "/details?identifiers=", "/detail/")));
                response.resume(index);
            }
            return null;
        });
    }

    @GET
    @Path("detail/{id}")
    public void getDetail(@Suspended final AsyncResponse response,
            @QueryParam("language") @DefaultValue("en") final String language, @PathParam("id") final String id) {
        target
                .path("component/details")
                .queryParam("language", language)
                .queryParam("identifiers", id)
                .request(APPLICATION_JSON_TYPE)
                .rx()
                .get(ComponentDetailList.class)
                .toCompletableFuture()
                .thenCompose(result -> uiSpecService.convert(result.getDetails().iterator().next()))
                .handle((result, e) -> {
                    if (e != null) {
                        onException(response, e);
                    } else {
                        response.resume(result);
                    }
                    return null;
                });
    }

    private void onException(final AsyncResponse response, final Throwable e) {
        final UiActionResult payload;
        final int status;
        if (WebException.class.isInstance(e)) {
            final WebException we = WebException.class.cast(e);
            status = we.getStatus();
            payload = actionService.map(we);
        } else if (CompletionException.class.isInstance(e)) {
            final CompletionException actualException = CompletionException.class.cast(e);
            log.error(actualException.getMessage(), actualException);
            status = Response.Status.BAD_GATEWAY.getStatusCode();
            payload = actionService.map(new WebException(actualException, -1, emptyMap()));
        } else {
            log.error(e.getMessage(), e);
            status = Response.Status.BAD_GATEWAY.getStatusCode();
            payload = actionService.map(new WebException(e, -1, emptyMap()));
        }
        response.resume(new WebApplicationException(Response.status(status).entity(payload).build()));
    }
}
the Client can be created using ClientFactory.createDefault(System.getProperty("app.components.base", "http://localhost:8080/api/v1")) and the service can be a simple new UiSpecService<>(). The factory uses JAX-RS if the API is available (assuming a JSON-B provider is registered). Otherwise, it tries to use Spring.

The conversion from the component model (REST API) to the uiSpec model is done through UiSpecService. It is based on the object model which is mapped to a UI model. Having a flat model in the component REST API allows to customize layers easily.

You can completely control the available components, tune the rendering by switching the uiSchema, and add or remove parts of the form. You can also add custom actions and buttons for specific needs of the application.

The /migrate endpoint was not shown in the previous snippet but if you need it, add it as well.

Using the UiSpec model without the tooling

<dependency>
  <groupId>org.talend.sdk.component</groupId>
  <artifactId>component-form-model</artifactId>
  <version>${talend-component-kit.version}</version>
</dependency>

This Maven dependency provides the UISpec model classes. You can use the Ui API (with or without the builders) to create UiSpec representations.

For Example:

final Ui form1 = ui()
    .withJsonSchema(JsonSchema.jsonSchemaFrom(Form1.class).build()) (1)
    .withUiSchema(uiSchema() (2)
        .withKey("multiSelectTag")
        .withRestricted(false)
        .withTitle("Simple multiSelectTag")
        .withDescription("This data list accepts values that are not in the list of suggestions")
        .withWidget("multiSelectTag")
        .build())
    .withProperties(myFormInstance) (3)
    .build();

final String json = jsonb.toJson(form1); (4)
1 The JsonSchema is extracted from reflection on the Form1 class. @JsonSchemaIgnore allows to ignore a field and @JsonSchemaProperty allows to rename a property.
2 A UiSchema is programmatically built using the builder API.
3 An instance of the form is passed to let the serializer extract its JSON model.
4 The Ui model, which can be used by UiSpec compatible front widgets, is serialized.

The model uses the JSON-B API to define the binding. Make sure to have an implementation in your classpath. To do that, add the following dependencies:

<dependency>
  <groupId>org.apache.geronimo.specs</groupId>
  <artifactId>geronimo-jsonb_1.0_spec</artifactId>
  <version>1.0</version>
</dependency>
<dependency>
  <groupId>org.apache.geronimo.specs</groupId>
  <artifactId>geronimo-json_1.1_spec</artifactId>
  <version>1.0</version>
</dependency>
<dependency>
  <groupId>org.apache.johnzon</groupId>
  <artifactId>johnzon-jsonb</artifactId>
  <version>${johnzon.version}</version> <!-- 1.1.5 for instance -->
</dependency>

Using the UiSpec for custom models

The following module enables you to define through annotations a uispec on your own models:

<dependency>
  <groupId>org.talend.sdk.component</groupId>
  <artifactId>component-uispec-mapper</artifactId>
  <version>${talend-component-kit.version}</version>
</dependency>
this can’t be used in components and is only intended for web applications.

org.talend.sdk.component.form.uispec.mapper.api.service.UiSpecMapper enables to create a Ui instance from a custom type annotated with org.talend.sdk.component.form.uispec.mapper.api.model.View and org.talend.sdk.component.form.uispec.mapper.api.model.View.Schema.

UiSpecMapper returns a Supplier and not directly an Ui because the ui-schema is re-evaluated when `get()̀ is called. This enables to update the title maps for example.

Here is an example:

@Data
public abstract class BaseModel {
    @View.Skip
    private String id;

    @View.Skip
    private Date created;

    @View.Skip
    private Date updated;

    @View.Schema(type = "hidden", readOnly = true)
    private long version;
}

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class ComponentModel extends BaseModel {
    @View.Schema(length = 1024, required = true, position = 1, reference = "vendors")
    private String vendor;

    @View.Schema(length = 2048, required = true, position = 2)
    private String name;

    @View.Schema(length = 2048, required = true, position = 3)
    private String license;

    @View.Schema(length = 2048, required = true, position = 4)
    private String sources;

    @View.Schema(length = 2048, required = true, position = 5)
    private String bugtracker;

    @View.Schema(length = 2048, required = true, position = 6)
    private String documentation;

    @View.Schema(widget = "textarea", length = 8192, required = true, position = 7)
    private String description;

    @View.Schema(widget = "textarea", length = 8192, position = 8)
    private String changelog;
}

This API maps directly the UiSpec model (json schema and ui schema of Talend UIForm).

The default implementation of the mapper is available at org.talend.sdk.component.form.uispec.mapper.impl.UiSpecMapperImpl.

Here is an example:

private UiSpecMapper mapper = new UiSpecMapperImpl(new Configuration(getTitleMapProviders()));

@GET
public Ui getNewComponentModelForm() {
    return mapper.createFormFor(ComponentModel.class).get();
}

@GET
@Path("{id}")
public Ui editComponentModelForm(final @PathParam("id") final String id) {
    final ComponentModel component = findComponent(id);
    final Ui spec = getNewComponentModelForm();
    spec.setProperties(component);
    return spec;
}

The getTitleMapProviders() method will generally lookup a set of TitleMapProvider instances in your IoC context. This API is used to fill the titleMap of the form when a reference identifier is set on the @Schema annotation.

JavaScript integration

component-kit.js is no more available (previous versions stay on NPM) and is replaced by @talend/react-containers. The previous import can be replaced by import kit from '@talend/react-containers/lib/ComponentForm/kit';.

Default JavaScript integration goes through the Talend UI Forms library and its Containers wrapper.

Documentation is now available on the previous link.

Logging

The logging uses Log4j2. You can specify a custom configuration by using the -Dlog4j.configurationFile system property or by adding a log4j2.xml file to the classpath.

Here are some common configurations:

  • Console logging:

<?xml version="1.0"?>
<Configuration status="INFO">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="[%d{HH:mm:ss.SSS}][%highlight{%-5level}][%15.15t][%30.30logger] %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Output messages look like:

[16:59:58.198][INFO ][           main][oyote.http11.Http11NioProtocol] Initializing ProtocolHandler ["http-nio-34763"]
  • JSON logging:

<?xml version="1.0"?>
<Configuration status="INFO">
  <Properties>
    <!-- DO NOT PUT logSource there, it is useless and slow -->
    <Property name="jsonLayout">{"severity":"%level","logMessage":"%encode{%message}{JSON}","logTimestamp":"%d{ISO8601}{UTC}","eventUUID":"%uuid{RANDOM}","@version":"1","logger.name":"%encode{%logger}{JSON}","host.name":"${hostName}","threadName":"%encode{%thread}{JSON}","stackTrace":"%encode{%xThrowable{full}}{JSON}"}%n</Property>
  </Properties>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="${jsonLayout}"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Output messages look like:

{"severity":"INFO","logMessage":"Initializing ProtocolHandler [\"http-nio-46421\"]","logTimestamp":"2017-11-20T16:04:01,763","eventUUID":"8b998e17-7045-461c-8acb-c43f21d995ff","@version":"1","logger.name":"org.apache.coyote.http11.Http11NioProtocol","host.name":"TLND-RMANNIBUCAU","threadName":"main","stackTrace":""}
  • Rolling file appender:

<?xml version="1.0"?>
<Configuration status="INFO">
  <Appenders>
    <RollingRandomAccessFile name="File" fileName="${LOG_PATH}/application.log" filePattern="${LOG_PATH}/application-%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="[%d{HH:mm:ss.SSS}][%highlight{%-5level}][%15.15t][%30.30logger] %msg%n"/>
      <Policies>
        <SizeBasedTriggeringPolicy size="100 MB" />
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
      </Policies>
    </RollingRandomAccessFile>
  </Appenders>
  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="File"/>
    </Root>
  </Loggers>
</Configuration>

More details are available in the RollingFileAppender documentation.

You can compose previous layout (message format) and appenders (where logs are written).

Docker

The server image is deployed on Docker. Its version is suffixed with a timestamp to ensure images are not overridden and can break your usage. You can check the available version on Docker hub.

Run

You can run the docker image by executing this command :

$ sudo docker run -p 8080:8080 tacokit/component-starter

Configure

You can set the env variable _JAVA_OPTIONS to customize the server, by default it is installed in /opt/talend/component-kit.

Maven repository

The maven repository is the default one of the machine, you can change it setting the system property talend.component.server.maven.repository=/path/to/your/m2.

Deploy components to the server

If you want to deploy some components you can configure which ones in _JAVA_OPTIONS (see server doc online) and redirect your local m2:

$ docker run \
       -p 8080:8080 \
       -v ~/.m2:/root/.m2 \
       -e _JAVA_OPTIONS="-Dtalend.component.server.component.coordinates=g:a:v,g2:a2:v2,..." \
       component-server

Logging

The component server docker image comes with two log4j2 profiles: TEXT (default) and JSON. The logging profile can be changed by setting the environment variable LOGGING_LAYOUT to JSON.

Note that Component Server adds to these default Talend profiles the KAFKA profile. With this profile, all logs are sent to Kafka.

You can check the exact configuration in the component-runtime/images/component-server-image/src/main/resources folder.

default or TEXT profile

The console logging is on at INFO level by default. You can customize it by setting the CONSOLE_LOG_LEVEL environment variable to DEBUG, INFO, WARN or to any other log level supported by log4j2.

Run docker image with console logging:

sudo docker run -p 8080:8080 \
	-e CONSOLE_LOG_LEVEL=DEBUG \
	component-server

JSON profile

The JSON profile logs on the console using the CONSOLE_LOG_LEVEL configuration as the default profile. Events are logged in the following format:

{
   "eventUUID":"%uuid{RANDOM}",
   "correlationId":"%X{traceId}",
   "spanId":"%X{spanId}",
   "traceId":"%X{traceId}",
   "category":"components",
   "eventType":"LOGEvent",
   "severity":"%level",
   "logMessage":"%encode{%message}{JSON}",
   "logSource":{
      "class.name":"%class",
      "file.name":"%file",
      "host.name":"%X{hostname}",
      "line.number":"%line",
      "logger.name":"%logger",
      "method.name":"%method",
      "process.id":"%pid"
   },
   "service":"${env:LOG_SERVICE_NAME:-component-server}",
   "application":"${env:LOG_APP_NAME:-component-server}",
   "exportable":"${env:LOG_EXPORTABLE:-true}",
   "audit":"${env:LOG_AUDIT:-false}",
   "logTimestamp":"%d{ISO8601}{UTC}",
   "serverTimestamp":"%d{ISO8601}{UTC}",
   "customInfo":{
      "threadName":"%encode{%thread}{JSON}",
      "stackTrace":"%encode{%xThrowable{full}}{JSON}"
   }
}

KAFKA profile

This profile is very close to the JSON profile and also adds the LOG_KAFKA_TOPIC and LOG_KAFKA_URL configuration. The difference is that it logs the default logs on Kafka in addition to the tracing logs.

Building the docker image

You can register component server images in Docker using these instructions in the corresponding image directory:

# ex: cd images/component-server-image
mvn clean compile jib:dockerBuild

Integrating components into the image

Docker Compose

Docker Compose allows you to deploy the server with components, by mounting the component volume into the server image.

docker-compose.yml example:

version: '3.2'

services:
  component-server:
    healthcheck:
      timeout: 3s
      interval: 3s
      retries: 3
      test: curl --fail http://localhost:1234/api/v1/environment
    image: tacokit/component-server:${COMPONENT_SERVER_IMAGE:-1.1.2_20181108161652}
    command: --http=1234
    environment:
    - CONSOLE_LOG_LEVEL=INFO
    - _JAVA_OPTIONS=
        -Xmx1024m
        -Dtalend.component.server.component.registry=/opt/talend/connectors/component-registry.properties
        -Dtalend.component.server.maven.repository=/opt/talend/connectors
    ports:
    - 1234:1234/tcp
    volumes:
    - type: bind
      read_only: true
      source: ${CONNECTORS_REPOSITORY}
      target: /opt/talend/connectors
      volume:
        nocopy: true

If you want to mount it from another image, you can use this compose configuration:

version: '3.2'

services:
  component-server:
    healthcheck:
      timeout: 3s
      interval: 3s
      retries: 3
      test: curl --fail http://localhost:1234/api/v1/environment
    image: tacokit/component-server:${COMPONENT_SERVER_IMAGE_VERSION}
    command: --http=1234
    environment:
    - _JAVA_OPTIONS=
        -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
        -Djava.library.path=/opt/talend/component-kit/work/sigar/sigar:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
        -Xmx1024m
        -Dtalend.component.server.component.registry=/opt/talend/connectors/component-registry.properties
        -Dtalend.component.server.maven.repository=/opt/talend/connectors
    ports:
    - 1234:1234/tcp
    - 5005:5005/tcp
    volumes:
    - connectors:/opt/talend/connectors:ro

  connectors:
    image: talend/connectors:${CONNECTORS_VERSION}
    environment:
    - CONNECTORS_SETUP_OPTS=setup --wait-for-end --component-jdbc-auto-download-drivers
    volumes:
    - connectors:/opt/talend/connectors:ro


volumes:
  connectors:

To run one of the previous compose examples, you can use docker-compose -f docker-compose.yml up.

Only use the configuration related to port 5005 (in ports and the -agentlib option in _JAVA_OPTIONS) to debug the server on port 5005. Don’t set it in production.

Adding extensions to the server

You can mount a volume in /opt/talend/component-kit/custom/ and the jars in that folder which will be deployed with the server. Since the server relies on CDI (Apache OpenWebBeans) you can use that technology to enrich it, including JAX-RS endpoints, interceptors etc…​or just libraries needing to be in the JVM.

Scroll to top