Hiya! 👋
It's been some time since I wrote on my blog. Recently, I participated in SHARE Dallas 2022 Hackathon that happened between Mar 28, 2022 and Mar 29, 2022 and it was a great experience that I wanted to treasure. Hence this post 😀.
This Hackathon showed the modern ways of working on a Mainframe and it, for sure, fascinates the Mainframers as well as those who think of IBM Mainframes as legacy and old stuff.
⚠ Before we start, I would like to let you know that this is going to be a long post because the takeaway was pretty huge for me. So, I'll be writing couple of posts to cover the entire experience (this being the first one)
The Hackathon was made available to participate for virtual attendees as well as in-person attendees of SHARE Dallas 2022 Event and no registration cost was involved. I participated virtually from India.
How things began on the day of event?
The Challenge 💪
- Display all the items in a catalog
- Display detailed information of an item
- Order an item.
CICS Interface showing the Main Menu of the Catalog Manager Application. |
CICS Interface showing the list of items in the Catalog, when '1. List Items' is selected from the Main Menu. |
CICS Interface showing the detailed information of an item when an item is selected from the previous screen. |
CICS Interface showing the status of the order at the left side bottom of the screen. |
Hacking through the tasks for Day 1
Task 1:
There is a UNIX interface within z/OS called UNIX System Services, or USS, so you can log in through ssh and hammer out commands.
For writing the Python code, I used the IBM Z Open Editor instead of Unix terminal. To view/edit the files on IBM Z Open Editor, all you need to do is to locate the file that you just created, from Unix System Services (USS) section under Zowe, and click on it. The contents of the file will be shown on the right side on IBM Z Open Editor.
Viewing the contents of helloWorld.py file on IBM X Open Editor. |
I just wrote a one line command using the print() function in Python to display a message. To finish the Task 1, I used the python3 command on the Terminal of VS Code to run the Python script I had created.
Output displayed after invoking the Python script using python3 command from USS Terminal. |
It is essential that we get inside the directory where our Python code is saved, before running the code with the python3 command.
This marked the completion of Task 1 ✅
Task 2:
To take things to the next level, Task 2 was all about creating our First web application on z/OS. I was introduced to the usage of Flask on Python.
Flask is a popular web framework and it provides functions on Python for rendering an HTML page and handling incoming HTTP requests.
I installed Flask on Python using the pip3 command. Post installation, I created a new directory under my Home directory (/u/ztecu85) and named it as webApp. Under webApp directory, two sub-directories namely static and templates were created.
webApp directory is where all my project's files resided. As the challenge unfolded, we had to create some HTML files and those were stored under the templates sub directory.
To complete the task, I created a new file named as webserver.py under webApp directory and wrote the code as shown below.
from flask import Flask - This line imports Flask module to the project.
app = Flask(__name__) - __name__ is a special variable in Python which returns the name of the current module (webserver.py). This line of code helps Flask look for the relevant files needed by the application, such as static and template files. Flask manages to find the root path based on the value stored in __name__.
@app.route('/') - This tells the Flask which URL should call the user defined Python function, index()that is defined in the next line. By passing '/' as an argument to the route() function of the Flask Class, we're binding the URL so that when we load the URL on the browser, we will be greeted with a message returned by index() function.
As we have associated the URL - 10.3.20.138 and Port - 24320 with the index() function defined in Python through app.run() method, this 👇 is what happened when I ran this code from the Unix Terminal.
Upon the execution of the code, there were several messages shown on the Terminal. One message showed a URL where the application was running. Pressing Ctrl + Clicking on the link took me to the URL where the message returned by the index() function was displayed.
This task was a nice twist to the traditional 'Hello World' program that we printed the same message on a web application.
Task 3:
This task introduced me to the CICS part. As mentioned earlier, the three CICS functions were made available to us by means of three REST API's. The Challenge documentation for this task contained a table with detailed description of the API's.
Though testing these API's were optional, I used the Postman tool to post the API's with the URL given for each function and receive responses to get familiarized with them.
Following are the GIF's showing the responses received on Postman after posting the three API's.
1. API to list all the items in Catalog
HTTP Verb: GET
URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/items?startItemRef={ }
Note that there were 21 items in the Catalog and each item had a unique Item Reference number (itemRef), starting from # 0010 up until 0210, in the increment of +10. The curly braces (highlighted in Red color) at the end of the URL means that it accepts a query parameter, which is an Integer between 10 and 210 (in the increment of +10). In the following GIF, I've assigned 10 to startItemRef at the end of the URL, so that the CICS application use the startItemRef value to get the next 15 items from the Catalog.
2. API to get the detailed information on one Item:
HTTP Verb: GET
URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/items/{ }
Posting this URL fetched the detailed information on one Item with itemRef that we have passed as query parameter at the end of the URL (The curly braces highlighted in Red color at the end of the URL means that it accepts query parameter).
3. API to Order an Item:
HTTP Verb: POST
URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/orders
This service was different from the other two that while posting this service, we had to send along a Request in JSON format. This Request contained information about the item that we wish to order and the User ID with which we are ordering. CICS Application used this information to update the Catalog and pass the Order's status message.
Upon posting the URL, following response was received.
Task 3a:
In this task, we were asked to invoke the API, that list items from the Catalog, using Python. As the response had only 15 items, participants were asked to use the information in the lastItemRef key to create some code in Python that lists all 21 items. FYI, each Item in the response would have a lastItemRef key that holds the value of the last item's reference number. So, the idea was to post the API and get the first response. Then, make use of the lastItemRef key value from the 15th item of the first response and use this value as a query parameter and create the URL to be posted for the second response.
It was required to combine the two results from the API calls. A clue that was given to the participants was to convert the responses into a Python Dictionary with the json() method; then add two dictionaries together using the extend() method.
This is where I got stuck 😕 and couldn't get past this task on the Day 1. I slept over this problem and was able to fare better on the Day 2.
Hacking through the tasks for Day 2
Task 3a (continued):
{
"data": {
"returnCode": 0,
"responseMessage": "+15 ITEMS RETURNED",
"inquireCatalog": {
"startItemRef": 10,
"lastItemRef": 150,
"items": [
{
"itemRef": 10,
"cost": "089.90",
"onOrder": 0,
"description": "Man's Waterproof Rain Jacket",
"department": 10,
"stock": 989
},
{
"itemRef": 20,
"cost": "089.90",
"onOrder": 99,
"description": "Women Waterproof Rain Jacket",
"department": 10,
"stock": 996
},
{
"itemRef": 30,
"cost": "040.90",
"onOrder": 0,
"description": "Sunglasses",
"department": 10,
"stock": 992
},
{
"itemRef": 40,
"cost": "079.90",
"onOrder": 0,
"description": "Windy Umbrella",
"department": 10,
"stock": 996
},
{
"itemRef": 50,
"cost": "004.99",
"onOrder": 0,
"description": "Hot Coffee",
"department": 10,
"stock": 990
},
{
"itemRef": 60,
"cost": "004.99",
"onOrder": 40,
"description": "Hot Chocolate",
"department": 10,
"stock": 999
},
{
"itemRef": 70,
"cost": "049.99",
"onOrder": 20,
"description": "Woman swim suit with fancy colors",
"department": 10,
"stock": 992
},
{
"itemRef": 80,
"cost": "049.99",
"onOrder": 0,
"description": "Man's swim suit also with fancy colors",
"department": 10,
"stock": 998
},
{
"itemRef": 90,
"cost": "019.99",
"onOrder": 0,
"description": "Thermoflask double stainless steel",
"department": 10,
"stock": 996
},
{
"itemRef": 100,
"cost": "009.90",
"onOrder": 20,
"description": "Icecream Family Pack",
"department": 10,
"stock": 994
},
{
"itemRef": 110,
"cost": "004.40",
"onOrder": 0,
"description": "Iced Tea",
"department": 10,
"stock": 995
},
{
"itemRef": 120,
"cost": "025.99",
"onOrder": 0,
"description": "Mineral Sunscreen",
"department": 10,
"stock": 997
},
{
"itemRef": 130,
"cost": "014.85",
"onOrder": 0,
"description": "Rain Cap Size Small",
"department": 10,
"stock": 998
},
{
"itemRef": 140,
"cost": "014.85",
"onOrder": 0,
"description": "Rain Cap Size Medium",
"department": 10,
"stock": 999
},
{
"itemRef": 150,
"cost": "014.85",
"onOrder": 45,
"description": "Rain Cap Size Large",
"department": 10,
"stock": 996
}
]
}
}
}
💡 Python Dictionaries store data values in key:value pair and are written with Curly braces.
💡 Python Lists are created using square brackets and are used to store multiple items in a single variable.
Discord came as savior 🙏. I posted this issue there and the organizers quickly helped me understand that most of the info from the Dictionary won't be used besides to make sure the request went well and the focus should be only on the Python List with the details of the items in the Catalog.
I created a new file named as webRequestHandler.py under the webApp directory and wrote the following code to get the result needed to mark this task as complete ✅.
I've added comments to each line of the code for your understanding. Still, I would like to highlight few sections of the code.
Line #13 is used to create a Python dictionary called header which stores the authentication token given by the Organizers of Hackathon. Requests to the back-end systems only with this Auth token are deemed as legal. Without the Auth token, we will not be able to send/post API's and get the responses from the back-end systems.
This 👇 is what happened after running this Python script.
Excellent work Srinivas,
ReplyDeleteIncredible coverage of this event. It was a pleasure hosting you as one of the participants. Looking forward to part 2 and even more content from you, Srivinas!
ReplyDelete