You are viewing the documentation for Blueriq 17. Documentation for other versions is available in our documentation directory.

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

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.

This container will replace the AQ_Dashboard_FlowWidget and AQ_Dashboard_ProjectWidget.

Definitions

Host RuntimeThe runtime which contains a project that has an AQ_ExternalFlow_ container implementation running.  
Target RuntimeThe runtime which contains a project with a flow that can be started by an AQ_ExternalFlow_ container implementation. 
Source ProfileThe domain model of the source. 
Target ProfileThe domain model of the target.
Interface ProfileThe domain model of the interface
Datastore                                           The location where the serialized profile is stored.

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:

  1. Enable external-flow profile in bootstrap.properties.
  2. Replace the material version (>=1.0.9)

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.
pom.xml
<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:
CustomExternalFlowStore.java
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

pom.xml
<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

Please make sure that HazelcastExternalFlowStore component is scanned by Spring.

HazelcastExternalFlowStore.java
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 

POST /api/v2/session/{sessionId}/externalflow/init

{"configurationId": "{configurationId}}"

Description

Initialises the external container component on the HOST runtime.

Parameters

URL SegmentExpected TypeDescription
sessionIdAquimaSessionSession for which the external container was expanded.

The body must be a JSON containing the configuration ID of type string

Example Response

If successful, status 200 OK and : 

{
	"configurationId" : "123-456-789"
}

Start external flow 

POST /api/v2/externalflow/start

{"configurationId": "{configurationId}}"

Description

Starts the external flow container on the TARGET runtime.

Parameters

A JSON containing the configuration ID of type string.

Example Response

If successful, status 200 OK and : 

{
	"sessionId" : "123-456-789"
}

Complete external flow 

POST /api/v2/session/{sessionId}/externalflow/{configurationId}/complete

Description

Completes the external flow and executes the mapping between the interface and source profile.

Parameters

URL SegmentExpected TypeDescription
sessionIdAquimaSessionThe Id of the AquimaSession from the host runtime.  
configurationIdstringUnique id for the external container configuration.

Example Response

If successful, status 200 OK and : 

{
   "events": [
      {
       	"sessionId": <sessionId>,
     	"changes": {"changes": []},
      	"type": "page"
      }, 
	  ...
	]
}

End external flow 

POST /api/v2/session/{sessionId}/externalflow/{configurationId}/end

Description

Closes the external session

Parameters

URL SegmentExpected TypeDescription
sessionIdAquimaSessionThe Id of the AquimaSession from the target runtime.  
configurationIdstringUnique id for the external container configuration.

Response

If successful, status code 200 OK

Known Issues

Todo ???

The

  • No labels