Installation Guide

Create a database

To use Alfred Inflow, you need to have a MySQL or PostgreSQL database. By default, you can create a database called “inflow” with a user “inflow”. Ensure that the Alfred Inflow user has all rights on the database.

On the first startup, Alfred Inflow will automatically create all the tables.

The following example creates a database and gives a user all rights to it.

create database inflow;
grant all on inflow.* to 'inflow'@'localhost' identified by 'inflow';
grant all on inflow.* to 'inflow'@'%' identified by 'inflow';

Install Alfred Inflow

Now you are ready to deploy the application itself. You can do this by moving inflow.war to the webapps folder of your Tomcat installation. In the default configuration of Tomcat any .war moved here will be deployed automatically.

Configuration

Add \${catalina.home}/shared/classes to the shared.loader property in catalina.properties (if it is not already present). After deploying Alfred Inflow you should configure it for your environment. The main configuration file is “inflow.properties”. You can find it in “inflow/WEB-INF/classes/inflow.properties”.
You can customise the configuration by creating a copy of inflow.properties in <class_path>{=html}/inflow/inflow-custom.properties and overriding the properties here.
Here is a list of all available configuration parameters:

Parameter Default Description
db.url jdbc:h2:build/h2/inflow_data The URL used to connect to the database server. This contains the hostname and the name of the database. Only MySQL and PostgreSQL are supported
db.user inflow The username used to connect to the database server.
db.pass inflow The password used to connect to the database server.
db.driver org.h2.Driver The driver that is used to connect to the database.
db.initialize true If true, the database will be created if the tables do not exist. Default is true.
hibernate.hbm2ddl.auto update Validates or exports the db schema. Use update on development, and validate on production.
hibernate.dialect org.hibernate.dialect.H2Dialect The language hibernate needs to generate. This value depends on your database. See http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html_single/#configuration-optional-dialects for possibilities.
mail.from move2alf@example.com The email address to send email reports from.
mail.smtp smtp.example.com The SMTP server for sending email reports.
url http://localhost:8080/inflow The URL where you can access Alfred Inflow. This is used to create links in the email reports.
type.server production If you want to use parser reloading, put to development. Else put it to production.
hotdeploy.paths no value Paths where the class files are located. This can be a comma separated list. Example: file:///C:/classpath/root/ (trailing slash is mandatory!)
base.package none The packages that can be scanned for parsers. This speeds up the startup of inflow. eu.xenit is always scanned by default. If the value remains empty, the full classpath will be scanned.
move.keepstructure true If set to true, the folder structure of the input folder is copied to alfresco. Default is true.
authentication.jwt.enabled false If true, Inflow allows authentication by a JWToken, as sent by e.g. Alfred Edge
authentication.jwt.secret A secret key, shared by the JWToken sender and receiver, for the signature with the HS256 algorithm (a default dummy value is specified )
authentication.jwt.keystore.path path to the keystore with keys for the JWT token signature with other signing algorithms
authentication.jwt.keystore.password password for the keystore
authentication.jwt.keystore.alias alias for the keystore
authentication.jwt.admin admin admin user used to create users with
authentication.jwt.new-password password for automatic created users
authentication.jwt.role.system-admin comma separated strings with roles that allow the inflow system admin role
authentication.jwt.role.job-admin comma separated strings with roles that allow the inflow job admin role
authentication.jwt.role.schedule-admin comma separated strings with roles that allow the inflow schedule admin role
authentication.jwt.role.consumer comma separated strings with roles that allow the inflow consumer role

JWT Authentication and Authorization

It is possible to enable the JWT authentication and authorization module in Inflow.

When enabled a valid secret and/or the complete specification for a keystore must be given.

With the JWT enabled, Inflow will accept requests containing a JWT Token, as e.g. sent by Alfred Edge. The subject of the token is used as user. If this user does not exist in the Inflow database, it is added with minimal rights (i.e. ROLE_CONSUMER).

If the JWT Token contains a claim with roles, these roles are converted to Inflow roles, based on the properties authentication.jwt.role.*. These inflow roles are not written in the database, but at runtime merged with the roles from the database. This means that the JWT token can add rights to an existing user from the database, but never forbid him granted rights.

Install Alfred Inflow AMP

You need to install the Alfred Inflow backend amp in alfresco in order for Alfred Inflow to operate. This AMP uses dynamic-extensions, so you will need to install that as well.

For information on how to install the AMP please consult the Alfresco documentation

Configuring load balancer

Inflow requires sticky sessions to work properly. The reason for this is that the backend is stateful during a cycle run of a job. If your destination alfresco is placed behind a load balancer, you will need to configure the loadbalancer so all requests from a cycle are sent to the same backend.

Inflow stores and sends cookies that it has received on a per-cycle basis. The loadbalancer can make use one of the following strategies to send all requests from the same cycle to the same backend:

  • Loadbalancing based on the received INFLOW_CYCLE_ID cookie. The INFLOW_CYCLE_ID cookie will be sent out by the Inflow server on all outgoing requests to the Alfresco server. The response from the Alfresco server will not contain the cookie (Note: There is no usage of the set-cookie response header).
  • Loadbalancing based on a cookie set by the loadbalancer. The Inflow backend does not send any set-cookie response headers, so the loadbalancer should insert a cookie by itself and should not be configured to rewrite an existing cookie. Inflow stores cookies separately for each cycle, so every cycle may be loadbalanced to a different Alfresco server.

There is also a cookie INFLOW_INSTANCE_ID available. The value of this cookie is a random generated value. This value is generated when the inflow server is started.

Example config

# HAProxy 2.3
backend alfresco
    cookie REPO_STICKY insert nocache
    server alfresco1 alfresco-core1:8080
    server alfresco2 alfresco-core2:8080

Posting job and destination configuration

Once Inflow is up and running, you probably want to define a set of jobs and destinations. This can be clicked together by the user. However, if the job and/or destination configuration is known beforehand, it can be posted to the Inflow server.
An example on how to post a destination json configuration:

curl -u username:password --data-binary @./destination.json -v http://inflow:8080/inflow/api/service/v1/destinations/ -XPOST -H 'Content-Type: application/json'

An example destination.json file:

{
  "name": "testDestination",
  "url": "http://target-alfresco:8080/alfresco/s",
  "username": "admin",
  "password": "admin",
  "storeContentThreads": 2,
  "createPackagesThreads": 4,
  "packagesPerTransaction": 250,
  "maximumBufferedReports": 2000
}

An example on how to post a job config yaml configuration:

curl -u username:password --data-binary @./job-config.yaml -v http://inflow:8080/inflow/api/service/v1/jobs/ -XPOST -H 'Content-Type: application/x-yaml'

An example job-config.yaml file:

---
name: "Example Parser"
description: "A good description"
configuration:
  inputPaths:
    - "/input-path-in-file-system"
  extension: "*.xml"
  destinationPath: "/destination-path-in-alfresco"
  processor: "name-of-parser-implementation"
  metadata:
    property: "value"
  commandBefore: ""
  commandAfter: ""
  schedules:
  overwrite: false
  replaceMetadata: false
  onlyUpdateFolders: false
  allowResidualProperties: false
  disablePackaging: false
  autoMove:
    moveBeforeProcessing: false
    moveAfterSuccessfulProcessing: true
    moveAfterSuccessfulProcessingPath: "/Loaded"
    moveAfterFailedProcessing: true
    moveAfterFailedProcessingPath: "/Error"
    moveUnprocessed: false