Your First Graph
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.