Introduction

Let's begin by writing a very simple graph to get acquainted with directed graph. To follow this tutorial you need to have access to an SDNC controller which can be an ONAP SDNC virtual machine with the containers for the controller and dgbuilder. 

This graph will use SLI-API execute which is installed by default by the ONAP SDNC installation scripts.

SLI-API is being used because it allows rapid prototyping of directed graphs without all of the setup required by an MD-SAL project.


You can either use the dgbuilder application on your running SDNC controller or install directed graph builder on your local VM. The tutorial for local install is at Install Directed Graph Builder on Ubuntu Desktop 

You should be familiar with calling REST APIs with a JSON payload. Postman is a popular and features a GUI. Command line options like curl are fine as well.

Your First Nodes

Open your browser and go to your directed graph instance. The default should be http://localhost:3100/# you can check the console you started dgbuilder in to confirm the URL. On the ONAP SDNC controller virtual machine the dgbuilder docker container is on port 3000 (e.g. http://10.0.7.1:3000/# or http://[sdnc_vm_public_id]:3000/#)

Your initial sheet will be blank. On the left hand side of the screen is a palette of nodes.

Left click and drag dgstart into the blank page. Do the same for service-logic and then method.

dgstart has a tab that when clicked will open up a dialog window for the developer. It is also the start node of any given graph and code execution starts at this node.

service-logic is used to uniquely identify a graph. Double left click on this node and a dialog window will appear.

For module fill in TUTORIAL in all caps. For version simply put down 1 and then click Ok. Now double click on the method node.

By deffault it will have rpc='', click between the single quotes and type in helloWorld like in the screen shot below then click Ok.

Your First Graph

From the left hand palette drag in a record node onto the screen.

Each node has a connector on the right, if you left click and hold it you can connect one node to another node.

Connect dgstart to service-logic, service-logic to method, and method to record. Your screen should look similar to the screenshot below.

Double click on the record node. By default the node will just have the tag <record>. Highlight and delete this tag. Copy the below XML onto your clipboard and then paste it into your node then click ok.

<record plugin="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder">
<parameter name="logger" value="message-log" />
<parameter name="level" value="info" />
<parameter name="field1" value="Hello World!"/>

The previous value for the record plugin was "org.openecomp.sdnc.sli.recording.Slf4jRecorder," but that is out of date. 

At this point this is a working directed graph, quite possibly the simplest graph that can be written.

The record node is used to write lines to the log. This will write a single line to the log with the hardcoded field "Hello World!".

Upload and activate your graph, doing this through dgbuilder is the most convenient method. If you are unsure how to do this visit  Update and Activate Through DGBuilder.

Now that the graph is uploaded and activated we can invoke it.

The URL to use for you local machine is http://localhost:8181/restconf/operations/SLI-API:execute-graph. Basic authorization is used, the username is admin and the password is the standard ONAP default password.

Use the below body. Initially we will not pass any parameters because this graph does not read any parameters.

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter":  [
        ]
    }
}

If everything worked we should get an HTTP 200 OK response. Let's check the logs to be sure.

tail /var/log/onap/sdnc/karaf.log

Below is the output of this command

2017-03-14T14:26:52.650Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T14:26:52.650Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T14:26:52.651Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (record)
2017-03-14T14:26:52.651Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T14:26:52.651Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T14:26:52.654Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T14:26:52.656Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Hello World!|
2017-03-14T14:26:52.656Z|8f3f991f-b844-4dc9-a5da-512c700c7e8f|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found

Based on this output we can see the graph which was just written, uploaded and activated has finally been executed. It executes a single node which we can see is writing a hardcoded string to the log file.

Using A Block Node

Let's make this into a simple 2 node graph, one node will record "Hello World!" the second node will record "Goodbye".

First drag a block node from the left hand palette into the page.

Make a copy of the existing record node. To do this left click on the record node that already exists then hit "crtl + c" to copy and then hit "crtl + v" to paste. Left click so the node is placed on the graph.

To delete an existing connection between two nodes simply left click on the wire and then hit the delete key.

Connect the nodes so they match what we have below.

