The UiSpec server is a companion application for the Component Server.
It provides a client to the Component Server which serves UiSpec payload to integrate with the client JavaScript UiForm
library.
Coordinates
<dependency>
<groupId>org.talend.sdk.component</groupId>
<artifactId>component-server-proxy</artifactId>
<version>${server-proxy.version}</version>
</dependency>
Configuring the UiSpec server
the configuration is read from system properties, environment variables, ….
If you use playx-microprofile-config , you can also use typesafe configuration.
|
Key | Description | Default |
---|---|---|
talend.component.proxy.actions.proposable.cached |
If true the proposable (suggestion lists only depending on the server state) will be cached, otherwise they will be requested for each form rendering. |
true |
talend.component.proxy.application.home |
A home location for relative path resolution (optional). |
${playx.application.home} |
talend.component.proxy.client.providers |
List of JAX-RS providers to register on the client, at least a JSON-B one should be here. |
- |
talend.component.proxy.client.timeouts.connect |
The connect timeout for the communication with the server.base in ms. |
60000 |
talend.component.proxy.client.timeouts.read |
The read timeout for the communication with the server.base in ms. |
600000 |
talend.component.proxy.jcache.active |
Should the server use jcache to store catalog information and refresh it with some polling. If so the keys |
true |
talend.component.proxy.jcache.provider |
Caching provider implementation to use (only set it if ambiguous). |
- |
talend.component.proxy.jcache.refresh.period |
Number of seconds used to check if the server must be refreshed. |
60 |
talend.component.proxy.processing.headers |
The headers to append to the request when contacting the server. Format is a properties one. You can put a hardcoded value or a placeholder ( |
- |
talend.component.proxy.processing.uiSpec.patch |
An optional location (absolute or resolved from The values can be keys in the resource bundle |
component-uispec-metadata.%s.json?force=false |
talend.component.proxy.server.base |
The base to contact the remote server (NOTE: it is recommanded to put a load balancer if you have multiple instances.) |
- |
Adding custom entries to the forms
As shown in the table above, you can customize the forms by type. The format reuses Talend Component Kit REST API (properties model) and defines two main types of extensions:
-
prependProperties
: Lists all the models of properties added to the form before the actual underlying form. -
appendProperties
: Lists all the models of properties added to the form after the actual underlying form.
If you don’t specify a name, the path is used to deduce the name automatically.
Always make sure to define a root object for these properties. Do not use dots in the path value. It is recommended to prefix it with a $ character.
|
Adding custom converters (selecting the widget or rendering)
When developing a org.talend.sdk.component.form.internal.converter.CustomPropertyConverter
CDI, the proxy adds it to the UiSpecService
service and uses it with a high priority to convert the server model to a UiSpec
model.
To make it a CDI bean, add @Dependent to the class and if you use the Play integration, customize the bean array: playx.cdi.beans.customs += {className: org.talend.myapp.MyConverter}.
|
This allows to use a custom @Ui
API and advanced modeling when specific to applications.
Converters are sorted respecting to the @Priority
value. If the annotation is missing, the priority defaults to 0
.
Client in Play
The client to use to connect to the Talend Component Kit server is the CXF client, using HttpClient HC (NIO) transport. When you use the Play module, it can be configured with its standard properties prefixed by talend.component.proxy.
.
You can find more information on CXF website.
Defining a dropdown with all root configurations
The special dynamic_values
action builtin::roots
can be used for a dropdown filled with all available root types.
Here is a sample patch file:
{
"prependProperties": [
{
"path": "$datasetMetadata",
"type": "OBJECT"
},
{
"path": "$datasetMetadata.type",
"displayName": "Types",
"type": "ENUM",
"metadata": {
"action::dynamic_values": "builtin::roots"
}
}
]
}
Reloading the form based on the selected root
The builtin::root::reloadFromId
action, with the jsonpatch
type,
allows to reload the whole form:
{
"path": "$datasetMetadata.type",
"displayName": "Types",
"type": "STRING",
"metadata": {
"action::dynamic_values": "builtin::roots", (1)
"action::reloadForm": "builtin::root::reloadFromId", (2)
"action::reloadForm::parameters": "."
}
}
1 | Prepopulating the dropdown with the list of datastores. |
2 | On selection of a datastore, refreshing the form with the new parameters. |
It is common to have a dropdown with the list of roots and to reload the form when one is selected.
For example, the UIForm
part (JavaScript side) can be implemented as follows:
import kit from 'component-kit.js';
// ...
constructor(props) {
super(props);
this.state = {};
this.trigger = kit.createTriggers({
url: '/componentproxy/api/v1/actions/execute',
customRegistry: {
reloadForm: ({ body }) => { (1)
const { _datasetMetadata } = this.state.uiSpec.properties;
return {
...body, (2)
properties: { _datasetMetadata }, (3)
};
}
}
});
// ...
}
// ...
onTrigger(event, payload) {
return this.trigger(event, payload)
.then(result => {
if (result.properties || result.errors || result.uiSchema || result.jsonSchema) { (4)
this.setState({
uiSpec: {
...this.state.uiSpec,
...result,
}
});
}
});
}
1 | Adding a custom handler for the specific reloadForm action. |
2 | Passing the uiSchema and jsonSchema to the next step in the response processing chain. |
3 | Resetting the dynamic part of the form. Only the static part is kept. |
4 | Merging back the result of the handler into the current state. You can use redux or cmf . |
HTTP API
Component UiSpec Server
Overview
These endpoints allow to obtain UiSpec representations of the component/configuration types properties.
Contact information
Contact : Talend
Contact Email : contact@talend.com
License information
License : Apache 2.0
License URL : www.apache.org/licenses/LICENSE-2.0.html
Terms of service : null
Paths
This endpoint execute an action required by a form.
POST /actions/execute
Parameters
Type | Name | Schema |
---|---|---|
Query |
action |
string |
Query |
family |
string |
Query |
language |
string |
Query |
type |
string |
Responses
HTTP Code | Description | Schema |
---|---|---|
200 |
successful operation |
< string, CompletionStageMapStringObject > map |
400 |
This response is returned when the action is null |
|
404 |
This response is returned when no action is found |
|
520 |
This response is returned when the action raise an unhandled error |
Return all the available root configuration (Data store like) from the component server
GET /configurations
Description
Every configuration has an icon. In the response an icon key is returned. this icon key can be one of the bundled icons or a custom one. The consumer of this endpoint will need to check if the icon key is in the icons bundle otherwise the icon need to be gathered using the familyId
from this endpoint configurations/{id}/icon
Return a form description ( Ui Spec ) without a specific configuration
GET /configurations/form/initial/{type}
Return a form description ( Ui Spec ) of a specific configuration
GET /configurations/form/{id}
Return the configuration icon file in png format
GET /configurations/icon/{id}
Update a configuration.
POST /configurations/persistence/edit/{id}
Saves a configuration based on a type. Concretely it is the same as /persistence/save/{formId}
but the formId
is contained into the payload itself and marked in the metadata as such.
POST /configurations/persistence/save-from-type/{type}
Saves a configuration based on a form identifier.
POST /configurations/persistence/save/{formId}
Definitions
EntityRef
Name | Description | Schema |
---|---|---|
id |
The identifier of the entity related to current request. It is generally thecreated entity of updated one. |
string |
JsonSchema
Name | Schema |
---|---|
defaultValue |
object |
description |
string |
enumValues |
< string > array |
id |
string |
items |
|
maxItems |
integer (int32) |
maxLength |
integer (int32) |
maximum |
number (double) |
minItems |
integer (int32) |
minLength |
integer (int32) |
minimum |
number (double) |
pattern |
string |
properties |
< string, JsonSchema > map |
ref |
string |
required |
< string > array |
schema |
string |
title |
string |
type |
string |
uniqueItems |
boolean |
Node
Name | Description | Schema |
---|---|---|
children |
The list of configuration reusing this one as a reference (can be created "next"). |
< string > array |
familyId |
The identifier of the family of this configuration. |
string |
familyLabel |
The display name of the family of this configuration. |
string |
icon |
The icon of this configuration. If you use an existing bundle (@talend/ui/icon), ensure it is present by default and if not do a request using the family on the related endpoint. |
string |
id |
The identifier of this configuration/node. |
string |
label |
The display name of this configuration. |
string |
name |
The technical name of this node (it is human readable but not i18n friendly), useful for debug purposes. |
string |
version |
The version of this configuration for the migration management. |
integer (int32) |
Nodes
Name | Description | Schema |
---|---|---|
nodes |
The list of nodes matching the request. The key is the node identifier. |
< string, Node > map |
ProxyErrorPayload
Name | Description | Schema |
---|---|---|
code |
The error code independently of the locale and not as precise as a message (not context aware). |
string |
message |
A human readable message to help understanding the error |
string |
Trigger
Name | Schema |
---|---|
action |
string |
family |
string |
onEvent |
string |
options |
< Option > array |
parameters |
< Parameter > array |
type |
string |
Ui
Name | Schema |
---|---|
jsonSchema |
|
properties |
object |
uiSchema |
< UiSchema > array |
UiNode
Name | Description | Schema |
---|---|---|
metadata |
The metadata associated to the node if needed by the UI. |
|
ui |
The ui specification corresponding to the requested node. It is literally the form representing this configuration. |
UiSchema
Name | Schema |
---|---|
autoFocus |
boolean |
conditions |
< Condition > array |
description |
string |
disabled |
boolean |
itemWidget |
string |
items |
< UiSchema > array |
key |
string |
options |
< string, string > map |
placeholder |
string |
readOnly |
boolean |
required |
boolean |
restricted |
boolean |
title |
string |
titleMap |
< NameValue > array |
triggers |
< Trigger > array |
type |
string |
widget |
string |
There are two ways to call the save
endpoint. If you don’t want to pass the form identifier and prefer to use a generic endpoint that simply passes the type of configuration you are configuring, then you need to modify your enrichment
configuration to ensure that the form identifier is present and to specify which form field it is.
To do that, add the proxyserver::formId
Boolean to the metadata:
{
"path": "$datasetMetadata.type",
"displayName": "Types",
"type": "STRING",
"metadata": {
// other metadata as seen previously
"proxyserver::formId": "true"
}
}
Only the first property with proxyserver::formId set to "true" is used. The path cannot contain any array.
|
Integrating with Play
Thanks to Playx, you can deploy this server in a Play! application.
-
Import the pre-configuration of the Play integration.
<dependency>
<groupId>org.talend.sdk.component</groupId>
<artifactId>component-server-proxy-play</artifactId>
<version>${server-proxy.version}</version>
</dependency>
-
Configure the integration in your
application.conf
file:
include "conf/component-proxy.play.conf" (1)
talend.component.proxy { (2)
server {
base = "http://localhost:8080/api/v1"
}
processing {
headers = """
X-ServiceName = proxy
X-ID = ${someRequestAttributeNameForTheId}
"""
// ...
}
}
1 | Importing the global configuration that maps the endpoints on /componentproxy/* . |
2 | Customizing the configuration to specialize it for the current deployment. |
If you are using Guice
The org.talend.sdk.component.guice.ComponentUiSpecServerModule
Guice module allows to import Services
from the server and to use some of them locally for the parts that are out of the scope of the endpoint delivery. For example:
-
Converting
JsonObject
toMap<String, String>
and the other way around. -
Getting the properties model for a configuration or component.
Use a Provider<T> injection to keep it lazy.
|
The server does not handle two layers. It is possible that you need to add:
-
Security.
-
Persistence.
For the security layer, it is recommended to create a Play filter that you configure before the proxy (ServletFilter
).
Make sure that you pass all contextual data in the request attributes to be able to get them back after.
For the persistence layer, the framework fires particular events (OnPersist
, OnEdit
and OnFindById
) that you should observe in order to implement the persistence as you wish.
Reusing the CDI context of the server just a plain CDI observer works, but if you used the Guice/CDI setup (using the Play module of the integration) you need to write Guice observers.
OnPersist needs to become identifier-aware of the created entity. Make sure to call composeId . In a similar way, OnFindById requires you to pass the found instance with composeProperties() and composeFormId() .
|
Optionally, you can implement OnFindByFormId
, which allows to have completion for references. If your application does not allow to edit references, you can bypass this event. If you implement it, make sure to call composeResult
no more than once.
@Singleton
public class PersistenceHandler {
@Subscribe
public void onPersist(final OnPersist event) {
// do persist, ensure to call event.composeId(...)
}
@Subscribe
public void onEdit(final OnEdit event) {
// do update
}
@Subscribe
public void onFind(final OnFindById event) {
// do find
}
@Subscribe
public void onFindByFormId(final OnFindByFormId event) {
// do find
}
}
Deletion is not handled by the server because there is no encapsulation of any format at that moment. |
Configuring the server module
The server module contains several configurations that you can set in:
-
Environment variables.
-
System properties.
-
A file located based on the
--component-configuration
CLI option.
the configuration is read from system properties, environment variables, …. |
Key | Description | Default |
---|---|---|
talend.component.server.component.coordinates |
A comma separated list of gav to locate the components |
- |
talend.component.server.component.extend.dependencies |
Should the component extensions add required dependencies. |
true |
talend.component.server.component.registry |
A property file where the value is a gav of a component to register (complementary with |
- |
talend.component.server.documentation.active |
Should the /documentation endpoint be activated. |
true |
talend.component.server.execution.dataset.retriever.timeout |
How long the read execution endpoint can last (max) |
180 |
talend.component.server.execution.pool.size |
The size of the execution pool for runtime endpoints. |
64 |
talend.component.server.execution.pool.wait |
How long the application waits during shutdown for the execution tasks to complete |
PT10S |
talend.component.server.jaxrs.exceptionhandler.defaultMessage |
If set it will replace any message for exceptions. Set to |
false |
talend.component.server.maven.repository |
The local maven repository used to locate components and their dependencies |
- |
talend.component.server.monitoring.brave.reporter.async |
When using url or kafka reporter, you can configure the async reporter with properties passed to this configuration entry.Ex: |
console |
talend.component.server.monitoring.brave.reporter.type |
The brave reporter to use to send the spans. Supported values are [log, noop]. When configuration is needed,you can use this syntax to configure the repoter if needed: In |
noop |
talend.component.server.monitoring.brave.sampling.action.rate |
The accuracy rate of the sampling for action endpoints. |
-1 |
talend.component.server.monitoring.brave.sampling.component.rate |
The accuracy rate of the sampling for component endpoints. |
-1 |
talend.component.server.monitoring.brave.sampling.configurationtype.rate |
The accuracy rate of the sampling for environment endpoints. |
-1 |
talend.component.server.monitoring.brave.sampling.documentation.rate |
The accuracy rate of the sampling for documentation endpoint. |
-1 |
talend.component.server.monitoring.brave.sampling.environment.rate |
The accuracy rate of the sampling for environment endpoints. |
-1 |
talend.component.server.monitoring.brave.sampling.execution.rate |
The accuracy rate of the sampling for execution endpoints. |
1 |
talend.component.server.monitoring.brave.sampling.rate |
The accuracy rate of the sampling. |
-1. |
talend.component.server.monitoring.brave.service.name |
The name used by the brave integration (zipkin) |
component-server |
talend.component.server.security.command.handler |
How to validate a command/request. Accepted values: securityNoopHandler. |
securityNoopHandler |
talend.component.server.security.connection.handler |
How to validate a connection. Accepted values: securityNoopHandler. |
securityNoopHandler |