View source | View content page | Page history | Printable version   

Projects:EHub/Technical Specification



This document gives a technical specification and design of the Openbravo eHUB solution.

The eHUB solution will offer two distinct functionalities:


Channel Concept

The channel concept in Openbravo corresponds to a sales channel by which products are being sold to retail customers. A channel can be an e-commerce site or franchise partners, but also an Openbravo WebPOS in an owned store or a kiosk.

The retail channel is an important concept and is therefore implemented explicitly in Openbravo using a separate table.

A POS Terminal will be linked to a channel. A channel can have multiple POS terminals, a POS Terminal belongs/works for one channel.

From a functional perspective a channel defines a specific sales area, from a technical perspective a channel defines implementation logic for transaction processing and query apis. This document focuses on the technical definition of a channel.

A channel implementation can also be used to cover the same functionality as currently is provided by connectors such as Magento. So the goal of the eHUB/channel development is to also cover and provide a generic framework (and for some cases an implementation) for connecting to E-Commerce and other third party systems.

Channel Columns/Fields

A channel has properties and sub-entities.

A channel will have the following properties:

Channel Sub Entities

For each channel it will be possible to override/set implementations and logic for specific services/hooks. These are defined in sub entities. The underlying technical concepts are discussed in more detail further down in this document.

As a technical detail, the service/hook/push definitions also support a json object as parameters. When saving a service/hook/push definition Openbravo should validate that the parameters are indeed valid json to prevent simple typos.

Channel Service

The channel api/functionality is implemented using a pre-defined set of services. A channel can override the service implementations. If a channel service is not defined explicitly then the default implementation will be used.

A channel service has the following columns:

Channel Hooks

A channel hook is a sub entity of a channel, for each channel one or more hooks can be defined with their implementing class. The supported/envisioned hooks are defined further down. The channel hook table will have the following columns:

Channel Push Definition

A channel can pull information by calling a service directly. This is a common approach. A channel can also request to get information pushed.

A push definition has the following fields/columns:

Channel Access

Channel access (who can call the underlying apis for the channel) is defined by user or role. The proposal is to have one channel access entity allowing either role or user access definition.

The channel access entity has the following properties:

Either role or user must be set in this case.

Channel Technical Aspects

Channel Requests - eHUB solution layering

All actions/updates in the eHUB are implemented as request-response actions. The following is assumed:

The solution should have 2 layers:

  1. the web layer actually receiving the http requests and returning the response. This layer also takes care of authentication.
  2. the execution layer, the api of this layer is more abstract and should be callable also directly without creating a http request/response. All the services provided by the eHUB should implement/extend the same default class.