Double left click on the second record node, using the editor change field1 from "Hello World!" to "Goodbye". Click save, then upload and activate this graph.

Submit the same REST request and tail the debug log.

tail /var/sdnc/logs/bvc/debug.log
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Hello World!|
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 3
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T14:47:07.902Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T14:47:07.903Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Goodbye!|
2017-03-14T14:47:07.903Z|f17b1eeb-c31e-407b-b04d-8e5b8c1681d7|qtp1849298247-43|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found

We can see that we now have a 3 node graph (block, record and record).

You should learn two things:

  • Block nodes are needed whenever multiple nodes need to be executed
  • Graphs execute from top to bottom, because the first node is above the second Hello World is printed before Goodbye. To test this you can drag the lower node above the other node and re-test. You can also experiment with moving nodes horizontally, the horizontal position does not matter.

Reading User Input

At this point the graph prints only static messages. To make it more interactive we can start passing and reading parameters.

If this was an MD-SAL project we would have a copy of the RPC's input in memory. For SLI-API execute we can pass in a free form input that is loaded into memory.

For our example we will pass in a customerName, the log will say hello to the customer and then print out goodbye.

To do this modify the first record node

<record plugin="org.onap.sli.core.sli.recording.Slf4jRecorder">
<parameter name="logger" value="message-log" />
<parameter name="level" value="info" />
<parameter name="field1" value="Hello World!"/>
<parameter name="field2" value="`$customerName`"/>

You will be adding a second field. You will notice this field contains a dollar sign and back ticks. A dollar sign ($) is used anytime values are read from memory.

