Event Driven Push Notification - Step 4

Description

In this Example we are going to modify the previous exercise by adding some calls to a MySQL database using GVDataHandler and setting up a scheduler to auto trigger the service every minute.

MySQL Database setup

Before to proceed you have to install MySQL on your system. To do that, you can use the following commands:

sudo apt-get update
sudo apt-get install mysql-server

Now is time to start MySQL and create the finance database, neaded for this exercise:

cd /usr/bin/
sudo mysql
CREATE DATABASE finance;
INSERT INTO mysql.user (User,Host,authentication_string,ssl_cipher,x509_issuer,x509_subject)
VALUES('admin','localhost',PASSWORD('admin'),'','','');
SELECT User, Host, authentication_string FROM mysql.user;
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON finance.* to admin@localhost;
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'admin'@'localhost';

Finally, create the following tables:

CREATE TABLE finance.notification (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, date TIMESTAMP, message VARCHAR(80),
	username VARCHAR(30), token VARCHAR(180));
CREATE TABLE finance.event (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, date TIMESTAMP, message VARCHAR(80), avg
FLOAT, prevTick FLOAT, lastTick FLOAT);
CREATE TABLE finance.device (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30), token VARCHAR(180), 
	enabled VARCHAR(10));

Insert a list of device tokens into device table (true = enabled, false = disabled):

INSERT INTO finance.device (username, token, enabled) VALUES ("gvadmin", "YOUR_FCM_DEVICE_TOKEN", "true");
INSERT INTO finance.device (username, token, enabled) VALUES ("gvadmin", "ANOTHER_ENABLED_FCM_DEVICE_TOKEN", "true");
INSERT INTO finance.device (username, token, enabled) VALUES ("gvadmin", "ANOTHER_DISABLED_FCM_DEVICE_TOKEN", "false");

Then, you have to configure GreenVulcano in order to be able to use the MySQL database. To do that use the following commands from the Karaf console:

jdbc:ds-create -dbName finance -dt DataSource -dn mysql -u admin -dc com.mysql.jdbc.Driver -p admin -url
jdbc:mysql://localhost:3306/finance CONNECTION_NAME

And check if the datasource is correctly created:

jdbc:ds-list
jndi:names

Now, you should be able to find a new configuration file in [KARAF_HOME]/etc named org.ops4j.datasource-finance.cfg (where finance is the db name). The file should contain the following rows:

osgi.jdbc.driver.name= mysql
pool= dbcp2
url= jdbc:mysql://localhost:3306/finance
user= root
password= password
dataSourceName= finance-ds
jdbc.pool.maxIdle= 4
jdbc.pool.maxTotal= 16
jdbc.pool.minIdle= 2

Note:

  • it’s necessary that the selected schema is actually present in you db!
  • check if the feature pax-jdbc-mysql is installed into Karaf, if not install it by the following command:

    gvadmin@root()> feature:install pax-jdbc-mysql

System setup

We have to set up a new System (DB) to use db operations:

So, create a new System named DB and Channel named db. Now you have to insert into db channel the following elements:

getEnabledTokens (dh-call)

This call return a list of enabled device tokens.

  • class = it.greenvulcano.gvesb.virtual.datahandler.DataHandlerCallOperation
  • type = call
  • name = getEnabledTokens
  • dboBuilder (DBOBuilder)
    • type = dbobuilder
    • jdbc-connection-name = osgi:service/finance-ds
    • name = dboBuilder
    • dboSelect (DBOSelect)
      • class = it.greenvulcano.gvesb.datahandling.dbo.DBOSelect
      • ignore-input = true
      • rowset-builder = json
      • type = dbo
      • name = dboSelect
      • select (statement)
        • type = select
        • statement =

            SELECT username, token
            FROM finance.device
            WHERE enabled = "true"            
          

insertEvent (dh-call)

This call has the task to insert into event table a 50 days average break with the related details.

  • class = it.greenvulcano.gvesb.virtual.datahandler.DataHandlerCallOperation
  • type = call
  • name = insertEvent
  • dboBuilder (DBOBuilder)
    • type = dbobuilder
    • jdbc-connection-name = osgi:service/finance-ds
    • name = dboBuilder
    • dboInsert (DBOInsert)
      • class = it.greenvulcano.gvesb.datahandling.dbo.DBOInsert
      • ignore-input = true
      • type = dbo
      • name = dboInsert
      • insert (statement)
        • type = insert
        • statement =

          		
            INSERT INTO finance.event (date, message,avg,prevTick,lastTick)
            VALUES ("@{{DATE}}", "@{{MESSAGE}}", "@{{AVG}}","@{{PREV_TICK}}","@{{LAST_TICK}}")            
          		
          

insertNotification (dh-call)

