Versions Compared
Key
- This line was added.
- This line was removed.
- Formatting was changed.
Warning |
---|
When using external flow please make sure that the host and the target runtimes have the same major and minor versions. |
Introduction
The external flow is a concept that allows embedding and starting a flow from a different project, without the use of Portal Messages.
The value of this functionality is to get:
- a good design of the solution:
- Structure your application
- Make your solution scalable
- a good application UX:
- The end user directly see which information is loaded and what not
- a good application model:
- Modelling is more explicit which brings clarity in the model
Conceptually it works as depicted in the following figure.
Image Removed
This container will replace the AQ_Dashboard_FlowWidget and AQ_Dashboard_ProjectWidget.
Definitions
Requirements
In order to use this functionality you need to enable Blueriq External Flow Component.
Limitations
- Running the external flow using host and target runtimes with different major and minor versions is not supported.
Configuration
To configure the External Flow Container to work on the runtime you have to do the following:
- Enable
external-flow
profile inbootstrap.properties
. - Replace the material version (>=1.0.9)
Info |
---|
External flow functionality saves the profile in a Redis Datastore. Please consult Blueriq External Flow Component in order to see more details on how to configure the runtime to support the external flow. |
Using other datastore implementation
Blueriq provides IExternalFlowStore interface which can be used to interact with a generic datastore. A default implementation is already provided in the Blueriq External Flow Component. If other datastore implementation is desired the following have to be done:
- Add the
blueriq-component-api
to the project dependencies.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<project ...>
...
<dependencies>
...
<dependency>
<groupId>com.blueriq</groupId>
<artifactId>blueriq-component-api</artifactId>
<version>${blueriq.version}</version>
</dependency>
...
</dependencies>
...
</project> |
- Define the custom implementation like below:
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package ...;
import com.blueriq.component.api.store.externalflow.IExternalFlowStore;
// other imports ...
@Component
public class CustomExternalFlowStore implements IExternalFlowStore {
@Override
public void delete(String key)
throws ExternalFlowStoreException, IllegalArgumentException {
// add implementation here
}
@Override
public <T extends Serializable> T get(String key, Class<T> valueType)
throws ExternalFlowStoreException, IllegalArgumentException {
// add implementation here
return null;
}
@Override
public boolean hasKey(String key)
throws ExternalFlowStoreException, IllegalArgumentException {
// add implementation here
return false;
}
@Override
public void set(String key, Serializable value)
throws ExternalFlowStoreException, IllegalArgumentException {
// add implementation here
}
}
|
Hazelcast Datastore
Here is a Hazelcast implementation of the datastore.
Adding the dependencies
The following dependencies are required in the pom.xml
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<project ...>
...
<dependencies>
...
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-all</artifactId>
<version>${hazelcast.version}</version>
</dependency>
<dependency>
<groupId>com.blueriq</groupId>
<artifactId>blueriq-component-api</artifactId>
<version>${blueriq.version}</version>
</dependency>
...
<dependencies>
...
</project> |
Implementing the IExternalFlowStore Interface
Warning | ||
---|---|---|
| ||
Please make sure that HazelcastExternalFlowStore component is scanned by Spring. |
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package ...;
import com.blueriq.component.api.store.externalflow.IExternalFlowStore;
// other imports ...
@Component
public class HazelcastExternalFlowStore implements IExternalFlowStore {
private final IMap<String, Serializable> map;
public HazelcastExternalFlowStore() {
ClientConfig config = new ClientConfig();
// configure Hazelcast properties here
HazelcastInstance hazelcastInstance
= HazelcastClient.newHazelcastClient(config);
map = hazelcastInstance.getMap("blueriq");
}
@Override
public void delete(String key)
throws ExternalFlowStoreException, IllegalArgumentException {
if (isInvalid(key)) {
throw new IllegalArgumentException("Invalid key.");
}
try {
map.delete(key);
} catch (Exception e) {
throw new ExternalFlowStoreException("Something went wrong", e);
}
}
@Override
public <T extends Serializable> T get(String key, Class<T> valueType)
throws ExternalFlowStoreException, IllegalArgumentException {
if (isInvalid(key)) {
throw new IllegalArgumentException("Invalid key.");
}
try {
Serializable storedValue = map.get(key);
if (storedValue == null) {
return null;
}
if (valueType.isInstance(storedValue)) {
return valueType.cast(storedValue);
}
throw new IllegalArgumentException(
String.format("Cannot cast from %s to %s.",
storedValue.getClass(), valueType));
} catch (Exception e) {
throw new ExternalFlowStoreException("Something went wrong", e);
}
}
@Override
public boolean hasKey(String key)
throws ExternalFlowStoreException, IllegalArgumentException {
if (isInvalid(key)) {
throw new IllegalArgumentException("Invalid key.");
}
try {
return map.get(key) != null;
} catch (Exception e) {
throw new ExternalFlowStoreException("Something went wrong", e);
}
}
@Override
public void set(String key, Serializable value)
throws ExternalFlowStoreException, IllegalArgumentException {
if (isInvalid(key)) {
throw new IllegalArgumentException("Invalid key.");
}
try {
map.set(key, value, 1, TimeUnit.MINUTES);
} catch (Exception e) {
throw new ExternalFlowStoreException("Something went wrong", e);
}
}
private boolean isInvalid(String key) {
// define what an invalid key means
return false;
}
}
|
Modeling an External Flow
Todo
External Flow Endpoints
Init external flow
Code Block | ||
---|---|---|
| ||
POST /api/v2/session/{sessionId}/externalflow/init {"configurationId": "{configurationId}}" |
Description
Initialises Initialize the external container component on the HOST runtime.
Parameters
URL Segment | Expected Type | Description |
---|---|---|
sessionId | AquimaSession | Session (HOST) session for which the external container was expanded. |
Request body
must be a JSON containing the configuration ID property name configurationId
with a value of type string.
Example
Responseresponse
If successful, status 200 OK and response body:
Code Block |
---|
{ "configurationId" : "123-456-789" "baseUrl" : <optional absolute or relative URL to TARGET Runtime> } |
Start external flow
Code Block | ||
---|---|---|
| ||
POST /api/v2/externalflow/start {"configurationId": "{configurationId}}" |
Description
Starts Start the external flow container on the TARGET runtime.
Parameters
None
Request body
A JSON containing the configuration ID property name configurationId
with a value of type string.
Example
Responseresponse
If successful, status 200 OK and response body:
Code Block |
---|
{ "sessionId" : "123-456-789" <id of the TARGET session> } |
Complete external flow
Code Block | ||
---|---|---|
| ||
POST /api/v2/session/{sessionId}/externalflow/{configurationId}/complete |
Description
Completes Complete the external flow and executes execute the mapping between the interface and source profile. This endpoint should be called on the HOST runtime.
Parameters
URL Segment | Expected Type | Description |
---|---|---|
sessionId | AquimaSession | The Id of the AquimaSession from the host HOST runtime. |
configurationId | string | Unique Automatically generated unique id for the external flow container configuration. |
Request body
Code Block |
---|
{
"parameters": {
<param1_name>: ["value1","value2"]
},
"elementKey": <elementKey>,
"fields": [
{
"key": <key>,
"values": ["value1", "value2"]
}
]
} |
Example response
If successful, status 200 OK and response body:
Code Block |
---|
{ "events": [ { "sessionId": <sessionId><id of the HOST session>, "changes": {"changes": []}, "type": "page" }, ... ] } |
End external flow
Code Block | ||
---|---|---|
| ||
POST /api/v2/session/{sessionId}/externalflow/{configurationId}/end |
Description
Closes Close the external session. This endpoint should be called on the TARGET runtime.
Parameters
URL Segment | Expected Type | Description |
---|---|---|
sessionId | AquimaSession | The Id of the AquimaSession from the target TARGET runtime. |
configurationId | string | Unique Automatically generated unique id for the external flow container configuration. |
Request body
None
Response
If successful, status code 200 OK
Known Issues
Todo ???
The
Table of Contents |
---|