public class ChannelService {
  public JSONObject execute(JSONObject json);

Following a two-layered approach makes it much easier to directly call eHUB functionality from backend code and to implement test cases.

The channel framework takes care that after the execute call the database transaction is automatically committed and several standard thread based resources of Openbravo are cleaned up. Similar to the current RequestFilter logic.

Channel Hooks

A channel hook allows specific code to be executed for each channel. So the exact implementation is defined in the channel. The proposal is to integrate the current server side hooks with new channel hooks. This means that the current server side hook concept need to be extended to support different implementations depending on the channel.

The main purpose of hooks is to be able to override/change the default logic from within the main loops/logic. This allows overriding/customizing without re-implementing a service completely. Some generic hooks make sense as they can be used to implement generic behavior with

The api of the hooks will be defined in more detail later. When defining the api the following approach should be followed:

A distinction can be made between technical and functionally oriented hooks. Both are described here.

Request Hooks

Request hooks are generic hooks which are executed for each request/response. The following request hooks can be identified:

Generic hooks should receive the service instance for which they are executed.

An example hook api:

public class RequestHook {
  public JSONObject onRequest(ChannelService service, JSONObject requestJson);
  public JSONObject onResponse(ChannelService service, JSONObject requestJson);

Functional Transactional Hooks

Functional transactional hooks are executed before-during and after transaction processing.

The following entities are covered by the functional transaction hooks:

Two other transaction entities (cashup and cash management) are not covered initially because they are less relevant for eHUB type of integrations.

The current server-side hooks will be recorded/integrated into the channel eHUB integration framework.

public class TransactionHook <T extends BaseOBObject> {
  public JSONObject beforeSave(JSONObject requestJson);
  public void onSave(T businessObject, JSONObject requestJson);
  public void afterSave(T businessObject, JSONObject requestJson);
  public void afterComplete(T businessObject, JSONObject requestJson);
public class OrderHook {
  public void beforeCreateShipment(Order order, JSONOrder json);
  public void afterCreateShipment(Order order, ShipmentInOut shipment);
  public void beforeCreatePayment(Order order, JSONObject json);
  public void afterCreatePayment(Order order, FIN_PaymentSchedule paymentSchedule);
  public void beforeCreateInvoice(Order order, JSONObject json);
  public void afterCreateInvoice(Order order, Invoice invoice);

Query Hooks

Query hooks are executed before and after reading data from the backend system. They are directly tied to the entity which is being read and filtered. See the query services for more information.

The following generic query hooks can be identified:

The before-query hook will have this signature:

public class BeforeQueryHook {
  public JSONObject transformQueryRequest(JSONObject json);
public class AfterQueryHook {
  public JSONObject transformQueryResponse(JSONObject json);

Query hooks are implemented for the following entities:

See the query service implementation for more details on data querying.

Note: hooks are called by a service, if a channel overrides a service it is possible that specific hooks are not called by the custom implementation.

Channel Request - Response Logging

A special table will be introduced to log and track the request and response for each channel service. Next to the response the system will also use this table to log exceptions/errors. The import entry concept (which has an archiving function) can be re-used for this.

Channel Execution Context

The server side code continuously should be able to detect for which channel the logic is executed. The channel is determined by the pos terminal which needs to be passed in as a parameter. The main service/request handler/thread should determine the pos terminal and set it from the start in a thread local.

Using this thread local, there should be an api which can be called by the execution code to always obtain the current channel/posterminal:

public class ChannelManager {
  public Channel getCurrentChannel();
  public OBPOSApplications getCurrentPOSTerminal();

Channel Request - Asynchronous handling

For high volume requests it makes sense to process the requests asynchronously. Asynchronous processing of channel requests (mainly makes sense for transactions) can be defined when specifying a custom implementation for a service. The asynchronous function can be implemented using the import entry framework.

Supporting push, data queries/updates

The proposal is to support both push and pull mode for channel operations. Pull mode is quite straightforward, the client does a request and receives a response. Push mode implementation is less generic, therefore the push class is defined in the channel explicitly.

For each channel a push subscription can be defined (see the push channel sub entity defined above).

The generic framework will do the following:

Potentially the import entry framework can be used for this.

Push mode will be supported for the following entities:

The push service is implemented for each channel. It has the following signature:

public class PushService {
  public boolean pushData(PushEntry pushDataEntry);

Some notes:

Channel Master Data Services

The proposal is to add a generic query service which can query for all kinds of master data using a simple criteria api. The main characteristic of this api is that it will allow the usage of non-db-ids to refer to searched data.

To focus the eHUB interface the proposal is to provide a generic query api for the following entities:

The query api will expect a json like this:

  "entity": "Order",
  "startRow": -1,
  "endRow": -1,
  "criteria": [

Customers & Addresses

The customer (=Business Partner) and addresses information can be accessed through the customer, so the customer query api should return the customer business object with all its address information and other related customer information.


The products api is quite extensive as all the product information is to be returned in one call. Only the products relevant for a pos terminal should be returned (assortment).

The service can be directed by providing the additional information:

For each product also its product categories should be returned.

Product Categories

Returns the list of product categories which are valid for a pos terminal.


The discount api returns a list of current discounts. It is probably to complex for any caller to implement the complete Openbravo discounting engine. But the discount id/names can be retrieved.


Return the list of taxes and tax rates. There is extensive logic in the backoffice to determine which tax to apply when. This api will only return the base information and will not replicate the complete Openbravo setup.

eHUB Transactional Services

The eHUB will provide transactional services for updating:

The update of product and related data is not in scope.

Currently Openbravo already offers a customer/address and orderloader. These api's can be re-used mostly, changes are needed to allow references to be send in as codes and not as database ids.


The customer loader of retail can be re-used for this. It allows to create and update a business partner. The customer loader needs to be wrapped into a ChannelService instance (so that hooks etc are called). That's the main change.

Customer Address

The customer address loader of retail can be re-used for this. It allows to create and update a business partner. The customer addressloader needs to be wrapped into a ChannelService instance (so that hooks etc are called). That's the main change.


The inventory api allows updating the inventory of a part in the Openbravo system. This is a new api which has the following signature:

The same structure as for the other apis can be used, so that multiple records at the same time can be send in.


The ticket api has to be extended to distinguish the following steps:

The above steps are present in the current order loading api but it needs to be extended, split and subdivided in 4 different services (create/update, ship, pay, invoice).

Retrieved from ""

This page has been accessed 3,077 times. This page was last modified on 30 November 2015, at 13:34. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.