This call insert into notification table date, message, username and token of the sent notification.

  • class = it.greenvulcano.gvesb.virtual.datahandler.DataHandlerCallOperation
  • type = call
  • name = insertNotification
  • dboBuilder (DBOBuilder)
    • type = dbobuilder
    • jdbc-connection-name = osgi:service/finance-ds
    • name = dboBuilder
    • dboInsert (DBOInsert)
      • class = it.greenvulcano.gvesb.datahandling.dbo.DBOInsert
      • ignore-input = true
      • type = dbo
      • name = dboInsert
      • insert (statement)
        • type = insert
        • statement =

          		
            INSERT INTO finance.notification (date, message, username, token)
            VALUES ("@{{DATE}}","@{{MESSAGE}}","@{{USERNAME}}", "@{{TOKEN}}")            
          		
          

Note: Check that your connection-factory is correctly configurated using the command jndi:names in the Karaf console.

Flow setup

Once the System DB is created we can start to modify our flows:

FinanceService


We are going to create another flow that can return a list of devices in order to send notifications only to the enabled devices, which is stored in the MySQL database. So, we don’t have to manually insert tokens anymore, then let’s remove getToken node and set getQuotationTrend as first node of the flow. Furthermore in this flow we have to add a db call to store an event (date, message and some data about the index under exam) only if we have “something to report”. Therefore we have to add the following elements:

notificationCondition (GVBufferCondition)

This element contains the properties of a GVBufferCondition that we can use for GVRoutings. If the message is equal to “Nothing to report.” and ALWAYS_SEND_DEBUG_MODE is not “true” this node return true. The two conditions are in “and” because they belong to the same group (g1).

  • class = it.greenvulcano.gvesb.internal.condition.GVBufferCondition
  • type = condition
  • condition = notificationCondition
  • MESSAGE (Property)
    • group = g1
    • operator = equal
    • type = gvbuffer-field
    • value = Nothing to report.
    • value-type = text
    • name = MESSAGE
  • ALWAYS_SEND_DEBUG_MODE (Property)
    • group = g1
    • operator = different
    • type = gvbuffer-field
    • value = true
    • value-type = text
    • name = ALWAYS_SEND_DEBUG_MODE

getNotificationMode (ChangeGVBufferNode)

This node has the task to retrive the value of ALWAYS_SEND_DEBUG_MODE property stored in a GV configuration file. The value will be requested during the deployment and any modification requires a configuration reload.

  • id = getNotificationMode
  • input = input
  • next-node-id = checkEvent
  • ChangeGVBuffer (ChangeGVBuffer)
    • clear-data = false
    • ALWAYS_SEND_DEBUG_MODE (PropertyDef)
      • name = ALWAYS_SEND_DEBUG_MODE
      • value = xmlp{{always.send.notification}}

checkEvent (GVNodeCheck)

This node, using the conditions defined before, allow to send notifications and store events only if the message body is considerable. So, if the message is equal to “Nothing to report.” and ALWAYS_SEND_DEBUG_MODE is not “true” the flow, next node will be end.

  • default-id = dbInsert
  • id = checkEvent
  • input = input
  • on-exception-id = error
  • notificationCondition (GVRouting)
    • condition = notificationCondition
    • next-node-id = end

dbInsert (GVOperationNode)

This node has the task to call insertEvent operation described before:

  • id = dbInsert
  • id-channel = db
  • id-system = DB
  • input = input
  • next-node-id = checkDB_2
  • operation-name = insertEvent
  • op-type = call
  • InputServices (InputServices)
    • dh-selector-service (dh-selector-service)
      • setDBService (dh-selector-call)
        • class = it.greenvulcano.gvesb.virtual.datahandler.DBOBuilderSelectorCallOperation
        • name = setDBService
        • type = call
        • DH_SERVICE_NAME = dboBuilder

checkDB_2 (GVNodeCheck)

This node just check if the previous operation it was successful:

  • default-id = prepareJson
  • id = checkDB_2
  • input = input
  • on-exception-id = error

NotificationHandler

Now we have to create another flow that can return a list of devices in order to send notifications only to the enabled devices, which is stored in the MySQL database.

setProperties (ChangeGVBufferNode)

This node has the task to initialize DATE and MESSAGE properties reading the json in the input buffer.

  • id = setProperties
  • input = input
  • next-node-id = getEnabledTokens
  • ChangeGVBuffer (ChangeGVBuffer)
    • clear-data = false
    • ALWAYS_SEND_DEBUG_MODE (PropertyDef)
      • name = ALWAYS_SEND_DEBUG_MODE
      • value = json{{date}}
    • MESSAGE (PropertyDef)
      • name = MESSAGE
      • value = json{{message}}

getEnabledTokens (GVOperationNode)