The back ticks (`) are used whenever a service logic expression is being created. In this case we have a very simple expression, but more complex expressions can be written.

Update the JSON body of the request to match what is below

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": "john"
            }
        ]
    }
}

Again check the logs

/opt/opendaylight/data/log/karaf.log
2018-12-13T23:01:26,161 | INFO  | qtp892619002-352 | sliapiProvider                   | 226 - org.onap.ccsdk.sli.core.sliapi-provider - 0.3.1 |  -  | Calling directed graph for TUTORIAL/helloWorld/sync
2018-12-13T23:01:26,161 | INFO  | qtp892619002-352 | SvcLogicServiceImpl              | 222 - org.onap.ccsdk.sli.core.sli-provider - 0.3.1 |  -  | Fetching service logic from data store
2018-12-13T23:01:26,171 | INFO  | qtp892619002-352 | SvcLogicServiceImpl              | 222 - org.onap.ccsdk.sli.core.sli-provider - 0.3.1 | SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1, md5sum=8d458c0a353f6676fd8ec607734412cf] -  | About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1, md5sum=8d458c0a353f6676fd8ec607734412cf]
2018-12-13T23:01:26,172 | INFO  | qtp892619002-352 | SvcLogicServiceImpl              | 222 - org.onap.ccsdk.sli.core.sli-provider - 0.3.1 | SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1, md5sum=8d458c0a353f6676fd8ec607734412cf] - 1 (block) | About to execute node # 1 (block)
2018-12-13T23:01:26,173 | INFO  | qtp892619002-352 | message-log                      | 223 - org.onap.ccsdk.sli.core.sli-recording - 0.3.1 | SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1, md5sum=8d458c0a353f6676fd8ec607734412cf] - 1 (block) | |Hello World!|john|
2018-12-13T23:01:26,173 | INFO  | qtp892619002-352 | message-log                      | 223 - org.onap.ccsdk.sli.core.sli-recording - 0.3.1 | SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1, md5sum=8d458c0a353f6676fd8ec607734412cf] - 1 (block) | |Goodbye!|


We can see that the value of the parameter named customerName is now printed out in the log.

Return an Error

Currently no matter what the caller passes the graph returns success. For this example we have decided if the customer name is john we should stop processing and return an error. This is because john has been known to steal service.

Every graph should either return failure or success. Business rules should dictate whether failure or success is returned. In an MD-SAL project the return status of the graph might dictate whether data is committed or rolled back.

In this example the caller will be able to see the return status.

Drag into the page a switch node, a returnFailure, a returnSuccess and an outcome. Arrange and connect them similar to below.


Switch nodes work like a switch statement in any programming language. Outcomes are like case statements.

The switch will be on the customerName and we will add a case for when the customerName is john. We connect return failure to this outcome. In effect when the customerName is equal to john the graph returns failure.

First edit the switch node so it reads the value of the customerName

 <switch test='`$customerName`'>

Edit the outcome so it only applies for john

<outcome value='john'>

Edit the failure node to return a hardcoded message and error code

<return status='failure'>
<parameter name='error-code' value='400' />
<parameter name='error-message' value='john is not welcome here.' />

Edit the success to return a hardcoded message and error code

<return status='success'>
<parameter name='error-code' value='200' />
<parameter name='error-message' value='SUCCESS' />

200 represents success.

double click on the block node, check off the checkbox next to atomic.

When a block node is atomic it stops executing further nodes if a failure is encountered. You can experiment with this by toggling it on or off, patching the graph and re-executing.

If this wasn't atomic the graph would always continue executing the print statements and the return success node.

Now let's send two payloads to this graph.

Payload 1 : The error case

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": "john"
            }
        ]
    }
}

The client receives this response

{
  "output": {
    "response-message": "john is not welcome here.",
    "context-memory-json": "{\"SvcLogic.status\": \"failure\",\"input.mode\": \"Sync\",\"customerName\": \"john\",\"input.rpc-name\": \"helloWorld\",\"error-message\": \"john is not welcome here.\",\"error-code\": \"400\",\"input.module-name\": \"TUTORIAL\"}",
    "response-code": "400",
    "ack-final-indicator": "Y"
  }
}

Checking the logs

2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to john
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Next node to execute is node 3
2017-03-14T18:24:58.137Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 3
2017-03-14T18:24:58.138Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-14T18:24:58.138Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status failure
2017-03-14T18:24:58.138Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to john is not welcome here.
2017-03-14T18:24:58.138Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 400
2017-03-14T18:24:58.138Z|c9dbf2a1-8984-40b5-8b2c-a429cf69b414|qtp1849298247-41|INFO |BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - stopped executing nodes due to failure status

It is clear the print nodes are not executing, the logs even mention the block node stopped executing due to failure status.

Let's try Payload 2 : the success case

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": "tom"
            }
        ]
    }
}

The client receives the response

{
  "output": {
    "response-message": "SUCCESS",
    "context-memory-json": "{\"SvcLogic.status\": \"success\",\"input.mode\": \"Sync\",\"customerName\": \"tom\",\"input.rpc-name\": \"helloWorld\",\"error-message\": \"SUCCESS\",\"error-code\": \"200\",\"input.module-name\": \"TUTORIAL\"}",
    "response-code": "200",
    "ack-final-indicator": "Y"
  }
}

Checking the logs

2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to tom
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |SvcLogicExprListener            |143 - com.att.sdnctl.sli-common - 11.0.7.SNAPSHOT|Outcome (tom) not found, keys are { (john)}
2017-03-14T18:30:57.233Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|No next node found
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 4
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Hello World!|tom|
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 3
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 5
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Goodbye!|
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T18:30:57.234Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 4
2017-03-14T18:30:57.235Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 6
2017-03-14T18:30:57.235Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-14T18:30:57.235Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status success
2017-03-14T18:30:57.235Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to SUCCESS
2017-03-14T18:30:57.235Z|e1f013c9-de97-4ae9-8681-b7be28126b6f|qtp1849298247-46|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 200

We can see the print statements are working and success is returned.

Checking For Null Values

The current code prevents john from using this service, but the client can enter a null or empty customerName.

Drag a new outcome node onto the graph. Connect this to the existing switch statement.

By default an outcome matches empty string, do not change this.

<outcome value=''>

Connect a new failure to this outcome with a new hardcoded message for example

<return status='failure'>
<parameter name='error-code' value='400' />
<parameter name='error-message' value='customer name was null.' />

The graph should look similar to the screenshot below


We can test against two scenarios

Scenario 1 customer name is completely missing (null)

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [
        ]
    }
}

The client will now receive the response

{
  "output": {
    "response-message": "customer name was null.",
    "context-memory-json": "{\"SvcLogic.status\": \"failure\",\"error-message\": \"customer name was null.\",\"input.rpc-name\": \"helloWorld\",\"input.module-name\": \"TUTORIAL\",\"input.mode\": \"Sync\",\"error-code\": \"400\"}",
    "response-code": "400",
    "ack-final-indicator": "Y"
  }
}

Scenario 2 the customer name is empty string

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": ""
            }
        ]
    }
}

The client will now receive the response

{
  "output": {
    "response-message": "customer name was null.",
    "context-memory-json": "{\"SvcLogic.status\": \"failure\",\"input.mode\": \"Sync\",\"customerName\": \"\",\"input.rpc-name\": \"helloWorld\",\"error-message\": \"customer name was null.\",\"error-code\": \"400\",\"input.module-name\": \"TUTORIAL\"}",
    "response-code": "400",
    "ack-final-indicator": "Y"
  }
}

The logs are below

2017-03-14T19:04:39.618Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T19:04:39.618Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to 
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Next node to execute is node 4
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 4
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status failure
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to customer name was null.
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 400
2017-03-14T19:04:39.619Z|72f0cbcf-69c6-4b93-92aa-0cd5da32112b|qtp1849298247-45|INFO |BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - stopped executing nodes due to failure status

The Other Outcome

Let's refactor the code to use an "other" outcome.

Drag in the other outcome from the palette. Drag in a new block node. Put the existing record nodes under the new block node, connect this to the other outcome.

Connect the other outcome to the original switch node. It should look like the screenshot below.


other outcomes function like a default case statement. When the customerName is not john and the customerName is not null the other outcome will execute.

Let's upload this graph and test with this payload

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "helloWorld",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": "tom"
            }
        ]
    }
}

Let's check  the logs

2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T19:14:45.437Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to tom
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |SvcLogicExprListener            |143 - com.att.sdnctl.sli-common - 11.0.7.SNAPSHOT|Outcome (tom) not found, keys are { ("") (john) (Other)}
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Next node to execute is node 5
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 5
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 6
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T19:14:45.438Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Hello World!|tom|
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||Goodbye!|
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 8
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status success
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to SUCCESS
2017-03-14T19:14:45.439Z|2c2a119c-5d0c-477c-9f10-35ece3d62d10|qtp1849298247-41|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 200

We can see the code is working as expected. This refactoring wasn't necessary, but there are cases when an other outcome is highly useful.

Context Memory

Behind the scenes memory is nothing more than a HashMap<String,String> in java. We can read and modify values in this hashmap.

SLI-API execute returns the contents of this hashmap to the client for debugging purposes. You may have already noticed this in the previous responses.

"context-memory-json": "{\"SvcLogic.status\": \"success\",\"input.mode\": \"Sync\",\"customerName\": \"tom\",\"input.rpc-name\": \"helloWorld\",\"error-message\": \"SUCCESS\",\"error-code\": \"200\",\"input.module-name\": \"TUTORIAL\"}",

One way to place values into this hashmap is using a set node.

Drag a set node from the palette onto the page. Double-click the set node. Lets create an array of greetings.

<set>
<parameter name='greeting[0]' value='HELLO' />
<parameter name='greeting[1]' value='BONJOUR' />
<parameter name='greeting[2]' value='CIAO' />
<parameter name='greeting_length' value='3' />

These values will all be put into context memory so they can be read.

Looping

Currently only For loops are supported. Let's loop over the greeting array. Drag a for node onto the page. One of the record nodes can be deleted.

The set node should be arranged so it executes early. Your graph should look similar to the graph below.


Double click the for node to edit it.

<for index='greetingIdx' start='0' end='`$greeting_length`' >

Fill in the values mentioned above. Double click the record node.

<record plugin="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder">
<parameter name="logger" value="message-log" />
<parameter name="level" value="info" />
<parameter name="field1" value="`$greeting[$greetingIdx]`"/>
<parameter name="field2" value="`$customerName`"/>

Field 1 of the record node uses two values in context memory. One is the index of the for loop, this is resolved first. Then it gets the value out of the greeting array in context memory.

Lets check the logs

2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-14T19:35:18.452Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-14T19:35:18.453Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type set - com.att.sdnctl.sli.provider.SetNodeExecutor
2017-03-14T19:35:18.453Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[0] to HELLO
2017-03-14T19:35:18.454Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting_length to 3
2017-03-14T19:35:18.454Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[2] to CIAO
2017-03-14T19:35:18.455Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[1] to BONJOUR
2017-03-14T19:35:18.455Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 3
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to tom
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |SvcLogicExprListener            |143 - com.att.sdnctl.sli-common - 11.0.7.SNAPSHOT|Outcome (tom) not found, keys are { ("") (john) (Other)}
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Next node to execute is node 6
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 6
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type for - com.att.sdnctl.sli.provider.ForNodeExecutor
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing atomic for loop - for (int greetingIdx = 0; greetingIdx < 3; greetingIdx++)
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T19:35:18.456Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||HELLO|tom|
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||BONJOUR|tom|
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||CIAO|tom|
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 3
2017-03-14T19:35:18.457Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 8
2017-03-14T19:35:18.458Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-14T19:35:18.458Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status success
2017-03-14T19:35:18.458Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to SUCCESS
2017-03-14T19:35:18.458Z|29796c7e-c41c-4b5b-980c-55832c223ac4|qtp1849298247-44|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 200

We can see it is looping over the greeting array and exiting.

Calling Subgraphs

It is possible for any graph to call any other graph. The word subgraph here means a graph that is only intended to be called by another graph and not invoked alone.

During a graph call context memory is shared between both graphs. This means the subgraph can access any memory the calling graph has set. The calling graph will also be able to access any memory the subgraph has set.

The same instance of the hashmap is used. The code must carefully be written or it can overwrite values unexpectedly.

Subgraphs can be a good way to produce re-usable common code. They need to be written very carefully to function properly.

The call node is used to make a call to another graph. Create a new graph set the module name to TUTORIAL,  version to 1, rpc name to greetingService and leave mode as sync.

Drag in a block node, set node and call node.

Let's have the set node override the customer name to something more generic

<set>
<parameter name='customerName' value='valued customer' />

Now let's have the call node call the original graph we had written

<call module='TUTORIAL' rpc='helloWorld' mode='sync' >

Your graph should look something like this



Now let's call it using this body

{
    "input": {
        "module-name": "TUTORIAL",
        "rpc-name": "greetingService",
        "mode": "sync",
        "sli-parameter": [{
                "parameter-name": "customerName",
                "string-value": "john"
            }
        ]
    }
}

This response is sent back

{
  "output": {
    "response-message": "SUCCESS",
    "context-memory-json": "{\"SvcLogic.status\": \"success\",\"greeting[0]\": \"HELLO\",\"input.mode\": \"Sync\",\"customerName\": \"valued customer\",\"input.rpc-name\": \"greetingService\",\"greeting[2]\": \"CIAO\",\"error-message\": \"SUCCESS\",\"greeting_length\": \"3\",\"error-code\": \"200\",\"input.module-name\": \"TUTORIAL\",\"greeting[1]\": \"BONJOUR\",\"greetingIdx\": \"2\"}",
    "response-code": "200",
    "ack-final-indicator": "Y"
  }
}

Let's check the logs

2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=greetingService, mode=sync, version=1]
2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing root node
2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-15T15:32:10.145Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type set - com.att.sdnctl.sli.provider.SetNodeExecutor
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute customerName to valued customer
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 3
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type call - com.att.sdnctl.sli.provider.CallNodeExecutor
2017-03-15T15:32:10.146Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|CallNodeExecutor                |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|execute: got SvcLogicGraph
2017-03-15T15:32:10.153Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|CallNodeExecutor                |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Calling [TUTORIAL,helloWorld,null,sync]
2017-03-15T15:32:10.160Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute graph SvcLogicGraph [module=TUTORIAL, rpc=helloWorld, mode=sync, version=1]
2017-03-15T15:32:10.160Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|About to execute node # 1 (block)
2017-03-15T15:32:10.160Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 1
2017-03-15T15:32:10.161Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type block - com.att.sdnctl.sli.provider.BlockNodeExecutor
2017-03-15T15:32:10.161Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 1
2017-03-15T15:32:10.161Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 2
2017-03-15T15:32:10.161Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type set - com.att.sdnctl.sli.provider.SetNodeExecutor
2017-03-15T15:32:10.162Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[0] to HELLO
2017-03-15T15:32:10.163Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting_length to 3
2017-03-15T15:32:10.164Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[2] to CIAO
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SetNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute greeting[1] to BONJOUR
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 2
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 3
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type switch - com.att.sdnctl.sli.provider.SwitchNodeExecutor
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing switch node
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|test expression ($customerName) evaluates to valued customer
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |SvcLogicExprListener            |143 - com.att.sdnctl.sli-common - 11.0.7.SNAPSHOT|Outcome (valued customer) not found, keys are { ("") (john) (Other)}
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SwitchNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Next node to execute is node 6
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 6
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type for - com.att.sdnctl.sli.provider.ForNodeExecutor
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing atomic for loop - for (int greetingIdx = 0; greetingIdx < 3; greetingIdx++)
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-15T15:32:10.165Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||HELLO|valued customer|
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||BONJOUR|valued customer|
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ForNodeExecutor                 |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|For  - executing outcome 1
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 7
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type record - com.att.sdnctl.sli.provider.RecordNodeExecutor
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|record node encountered - looking for recorder class com.att.sdnctl.sli.recording.Slf4jRecorder
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|INFO |message-log                     |145 - com.att.sdnctl.sli-recording - 11.0.7.SNAPSHOT||CIAO|valued customer|
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|RecordNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no failure or Other branch found
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|BlockNodeExecutor               |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Block - executing outcome 3
2017-03-15T15:32:10.166Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node 8
2017-03-15T15:32:10.167Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|SvcLogicServiceImpl             |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Executing node executor for node type return - com.att.sdnctl.sli.provider.ReturnNodeExecutor
2017-03-15T15:32:10.167Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Returning status success
2017-03-15T15:32:10.167Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-message to SUCCESS
2017-03-15T15:32:10.167Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|ReturnNodeExecutor              |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|Setting context attribute error-code to 200
2017-03-15T15:32:10.167Z|756ffbf9-9e44-4e3c-8e6c-66960ff9c501|qtp1849298247-42|DEBUG|CallNodeExecutor                |144 - com.att.sdnctl.sli-provider - 11.0.7.SNAPSHOT|no success or Other branch found

You should notice a few things:

  • The original graph overwrote the customerName so the subgraph couldn't prevent john from using this service.
  • The response-code and response-message being returned are written by the subgraph and not the parent graph.
  • Memory between the graphs is shared

Sharing memory makes passing data very simple, but can have unintended consequences. When writing subgraphs this must be understood.

Conclusion

At the end of this guide you should be familiar with:

  • creating a graph from scratch
  • reading user input
  • returning errors
  • checking for null values
  • block node
  • atomic block node
  • outcomes
  • looping
  • handling arrays
  • set node
  • record node
  • call node

This covers the base functionality of directed graph. You can now continue with Further Reading.



  • No labels

12 Comments

  1. Hi,

    Cannot see the screenshots as the link provided for it is of att.

    Regards,

    Shubhada

  2. Sorry about that. Confluence wasn't as smart as I expected it to be. I was copying from an internal confluence to an external confluence and it didnt move the images. I fixed this page and will work through the other pages today.

  3. Hi,

    Can you please provide various missing links wherever you have mentioned (fill in link). ?

    eg: This graph will use SLI-API execute, if this hasn't been installed yet install it now by following SLI-API:execute-graph#API:execute-graph-InstallingSLI-API (fill in link).


    Regards,

    Shubhada

    1. Hi Shubhada Vaze i am not able to see the SLI-API module in the swagger api . because of this i am not able to execute the directed graphs. 

      Could you tell me how to activate the SLI-API module in the ONAP SDNC

  4. /var/sdnc/logs/bvc/debug.log
    Hi, 
    Can you please tell the exact location where we can find this debug.log file? Is it inside any specific container or ouside container on rackspace? 
    1. Hi Shubhada,

      were you able to figure out where debug.log is located ? I am also not able to see it.

      Checked both containers:  sdnc container and dgbuilder container.

      Could be that it is not enabled ?

      1. Hello,

        After running the test, I found the "Hello World!" log line in the sdnc_controller_container of the SDN-C VM in two different files:

        • the karaf log file: /opt/opendaylight/distribution-karaf-0.6.1-Carbon/data/log/karaf.log
        • the TUTORIAL DG log file: /opt/opendaylight/distribution-karaf-0.6.1-Carbon/data/log/SvcLogicGraph [module=TUTORIAL, rpc=helloworld, mode=sync, version=1].log 

        Regards,

        Gwenael


        PS: in order to make the "record" node work with the SDN-C VM I installed thanks to the onap_openstack.yaml and onap_openstack.env files found in the heat/ONAP directory of the ONAP demo project  (https://gerrit.onap.org/r/p/demo.git, master branch, c46a7459849f5219959b92e684619674a34fc8f2 commit ID), I had to change the package name of the Slf4jRecorder in the "record" node XML on dgbuilder:

        • default package provided by dgbuilder: <record plugin="org.openecomp.sdnc.sli.recording.Slf4jRecorder">
        • fixed package: <record plugin="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder">

        Before the fix, the "Hello World!" message was not output in the logs and I had the following error in karaf log:

        2017-10-23 10:20:25,756 | WARN | p782482231-30892 | RecordNodeExecutor | 295 - org.onap.ccsdk.sli.core.sli-provider - 0.1.2.SNAPSHOT | Could not find SvcLogicRecorder object for plugin org.openecomp.sdnc.sli.recording.Slf4jRecorder

        This issue is already tracked: SDNC-106 - Getting issue details... STATUS


  5. Hi,

    I am running into an issue while trying to access the logs:

    root@sdnc-694965092-whftc:/opt/opendaylight/distribution-karaf-0.6.1-Carbon/data# tail /var/log/onap/sdnc/karaf.log
    Oct 26, 2017 7:15:57 PM org.apache.karaf.main.lock.SimpleFileLock lock
    INFO: Lock failed
    Oct 26, 2017 7:15:58 PM org.apache.karaf.main.lock.SimpleFileLock lock
    INFO: Trying to lock /opt/opendaylight/distribution-karaf-0.6.1-Carbon/lock
    Oct 26, 2017 7:15:58 PM org.apache.karaf.main.lock.SimpleFileLock lock
    INFO: Lock failed
    Oct 26, 2017 7:15:59 PM org.apache.karaf.main.lock.SimpleFileLock lock
    INFO: Trying to lock /opt/opendaylight/distribution-karaf-0.6.1-Carbon/lock
    Oct 26, 2017 7:15:59 PM org.apache.karaf.main.lock.SimpleFileLock lock
    INFO: Lock failed

    If anybody has come across this, or may know a fix, any guidance would be appreciated!

  6. Usually that means there is a previous run of ODL that didn't get stopped correctly (if it persists for more than few cycles).  Did you try removing the lock file ? (after making sure no other kafka instances running).

    btw - /opt/opendaylight/current/data/log would be the path I would have used to find karaf.log and the new per DG log files so that when a new version is deployed we move the link from carbon to nitrogen.

  7. Hi, 

    In my hello word DG example, if I set a sub-node to return failure in an atomic node block. the rollback does not happen.

    my question is

    does setting a block as atomic means that a rollback in case of failure is automatically defined or not. In other words, do DG have a rollback mechanism or not?



    Bests

  8. Hi All,
    I would like to find a way to parse the returned hash(string;string) like
    "context-memory-json": "{\"SvcLogic.status\": \"success\",\"input.mode\": \"Sync\",\"customerName\": \"tom\",\"input.rpc-name\": \"helloWorld\",\"error-message\": \"SUCCESS

    in order to extract some valuable information I would like to use for further treatment.
    How could I do that please ?
    Many thx !
    David.