Open zajcu opened 5 years ago
Hi @zajcu,
thanks for the issue. In Knot.x 1.5.0 it was possible to specify the params
attribute that overrode the one from the [dataDefinitions[namespace].params]
configuration attribute, see the example. So it was easy to specify the new path
for the named HTTP data source (REST endpoint). Please note that in Knot.x 1.5.0 it was possible to define many data sources per fragment.
In Knot.x 2.0.0 we introduced a task concept where you can define only one task per fragment.
<knotx:snippet data-knotx-task="booklist"
</knotx:snippet>
Then in the configuration we have:
tasks {
booklist {
actions = [
{ action = books }
{ action = authors }
]
onTransitions {
_success {
action = template-engine-handlebars
}
}
}
}
Task can specify one and more actions to execute, in this example we have two actions: books
and authors
.
Our actions call REST endpoints and fill the payload. Every action gets Fragment, do some transformation and responds with the new Fragment.
In Fragment there is the configuration
attribute, it is a JSON object. For HTML markup, it contains all knotx:snippet
tag attributes. So it is not required to extend Fragments model with extra attribute.
When you check the Http Action documentation you will find that you can parametrize your action with:
You can check available placeholders here. Maybe it is worth to add the example for configuration attributes, like {config.books-query}
. This attribute can be specified with:
<knotx:snippet data-knotx-task="booklist" books-query="java"
</knotx:snippet>
So then in the action configuration, you will have:
book {
factory = http
config {
endpointOptions {
path = /service/mock/book.json?q={config.books-query}
domain = localhost
port = 3000
allowedRequestHeaders = ["Content-Type"]
}
}
}
Can you please verify if it works for you? Our intention was to simply tag attributes.
Thank you @zajcu for your input. As we discussed this solution works as expected. However, we discovered new requirements. Let me explain it with the example below:
ZG Bridge integrates with Knot.x to deliver dynamic data to templates coming from AEM. ZG Bridge defines collections and collections items that can be easily used during AEM authoring.
So, let's imagine that we have two independent collections: authors and books. Both authors and books are JSON objects coming from REST API. JSON is a contract, REST API is a data source. There are two REST endpoints for authors:
/authors?filter="first name"
/author/{id}
and books:
/books?filter="title"
/book/{id}
Then in ZG Bridge you can specify what items are used to fill a template from AEM. In this way, we can specify two books at a single page (first - the primary one, second - the recommended one).
So we have book-1
and book-2
. This data must be configured something in HTML, then Knot.x can use it and fill the template.
The example HTML markup can look like:
<knotx:snippet task="product-details-component">
{{book.1.title}}
<h1>Recommended products</h1>
{{book.2.title}}
</knotx:snippet>
In Knot.x there is the product-details-component
task defined. In the standard approach, we would define it as:
tasks {
product-details-component {
actions = [
{ action = book1 }
{ action = book2 }
]
onTransitions {
_success {
action = template-engine-handlebars
}
}
}
}
and specify two actions. But as you see this solution is not very flexible. So we need some configuration to make those task definitions more dynamic.
Let's change the task configuration to:
tasks {
product-details-component {
actions = @book
onTransitions {
_success {
action = template-engine-handlebars
}
}
}
}
Then we can configure @book
with some parameter in HTML
<knotx:snippet task="product-details-component" task-actions="@books-configuration">
{{book.1.title}}
<h1>Recommended products</h1>
{{book.2.title}}
</knotx:snippet>
, where the @books-configuration
structure is:
{
"book": [
{
"namespace": 1,
"config": {
"id": 1
}
},
{
"namespace": 2,
"config": {
"id": 2
}
}
]
}
With this solution we specify Action once:
actions {
book {
factory = http
config {
endpointOptions {
path = /book/{config.id}
...
}
}
}
}
Then we can specify the dynamic task provider implementation that would transform the task-actions
attribute to Task.
Thank you @tomaszmichalak this is exactly what we need to cover our requirements. By the way very nice explanation.
Hi, we had a design session, those are outputs:
tasks {
simple-task {
action = aAction
onTransitions {
_success {
action = te-hbs
}
}
}
}
default
task factory, the example simple-task
can be configured as:
tasks {
simple-task {
factory = default
metadata {
taskKey = "data-knotx-task"
}
config {
action = aAction,
onTransitions {
_success {
action = te-hbs
}
}
}
},
pre-configured
task factory handling dynamic task configuration:
tasks {
some-template-task {
factory = pre-configured
metadata {
taskKey = "data-knotx-task"
}
config {
actions = [ @customActions ]
onTransitions {
_success {
action = te-hbs
}
}
}
}
}
actions {
aAction { },
bAction { },
te-hbs {
factory = knot,
config {
address = knotx.knot.te.handlebars,
deliveryOptions {
sendTimeout = 1000
}
}
}
}
Is your feature request related to a problem? Please describe. In databridge 1.5.0 version there was a awesome feature: params https://github.com/Knotx/knotx-data-bridge/tree/1.5.0 What is missed in current 2.0 version
Describe the solution you'd like We need similar feature in 2.x version. For example to cover example code: `
{{item._result.book.name}}
{{item2._result.user.name}}
...`
I supposed the simple solution will be extend fragments model to have additional JsonObject property, and later in processing consume it for example in HttpAction like it was in old implementation in HttpClientFacade (1.5.0 version).
Potentialy this object can be reused in other places.
What do you think?
Additional context We have used it a lot in our current project, we need this to start migrate !X to the last version.