This node has the task to retrive a tokens list which will be used for sending notifications.

  • id = getEnabledTokens
  • id-channel = db
  • id-system = DB
  • input = input
  • next-node-id = checkDbCall
  • operation-name = getEnabledTokens
  • op-type = call
  • InputServices (InputServices)
    • dh-selector-service (dh-selector-service)
      • setDBService (dh-selector-call)
        • class = it.greenvulcano.gvesb.virtual.datahandler.DBOBuilderSelectorCallOperation
        • name = setDBService
        • type = call
        • DH_SERVICE_NAME = dboBuilder
  • OutputServices (OutputServices)
    • toString (script-service)
      • toString (script-call)
        • Script (Script)
          • Script =

              var payload =new java.lang.String(data.getObject());
              data.setObject(payload);
            

checkDbCall (GVNodeCheck)

This node just check if the previous operation it was successful:

  • default-id = sendToAll
  • id = checkDB_2
  • input = input
  • on-exception-id = error

sendToAll (GVLoopOperationNode)

This node makes n-calls to sendAndStore flow, one for each token in the list returned by the previous db-call.

  • class = it.greenvulcano.gvesb.core.flow.iteration.GVLoopOperationNode
  • id = sendToAll
  • input = input
  • next-node-id = checkIterator
  • op-type = subcall
  • sendAndStore (subflow)
    • change-log-context = true
    • dynamic = true
    • subflow = sendAndStore

checkIterator (GVNodeCheck)

This node just check if the previous operation it was successful:

  • default-id = end
  • id = checkIterator
  • input = input
  • on-exception-id = endError

endError (GVEndNode)

This node return the result of the operation in case of failure:

  • id = endError
  • output = input

end (GVEndNode)

This node return the result of the operation in case of success.

  • id = end
  • output = input

SendAndStore

getDataFromJson (ChangeGVBufferNode)

This node has the task to retrive the value of username and token from the json in the input buffer and define USERNAME and TOKEN properties:

  • id = getDataFromJson
  • input = input
  • next-node-id = send
  • ChangeGVBuffer (ChangeGVBuffer)
    • clear-data = false
    • TOKEN (PropertyDef)
      • name = TOKEN
      • value = json{{token}}
    • USERNAME (PropertyDef)
      • name = USERNAME
      • value = json{{username}}

pushNotificationCall (GVCoreCall)

This node just send the json to PushNotification service:

  • id = pushNotificationCall
  • id-service = PushNotification
  • input = input
  • next-node-id = end
  • operation = Send

storeMessage (GVOperationMode)

This node call insertNotification operation to save the sent message into the database.

  • class = it.greenvulcano.gvesb.core.flow.GVOperationNode
  • type = flow-node
  • name = storeMessage
  • id-channel = db
  • id-system = DB
  • input = input
  • next-node-id = check
  • operation-name = insertNotification
  • op-type = call

check (GVNodeCheck)

This node just check if the previous operation it was successful:

  • default-id = end
  • id = check
  • input = input
  • on-exception-id = err

err (GVEndNode)

This node return the result of the operation in case of failure:

  • id = err
  • output = input

end (GVEndNode)

This node return the result of the operation in case of success.

  • id = end
  • output = input

Send

We don’t have to set the properties in this flow anymore because they’re already present in the input buffer, then remove getDataFromJson node and set sendPushNotification as first node of the flow.

Lastly, you have to modify the Forward configuration to trigger the right service:

<ForwardConfiguration enabled="true" flow-service="FinanceService"
                      forwardName="notificationHandler" full-debug="true"
                      name="financePushNotification" ref-dp="textMessageReader">
      <ForwardDeployment clientId="clientSub"
                         connection-factory="osgi:service/jms/inboundConnection"
                         destination="TEST.TOPIC" destination-type="topic"
                         transacted="false" transaction-timeout-sec="30"/>
</ForwardConfiguration>

Testing with GV Console

Now you are able to test your VulCon Service from the GV Console® once exported the configuration.

So, let’s start GreenVulcano® ESB, access to the GV Console and deploy your Vulcon project setting your apikey. Set always.send.notification property to true if you want to reiceve all the notifications, even when the message body is “nothing to report.” This mode is useful to test the notification system.


Once the configuration is deployed you can finally test it. Go to Execute section end select Threshold operation. In this case you don’t need to insert anything in the body, just click on Run button.

Now you can reiceve notifications by your Android App:


We can also use GV-Scheduler to auto execute the service every minute. To do that, you have to install “gvscheduler” and “gvscheduler-conf” features. You should set always.send.notification property to false if you don’t want to reiceve many notification with “nothing to report.” When you change the value of a property in the console, you have to reload the configuration before the changes take effect.


Note: In case of error or exceptions you can check the file GVCore.log situated in the folder GV_HOME/data/log/.

Download

Here you can download the configuration: