<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Meenakshi</title>
    <description>The latest articles on DEV Community by Meenakshi (@meenakshidhanani).</description>
    <link>https://dev.to/meenakshidhanani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F299414%2Fd0fc5816-e5ed-4264-baec-85cf5b58628e.jpeg</url>
      <title>DEV Community: Meenakshi</title>
      <link>https://dev.to/meenakshidhanani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meenakshidhanani"/>
    <language>en</language>
    <item>
      <title>COVID-19 Vaccines in India: How to Build an API-based Vaccine Locator with Postman</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Tue, 11 May 2021 19:15:57 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/covid-19-vaccines-in-india-how-to-build-an-api-based-vaccine-locator-with-postman-5fgk</link>
      <guid>https://dev.to/meenakshidhanani/covid-19-vaccines-in-india-how-to-build-an-api-based-vaccine-locator-with-postman-5fgk</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f_5YRjR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AwVP9lguvy5893HqW" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f_5YRjR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AwVP9lguvy5893HqW" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@hannahbusing?utm_source=medium&amp;amp;utm_medium=referral"&gt;Hannah Busing&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.cowin.gov.in/home"&gt;Co-Win portal&lt;/a&gt; is a critical website for India at this time, allowing Indians to register and schedule vaccinations against COVID-19 (please note that the portal may lead to a 403 Forbidden error if you’re not in India), and it has published the &lt;a href="https://apisetu.gov.in/public/marketplace/api/cowin"&gt;Co-Win APIs&lt;/a&gt;. Since the population of India is so large and the situation is extremely tense right now, the available vaccination slots get booked in seconds. During the initial days of the vaccine, Postman Chief Software Architect &lt;a href="https://blog.postman.com/author/shamasis/"&gt;Shamasis Bhattacharya&lt;/a&gt; and Postman Software Engineer Intern Himanshu Sharma used the Postman &lt;a href="https://learning.postman.com/docs/running-collections/intro-to-collection-runs/"&gt;Collection Runner&lt;/a&gt; to receive alerts on the availability of vaccines in their respective areas—and they managed to get vaccinated. Though the portal’s traffic has increased considerably since, and getting a vaccine appointment has become more difficult, we still think that automating updates when a resource is available is especially useful during the pandemic. We hope you can apply this approach to other helpful APIs in addition to the Co-Win API used in this tutorial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;We wanted to share the Postman Collections, monitors, and APIs used by our Postmanauts to configure alerts and visualize available vaccines, so we created a &lt;a href="https://blog.postman.com/public-workspaces-why-we-created-them-what-you-can-do/"&gt;public workspace&lt;/a&gt; for anyone to access. The new &lt;a href="https://www.postman.com/postman/workspace/covid-19-vaccine-locator-india/overview"&gt;COVID-19 Vaccine Locator India&lt;/a&gt; public workspace contains collections that allow you to receive updates based on configurable parameters, including age limit, vaccine type, and the number of vaccinations required. You can fork the collections you find useful to receive alerts on Slack and Telegram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E87I00im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AJZo7ke2h0NoZ99BM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E87I00im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AJZo7ke2h0NoZ99BM.png" alt=""&gt;&lt;/a&gt;&lt;em&gt;COVID-19 Vaccine Locator India public workspace Overview page&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure alerts
&lt;/h3&gt;

&lt;p&gt;The Co-Win 2-week Alert collection and the Co-Win n-day Alert collections are useful for receiving alerts once the vaccines are available. The respective collection documentation explains the difference between the two and their filtering criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Co-Win 2-week Alert sends alerts for vaccines available in the next two weeks&lt;/li&gt;
&lt;li&gt;Co-Win n-day Alert sends alerts for vaccines available in the next n days&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to configure alerts, fork the collection and the Co-Win environment. Once forked, you need to run the collection at regular intervals in order to receive regular alerts. This can be done in three ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Configure alerts via the Postman Collection Runner
&lt;/h3&gt;

&lt;p&gt;The Postman &lt;a href="https://learning.postman.com/docs/running-collections/intro-to-collection-runs/"&gt;Collection Runner&lt;/a&gt; lets you run a collection by specifying a delay in milliseconds between collection runs. This is recommended because you can set the smallest delay between runs which would enable you to get notified quicker if vaccination is available. Since Postman the Co-Win API may return a 403 Forbidden for a client other than India, be sure to not select the Cloud Agent, instead choose the &lt;a href="https://blog.postman.com/introducing-the-postman-agent-send-api-requests-from-your-browser-without-limits/"&gt;Desktop agent&lt;/a&gt; if you are using the web version. Please Note: Requests fired from the desktop will only work for clients in India.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vuiVPL_J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APilkFxJaLvCiyMv1A4oxnA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vuiVPL_J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APilkFxJaLvCiyMv1A4oxnA.gif" alt=""&gt;&lt;/a&gt;&lt;em&gt;Running a collection via the Collection Runner&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The only downside to this approach is that you will have to keep your machine running the entire time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Configure alerts via Postman CLI: Newman
&lt;/h3&gt;

&lt;p&gt;Postman monitors run requests on Postman servers, where the Co-Win API may return a 403 Forbidden since these APIs only work for clients in India. Even though Postman monitors allow us to &lt;a href="https://learning.postman.com/docs/designing-and-developing-your-api/monitoring-your-api/intro-monitors/#multi-region-monitoring"&gt;configure regions&lt;/a&gt;, the closest region we can get is the Asia Pacific but not specifically India. In that case, we can still reuse all the code in the collections and the environment by running it locally/remotely (on a server in India) using &lt;a href="https://www.npmjs.com/package/newman"&gt;Newman&lt;/a&gt;. Since the collections run on a remote server we need not keep the machine running all day as opposed to the previous approach using the Collection Runner.&lt;/p&gt;

&lt;p&gt;In order to use Newman, you need to first install it locally or on any other environment (you can try &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/scheduling_tasks.html"&gt;AWS ECS scheduled task&lt;/a&gt;, &lt;a href="https://cloud.google.com/appengine/docs/flexible/nodejs/scheduling-jobs-with-cron-yaml"&gt;Google’s App Engine Cron Service&lt;/a&gt;). Once installed, to run the collection referencing the environment, either export the collection or find the collection URL. Using the URL directly is far more convenient because then you can modify the collection in Postman and without exporting expect to see that change reflected whenever Newman runs.&lt;/p&gt;

&lt;p&gt;To find the URL for a collection/environment in your personal workspace, you will need the &lt;a href="https://learning.postman.com/docs/developer/intro-api/#generating-a-postman-api-key"&gt;Postman API Key&lt;/a&gt;. The API token can be used to fetch a collection or environment using the &lt;a href="https://www.postman.com/postman/workspace/postman-public-workspace/documentation/12959542-c8142d51-e97c-46b6-bd77-52bb66712c9a"&gt;Postman API&lt;/a&gt; by using these formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;newman run "https://api.getpostman.com/collections/$collection_uuid?apikey=$apikey" --environment "https://api.getpostman.com/environments/$environment_uuid?apikey=$apikey"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Set the environment variable values to the initial value you prefer. Newman only picks up the initial value defined in the environment, since the current value doesn’t get synced to the Postman server.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Configure alerts via monitors
&lt;/h3&gt;

&lt;p&gt;Click on the “Monitors” tab on the left, and create the monitor. Select Co-Win as the environment and the collection to monitor. Configure how often you want the monitor to run. For every subsequent run, the monitor will find vaccines matching above mentioned criteria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Set the environment variable values to the initial value you prefer. Monitors only pick up the initial value defined in the environment, since the current value doesn’t get synced to the Postman server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qC_Mqp4y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AF4MA2BfiNCJiYHC_jL4Qhw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qC_Mqp4y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AF4MA2BfiNCJiYHC_jL4Qhw.gif" alt=""&gt;&lt;/a&gt;&lt;em&gt;Creating a Postman monitor&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Receive Slack and Telegram alerts
&lt;/h3&gt;

&lt;p&gt;In order to receive alerts on Slack or Telegram, you need to provide some details (i.e., an auth token/key) or configure a webhook, bot, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set up a Slack webhook
&lt;/h3&gt;

&lt;p&gt;To send an alert on a Slack channel, we need to configure an &lt;a href="https://slack.com/intl/en-in/help/articles/115005265063-Incoming-webhooks-for-Slack"&gt;incoming webhook for Slack&lt;/a&gt;. Once the incoming webhook is set up, you can copy the webhook URL and set the environment variable slack_hook to that value.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set up a Telegram Bot
&lt;/h3&gt;

&lt;p&gt;To send an alert to Telegram, you can create a Telegram bot by sending a text to BotFather. Read &lt;a href="https://core.telegram.org/bots#6-botfather"&gt;How to create a Telegram bot?&lt;/a&gt; to learn how to receive a bot API token. Set the environment variable telegram_token to the token received. Next, we need a chat ID to send the text message to the bot. To obtain the chat_id, type a message in the custom bot chat and send. Now, hit the following API to get the chat_id in the response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://api.telegram.org/bot%7B%7Btelegram_token%7D%7D/getUpdates"&gt;https://api.telegram.org/bot&lt;code&gt;{{telegram_token}}&lt;/code&gt;/getUpdates&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the chat_id received to the environment variable telegram_chat_id_._&lt;/p&gt;

&lt;h3&gt;
  
  
  How to test existing collection workflows
&lt;/h3&gt;

&lt;p&gt;There is a fair bit of logic involved in the tests and the pre-request script for each of the requests. You’ll need to do some filtering and merging based on the criteria defined in the environment. The goal of these collections is for anyone to not only receive alerts but also be able to customize certain conditions based on their requirements. For that, the code needs to be maintainable. As a user, you don’t want to break existing functionality while modifying or adding certain filters. Since hitting the actual Co-Win API for testing isn’t feasible, especially because the server could be down sometimes due to traffic or geo-locks, we created a &lt;a href="https://www.postman.com/postman/workspace/covid-19-vaccine-locator-india/mock/9d443558-4ba5-457d-8095-6c8a44c3424b"&gt;mock server&lt;/a&gt; by importing the &lt;a href="https://www.postman.com/postman/workspace/covid-vaccine-locator-india/api/2303108c-7639-47d3-91e1-912d084a576d?version=5fc36176-d083-45cb-94f5-0b8c621d6ff1&amp;amp;tab=overview"&gt;OpenAPI definition for Co-Win API&lt;/a&gt;. The &lt;a href="https://www.postman.com/postman/workspace/covid-vaccine-locator-india/collection/13059338-762a2e4b-3729-48e7-9cd5-24246132580f?ctx=documentation"&gt;Co-Win API collection&lt;/a&gt; is the source of truth for the mock server. Any example added to a request should reflect in the mock server behavior.&lt;/p&gt;

&lt;p&gt;In order to test the collection, you need to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch the base_url to point to the mock_url in the environment&lt;/li&gt;
&lt;li&gt;The pre-request script of both collections-Co-Win 2-week Alert as well as Co-Win n-day Alert-have request IDs listed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P1d6Rq0x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/900/0%2AzLnKURAWqzE7XPTc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P1d6Rq0x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/900/0%2AzLnKURAWqzE7XPTc.png" alt=""&gt;&lt;/a&gt;&lt;em&gt;Pre-request script of collections to target the mock server&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How does the pre-request script test for different scenarios?
&lt;/h3&gt;

&lt;p&gt;The pre-request script adds a universally unique identifier (UUID) to the x-mock-response-id header. This will make sure that the mock server always returns the example response matching the path and the UUID requested in the header. Since we have the success example UUID uncommented, the mock server will return only the success response each time, and we can run the collection and test if all the logic in the scripts performs as expected for a success scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should you use to run the collection while testing?
&lt;/h3&gt;

&lt;p&gt;Postman’s &lt;a href="https://learning.postman.com/docs/running-collections/intro-to-collection-runs/"&gt;Collection Runner&lt;/a&gt;, unlike a monitor, will point to the current value in the environment and can work on the &lt;a href="https://blog.postman.com/introducing-the-postman-agent-send-api-requests-from-your-browser-without-limits/"&gt;Postman desktop agent&lt;/a&gt; which means you may not receive a 403 Forbidden because of the geo-lock while hitting the Co-Win API and you can use the same runner against the mock server by modifying the base_url current value.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to contribute to this public workspace
&lt;/h3&gt;

&lt;p&gt;There are multiple ways you can contribute to the important work of the COVID-19 Vaccine Locator India public workspace or any other public workspace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add collections alerting for different use cases&lt;/li&gt;
&lt;li&gt;Add alerts for other products/platforms (Whatsapp, Messenger, etc.)&lt;/li&gt;
&lt;li&gt;Separate out the testing via mock server logic from pre-request to a different collection to enable ease of use&lt;/li&gt;
&lt;li&gt;Add more visualizations&lt;/li&gt;
&lt;li&gt;Add &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/commenting-on-collections/"&gt;comments&lt;/a&gt; wherever helpful&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can fork an existing collection and make changes to experiment with different options. Once complete, raise a &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/#creating-pull-requests"&gt;pull request&lt;/a&gt; to the collection in the workspace. To contribute by adding a new collection to the COVID-19 Vaccine Locator India workspace, fork the CONTRIBUTIONS collection and raise a pull request against it.&lt;/p&gt;

&lt;p&gt;It is a critical time to band together and apply all of our technical proficiency in order to discover new ways to fight the pandemic. We hope this approach inspires you to build automated solutions to ease the process when constantly waiting for resources-whether now or for future circumstances.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.postman.com/how-to-build-an-api-based-covid-19-vaccine-locator/"&gt;&lt;em&gt;https://blog.postman.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on May 11, 2021.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>covid19</category>
      <category>postman</category>
      <category>webhooks</category>
    </item>
    <item>
      <title>Problem: Spreadsheets. Solution: Specifications</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Mon, 10 May 2021 13:47:34 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/problem-spreadsheets-solution-specifications-1djp</link>
      <guid>https://dev.to/meenakshidhanani/problem-spreadsheets-solution-specifications-1djp</guid>
      <description>&lt;p&gt;This is a story inspired by true events, about a team and the everyday struggles they faced while building an API defined by spreadsheets and documents. What can come to the rescue in such a scenario? API specifications.&lt;/p&gt;

&lt;h2&gt;In analysis&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u9kn1FzK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u9kn1FzK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image1-1.png" alt="A business analyst and a developer may have different objectives and perspectives"&gt;&lt;/a&gt;A business analyst and a developer may have different objectives and perspectives&lt;/p&gt;

&lt;p&gt;Here’s an example of a conversation that you may have been part of sometime in your life as a developer.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Business Analyst&lt;/b&gt;: Our next user story involves creating an API (let’s call it “Customer API”).&lt;br&gt;
&lt;b&gt;Developer A&lt;/b&gt;: How novel! That’s what I did yesterday and the day before and the day before that.&lt;br&gt;
&lt;b&gt;Business Analyst&lt;/b&gt;: Great, should I let the clients know that it wouldn’t take as long to build it?&lt;br&gt;
&lt;b&gt;Developer A&lt;/b&gt;: Hold on. We haven’t even heard the requirements for Customer API.&lt;br&gt;
&lt;b&gt;Business Analyst&lt;/b&gt;: It’s just a couple of hundred fields that Customer API needs to send to another downstream API to perform the transaction.&lt;br&gt;
&lt;b&gt;Developer A&lt;/b&gt;: And how will we know the values for these fields that Customer API needs to send?&lt;br&gt;
&lt;b&gt;Business Analyst&lt;/b&gt;: I’ll take care of it. I have already spoken to the lead developer from the downstream API team, and he’s sent me a spreadsheet. It has all the fields and the values that need to be part of the request body. He’s also sent me a document with information on the headers and auth details required to call the downstream API.&lt;br&gt;
&lt;b&gt;Developer A&lt;/b&gt;: Is this downstream API available in a testing environment? A playground, maybe?&lt;br&gt;
&lt;b&gt;Business Analyst&lt;/b&gt;: They’re still working on building the downstream API, so they don’t have a working version yet.&lt;/p&gt;

&lt;h2&gt;In development&lt;/h2&gt;

&lt;p&gt;Developer A gets to work. She pairs with Developer B, another application developer on her team, to finish the Customer API story. Business Analyst sends them an email with a spreadsheet containing the fields and a document that includes the API currently in development by the downstream API team. It seems like Developer A and Developer B have all the information required to start building the Customer API, so they come up with the following list of tasks:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Create the Customer Request model that has all the fields from the spreadsheet.&lt;/li&gt;
    &lt;li&gt;Fill the model with default values.&lt;/li&gt;
    &lt;li&gt;Build the Customer API that will use this model as part of the request body.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Seems straightforward. That’s what Developer A and Developer B felt too. Let's see what happened.&lt;/p&gt;

&lt;h2&gt;In the soup&lt;/h2&gt;

&lt;p&gt;When Developer A and Developer B scanned the spreadsheet, it didn’t have a hundred fields (as Business Analyst said) but 300 fields. Did that slow them down? Yes, it did.&lt;/p&gt;

&lt;p&gt;Let’s look at some of the challenges they faced and what they did.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;How did Developer A and Developer B convert fields from the spreadsheet to data members of a class?&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Developer B started by showing off some editing skills in his favorite integrated development environment (IDE). To be fair, he recently acquired these skills from another developer last week. Now was his chance to shine. He simply showed Developer A how to paste the fields from the spreadsheet to the class file and some shortcuts on the IDE to clean the copy/paste bit and replace it with Kotlin (the language they used) syntax for a class.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;How did they assign the values to the fields? &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Not all fields had default values, so assigning defaults to specific fields became a manual process for them, which of course took a while and some patience to complete.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Why are we saying they were in the soup?&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Because here’s what happened over the course of the project. Integration failed due to:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Incorrectly spelled fields&lt;/li&gt;
    &lt;li&gt;Case sensitive fields&lt;/li&gt;
    &lt;li&gt;Mismatched data types: Some fields were represented as Boolean when they were actually Strings&lt;/li&gt;
    &lt;li&gt;Error parsing issues, since the document misrepresented it&lt;/li&gt;
    &lt;li&gt;Missing responses (200 OK even) for some paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BBUi2Mak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BBUi2Mak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image2.png" alt="A developer can feel in the soup due to integration failure"&gt;&lt;/a&gt;A developer can feel in the soup due to integration failure&lt;/p&gt;

&lt;h2&gt;In retrospect&lt;/h2&gt;

&lt;p&gt;I relate to the character of Developer A in this scenario so much, because these are issues that my team has faced. For us, the problems kept popping up frequently, and the integration took a couple of months. I always wondered if there was a better way to communicate—or a process to spend less time on—the issues we faced. Fast-forward to today, and I am glad to report that I’m now fairly acquainted with API specifications.&lt;/p&gt;

&lt;h2&gt;What are API specifications, and why use them?&lt;/h2&gt;

&lt;p&gt;A spreadsheet (or a doc) may be tempting to use because it doesn’t come with a lot of rules, but a specification has the same benefit plus more. Here are a few reasons why I’ve become an advocate of specifications (like the &lt;a href="https://blog.postman.com/openapi-specification-postman-how-to/"&gt;OpenAPI Specification&lt;/a&gt;):&lt;/p&gt;

&lt;h3&gt;Conformance to a format&lt;/h3&gt;

&lt;p&gt;Specifications have a format, and the format could be JSON/YAML, which is much closer to an API than plain text. Examples of APIs and their formats:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://www.postman.com/twilio/workspace/twilio-api/api/d4f6010f-a731-4741-bcff-fd88640a9036?version=03c17ae1-c0ed-4a51-8763-67a858cda324&amp;amp;tab=overview"&gt;Twilio Messaging API&lt;/a&gt;: Defined in JSON format&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.postman.com/postman/workspace/postman-public-workspace/api/f00b3236-8241-43ce-925f-80f6f73f8ffc?version=26b1363e-2b53-4ec3-85b2-21ae480c86fe&amp;amp;tab=overview"&gt;Postman API&lt;/a&gt;: Defined in YAML format&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Schema objects&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://spec.openapis.org/oas/v3.1.0#schema-object"&gt;Schema objects&lt;/a&gt; can be defined, and that would resolve the error response parsing issues we faced earlier. Below is an example of a defined schema object.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://www.postman.com/dolbyio/workspace/dolby-io-public-workspace/api/1836eb91-6406-4783-a683-ed7d7685560b?version=475ae55d-7eb0-4609-b6cd-96c9ece9002b&amp;amp;tab=define"&gt;Dolby Media Analyze OpenAPI&lt;/a&gt;, &lt;code&gt;RequestError&lt;/code&gt; is a schema object defined as follows:&lt;/p&gt;

&lt;pre&gt;RequestError:     
     type: object     
     properties:       
       type:         
         description: A URL that uniquely identifies the problem type.         
         type: string         
         example: "/problem/validation-error"       
     title:         
       description: A human readable description of the error.         
       type: string         
       example: "Your request parameters didn't validate"       
     status:         
       description: The HTTP response code.         
       type: number         
       example: 400       
     instance:         
       description: The URL of the call for which the error occurred.         
       type: string         
       example: "/media/analyze"       
     detail:         
       description: An optional field with more information depending on the type.         
       type: string         
       example: "job_id is required"&lt;/pre&gt;

&lt;h3&gt;Schema validations&lt;/h3&gt;

&lt;p&gt;Validations on the specification ensure that at least one successful response is defined for a path. In addition, there are a lot of other validations on the schema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z75A7JyY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image3-1-1024x512.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z75A7JyY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/04/image3-1-1024x512.png" alt="Discourse API (Validation Errors Example) demonstrating validation errors"&gt;&lt;/a&gt;Discourse API (Validation Errors Example) demonstrating validation errors&lt;/p&gt;

&lt;p&gt;The above screenshot displays validation errors found in the schema. Dive right into the &lt;a href="https://www.postman.com/postman/workspace/postman-blog/api/20e74ed8-66d2-497d-ba01-db5360c0131d?version=9a08a555-2fdc-4a06-bc77-45e120f9960b&amp;amp;tab=define"&gt;Discourse API (Validation Errors Example)&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h3&gt;Tooling&lt;/h3&gt;

&lt;p&gt;Specifications are supported by extensive &lt;a href="https://openapi.tools/"&gt;tooling&lt;/a&gt;—like code generators, mock servers, documentation, etc. Leverage the tooling available in Postman by following the detailed walkthrough &lt;a href="https://learning.postman.com/docs/designing-and-developing-your-api/the-api-workflow/#developing-an-api"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Helpful API blueprints&lt;/h2&gt;

&lt;p&gt;API specifications are a blueprint for APIs, providing a huge help by describing the structure of the API. Read Postman Chief Evangelist &lt;a href="https://blog.postman.com/author/kinlane/"&gt;Kin Lane&lt;/a&gt;’s &lt;a href="https://apievangelist.com/2020/11/23/a-high-level-look-at-api-specifications/"&gt;blog post&lt;/a&gt; to get a high-level view of API specifications currently available.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spreadsheets served us well in the information age, but as enterprise organizations wrestle with their digital transformation, they are realizing they need a much more precise set of human- and machine-readable tools that can track the exponentially increasing data being produced each day. Specifications now help teams keep up with the perpetual pace of change and remain competitive in today’s ever-evolving and shifting digital landscape.&lt;br&gt;
— &lt;em&gt;Postman Chief Evangelist Kin Lane&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To get started, you can define the API schema in Postman using the &lt;a href="https://learning.postman.com/docs/designing-and-developing-your-api/the-api-workflow/"&gt;API Builder&lt;/a&gt;. Share your experiences with and without specifications, and then give us your feedback by leaving a comment below.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>openapi</category>
      <category>postman</category>
      <category>schema</category>
    </item>
    <item>
      <title>Postman Game on: How I Got 346 Collection Forks in One Day</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Fri, 09 Apr 2021 15:55:31 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/postman-game-on-how-i-got-346-collection-forks-in-one-day-jbp</link>
      <guid>https://dev.to/meenakshidhanani/postman-game-on-how-i-got-346-collection-forks-in-one-day-jbp</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.postman.com/postman/workspace/postman-games/documentation/13059338-c3e32cda-40a2-4ea3-a521-3109c720af80"&gt;Postman Games&lt;/a&gt; challenge is a new &lt;a href="https://blog.postman.com/public-workspaces-why-we-created-them-what-you-can-do/"&gt;public workspace&lt;/a&gt; that contains a series of requests that you send to receive trivia questions—all as a fun way to test your Postman IQ. We published the workspace at the &lt;a href="https://www.postman.com/postman-galaxy/"&gt;Postman Galaxy&lt;/a&gt; global conference this February, and within just one day, the GET Your Postman Game On! collection received more than 300 forks and two pull requests. The game became a popular topic for discussion among event attendees and proved to be a fun way to break the ice at a virtual conference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YBNeO4AE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/03/image1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YBNeO4AE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/03/image1-1.png" alt="Test your Postman IQ with the Postman Games public workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our success with this game can easily be repeated and applied to any developer community, conference, or meetup. So I encourage you to play it yourself and then have a go at recreating the challenge in Postman by following these tips:&lt;/p&gt;

&lt;h3&gt;1. Make it visually appealing&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://learning.postman.com/docs/sending-requests/visualizer/"&gt;Postman Visualizer&lt;/a&gt; can come in handy to visualize API responses. We used it to render the crossword and word search games in Postman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JU1gWHIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/03/image2-1024x503.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JU1gWHIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2021/03/image2-1024x503.png" alt="Crossword Puzzle in the Postman Games public workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;2. &lt;b&gt;Collaborate for feedback&lt;/b&gt;
&lt;/h3&gt;

&lt;p&gt;Once you have the collection all set, I recommend sharing the workspace with a private audience for testing. I initially invited just a few Postmanauts to try the quiz by &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/#forking-a-collection"&gt;forking the collection&lt;/a&gt;. Early collaborative testing helped collect feedback on the questions, possible answers, and the overall experience. On a personal note, it was a great opportunity to collaborate with so many Postmanauts and build something together.&lt;/p&gt;

&lt;h3&gt;3. &lt;b&gt;Share your collection in a public workspace&lt;/b&gt;
&lt;/h3&gt;

&lt;p&gt;Right before your event (after you’ve incorporated all the feedback to optimize your collection), switch your workspace visibility from Team to Public. The &lt;a href="https://blog.postman.com/public-workspaces-why-we-created-them-what-you-can-do/"&gt;public workspace&lt;/a&gt; enables anyone with a Postman account to fork the collection. You can track how popular your collection is by watching the number of forks it has. Be sure to spread the word and share the link to see an upward trend of forks.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Pro tip:&lt;/b&gt; If the challenge leads to a prize, you’re much more likely to see an increase in the forks.&lt;/p&gt;

&lt;h3&gt;4. &lt;b&gt;Don’t worry about perfecting it&lt;/b&gt;
&lt;/h3&gt;

&lt;p&gt;There were a few issues with the Postman game challenge on the day of the event. While that had me nervous at first, the good part was that it led to a wider scope for contribution. During the conference, a few attendees even raised &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/#creating-pull-requests"&gt;pull requests&lt;/a&gt; with certain fixes (e.g., correcting misspelled words and improving usability) and we merged them to the source. At the end of the day, it’s more about building a community than coming up with a perfect solution.&lt;/p&gt;

&lt;h2&gt;Let the games begin&lt;/h2&gt;

&lt;p&gt;Help us improve the challenge by contributing to the &lt;a href="https://www.postman.com/postman/workspace/postman-games/documentation/13059338-c3e32cda-40a2-4ea3-a521-3109c720af80"&gt;Postman Games&lt;/a&gt; public workspace. Also, check out the &lt;a href="https://github.com/postmanlabs/postman-quiz"&gt;postman-quiz Github repository&lt;/a&gt; that includes the source code and all the help you’ll need to recreate the quiz with a different topic. Above all, don’t forget to have fun in the process.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://blog.postman.com/postman-games-public-workspace/"&gt;https://blog.postman.com/postman-games-public-workspace/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postman</category>
      <category>conference</category>
      <category>community</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Guidelines for Java code review</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Thu, 01 Apr 2021 07:30:00 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/guidelines-for-java-code-review-4ebo</link>
      <guid>https://dev.to/meenakshidhanani/guidelines-for-java-code-review-4ebo</guid>
      <description>&lt;p&gt;Tips for Java developers to get a jumpstart on reviewing code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fB7Z0aW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AAVG9-XVvHnOXgIF1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fB7Z0aW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AAVG9-XVvHnOXgIF1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having another pair of eyes scan your code is always useful and helps you spot mistakes before you break production. You need not be an expert to review someone’s code. Some experience with the programming language and a review checklist should help you get started. We’ve put together a list of things you should keep in mind when you’re reviewing Java code. Read on!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Follow Java code conventions
&lt;/h3&gt;

&lt;p&gt;Following language conventions helps quickly skim through the code and make sense of it, thereby improving readability. For instance, all package names in Java are written in lowercase, constants in all caps, variable names in CamelCase, etc. Find the complete list of conventions &lt;a href="https://www.oracle.com/technetwork/java/codeconventions-150003.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some teams develop their own conventions, so be flexible in such cases!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Replace imperative code with lambdas and streams
&lt;/h3&gt;

&lt;p&gt;If you’re using Java 8+, replacing loops and extremely verbose methods with streams and lambdas makes the code look cleaner. &lt;a href="https://medium.com/javarevisited/7-best-java-tutorials-and-books-to-learn-lambda-expression-and-stream-api-and-other-features-3083e6038e14?source=---------14------------------"&gt;Lambdas&lt;/a&gt;and &lt;a href="https://medium.com/javarevisited/7-best-java-collections-and-stream-api-courses-for-beginners-in-2020-3ad18d52c38"&gt;streams&lt;/a&gt;allow you to write functional code in Java. The following snippet filters odd numbers in the traditional imperative way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List **&amp;lt;** Integer **&amp;gt;** oddNumbers **=**  **new** ArrayList**&amp;lt;&amp;gt;();**
 **for** **(**Integer number **:** Arrays **.** asList**(**1 **,** 2 **,** 3 **,** 4 **,** 5 **,** 6**))**  **{**
    **if** **(**number **%** 2 **!=** 0**)**  **{**
      oddNumbers **.** add**(**number**);**
  **}**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the functional way of &lt;a href="http://javarevisited.blogspot.sg/2013/04/how-to-check-if-number-is-even-or-odd.html#axzz59AWpr6cb"&gt;filtering odd numbers&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List **&amp;lt;** Integer **&amp;gt;** oddNumbers **=** Stream **.** of**(**1 **,** 2 **,** 3 **,** 4 **,** 5 **,** 6**)**
  **.** filter**(**number **-&amp;gt;** number **%** 2 **!=** 0**)**
  **.** collect**(**Collectors **.** toList**());**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Beware of the NullPointerException
&lt;/h3&gt;

&lt;p&gt;When writing new methods, try to avoid returning nulls if possible. It could lead to &lt;a href="https://javarevisited.blogspot.com/2013/05/ava-tips-and-best-practices-to-avoid-nullpointerexception-program-application.html#axzz6Kgpx2OGT"&gt;null pointer exceptions&lt;/a&gt;. In the snippet below, the highest method returns a null if the list has no integers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**class**  **Items**  **{**
    **private**  **final** List **&amp;lt;** Integer **&amp;gt;** items **;**
    **public** **Items(**List **&amp;lt;** Integer **&amp;gt;** items**)**  **{**
            **this.** items **=** items **;**
    **}**
    **public** Integer **highest()**  **{**
      **if** **(**items **.** isEmpty**())**  **return**  **null;**
      Integer highest **=**  **null;**
      **for** **(**Integer item **:** items**)**  **{**
          **if** **(**items **.** indexOf**(**item**)**  **==** 0**)** highest **=** item **;**
          **else** highest **=** highest **&amp;gt;** item **?** highest **:** item **;**
      **}**
      **return** highest **;**
    **}**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before directly calling a method on an object I recommend checking for &lt;a href="https://javarevisited.blogspot.com/2014/12/9-things-about-null-in-java.html#axzz6fLto55st"&gt;nulls&lt;/a&gt;as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Items items **=**  **new** Items**(**Collections **.** emptyList**());**
Integer item **=** items **.** highest**();**
 **boolean** isEven **=** item **%** 2 **==** 0 **;** _// throws NullPointerException ❌_  
**boolean** isEven **=** item **!=**  **null**  **&amp;amp;&amp;amp;** item **%** 2 **==** 0 _// ✅_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be pretty cumbersome to have null checks everywhere in your code though. If you are using Java 8+, consider using the Optional class to represent values that may not have valid states. It allows you to easily define alternate behavior and is useful for chaining methods.&lt;/p&gt;

&lt;p&gt;In the snippet below, we are using &lt;a href="https://javarevisited.blogspot.com/2020/04/top-5-courses-to-learn-java-collections-and-streams.html"&gt;Java Stream API&lt;/a&gt; to find the highest number with a method that returns an Optional. Note that we are using Stream.reduce, which returns an Optional value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**public** Optional **&amp;lt;** Integer **&amp;gt;** **highest()**  **{**
    **return** items
            **.** stream**()**
            **.** reduce**((**integer **,** integer2**)**  **-&amp;gt;** 
                            integer **&amp;gt;** integer2 **?** integer **:** integer2**);**
 **}**
Items items **=**  **new** Items**(**Collections **.** emptyList**());**
items **.** highest**().**ifPresent**(**integer **-&amp;gt;**  **{** _// ✅_  
    **boolean** isEven **=** integer **%** 2 **==** 0 **;**
**});**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you could also use annotations such as @Nullable or @NonNull which will result in warnings if there is a null conflict while building the code. For instance, passing a @Nullable argument to a method that accepts @NonNull parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Directly assigning references from client code to a field
&lt;/h3&gt;

&lt;p&gt;References exposed to the client code can be manipulated even if the field is final. Let’s understand this better with an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**private**  **final** List **&amp;lt;** Integer **&amp;gt;** items **;**
 **public** **Items(**List **&amp;lt;** Integer **&amp;gt;** items**)**  **{**
        **this.** items **=** items **;**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, we directly assign a reference from the client code to a field. The client can easily mutate the contents of the list and manipulate our code as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List **&amp;lt;** Integer **&amp;gt;** numbers **=**  **new** ArrayList**&amp;lt;&amp;gt;();**
Items items **=**  **new** Items**(**numbers**);**
numbers **.** add**(**1**);** _// This will change how items behaves as well_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, consider &lt;a href="https://javarevisited.blogspot.com/2013/09/how-clone-method-works-in-java.html#axzz5Y4Ks1BbR"&gt;cloning the reference&lt;/a&gt; or creating a new reference and then assigning it to the field as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**private**  **final** List **&amp;lt;** Integer **&amp;gt;** items **;**
 **public** **Items(**List **&amp;lt;** Integer **&amp;gt;** items**)**  **{**
    **this.** items **=**  **new** ArrayList**&amp;lt;&amp;gt;(**items**);**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same rule applies while returning references. You need to be cautious so as not to expose an internal mutable state.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Handle exceptions with care
&lt;/h3&gt;

&lt;p&gt;While catching exceptions, if you have multiple catch blocks, ensure that the sequence of catch blocks is most specific to least. In the snippet below, the exception will never be caught in the second block since the Exception class is the mother of all exceptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**try**  **{**
    stack **.** pop**();**
 **}**  **catch** **(**Exception exception**)**  **{**
    _// handle exception_  
**}**  **catch** **(**StackEmptyException exception**)**  **{**
    _// handle exception_  
**}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the situation is recoverable and can be handled by the client (the consumer of your library or code) then it is good to use &lt;a href="https://javarevisited.blogspot.com/2011/12/checked-vs-unchecked-exception-in-java.html"&gt;checked exceptions&lt;/a&gt;. e. g. IOException is a checked exception that forces the client to handle the scenario and in case the client chooses to re-throw the exception then it should be a conscious call to disregard the exception.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Ponder over the choice of data structures
&lt;/h3&gt;

&lt;p&gt;Java collections provide ArrayList, LinkedList, Vector, Stack, HashSet, HashMap, Hashtable. It’s important to understand the pros and cons of each to use them in the correct context. A few hints to help you make the right choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Map: Useful if you have unordered items in the form of key, value pairs and require efficient retrieval, insertion, and deletion operations. &lt;a href="https://www.java67.com/2017/08/top-10-java-hashmap-interview-questions.html"&gt;HashMap&lt;/a&gt;, Hashtable, LinkedHashMap are all implementations of the Map interface.&lt;/li&gt;
&lt;li&gt;List: Very commonly used to create an ordered list of items. This list may contain duplicates. ArrayList is an implementation of the List interface. A list can be made thread-safe using Collections.synchronizedList thus removing the need for using Vector. &lt;a href="https://javaconceptoftheday.com/not-use-vector-class-code/"&gt;Here&lt;/a&gt;’s some more info on why Vector is essentially obsolete.&lt;/li&gt;
&lt;li&gt;Set: Similar to list but does not allow duplicates. HashSet implements the Set interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Think twice before you expose
&lt;/h3&gt;

&lt;p&gt;There are quite a few access modifiers to choose from in Java — public, protected, private. Unless you want to expose a method to the client code, you might want to keep everything private by default. Once you expose an API, there’s no going back.&lt;/p&gt;

&lt;p&gt;For instance, you have a class Library that has the following method to check out a book by name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**public** **checkout(**String bookName**)**  **{**
    Book book **=** searchByTitle**(**availableBooks **,** bookName**);**
  availableBooks **.** remove**(**book**);**
  checkedOutBooks **.** add**(**book**);**
 **}**

**private** **searchByTitle(**List **&amp;lt;** Book **&amp;gt;** availableBooks **,** String bookName**)**  **{**
 **...**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not keep the searchByTitle method private by default and it ends up being exposed, other classes could start using it and building logic on top of it that you may have wanted to be part of the Library class. It could break the encapsulation of the Library class or it may be impossible to revert/modify later without breaking someone else’s code. Expose consciously!&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Code to interfaces
&lt;/h3&gt;

&lt;p&gt;If you have concrete implementations of certain interfaces (e. g. ArrayList or LinkedList) and if you use them directly in your code, then it can lead to high coupling. Sticking with the List interface enables you to switch over the implementation any time in the future without breaking any code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**public** **Bill(**Printer printer**)**  **{**
    **this.** printer **=** printer **;**
 **}**

**new** Bill**(new** ConsolePrinter**());**
 **new** Bill**(new** HTMLPrinter**());**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, using the Printer interface allows the developer to move to another concrete class HTMLPrinter.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Don’t force fit interfaces
&lt;/h3&gt;

&lt;p&gt;Take a look at the following interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**interface**  **BookService**  **{**
        List **&amp;lt;** Book **&amp;gt;** **fetchBooks();**
    **void** **saveBooks(**List **&amp;lt;** Book **&amp;gt;** books**);**
    **void** **order(**OrderDetails orderDetails**)**  **throws** BookNotFoundException **,** BookUnavailableException **;**    
**}**

**class**  **BookServiceImpl**  **implements** BookService **{**
 **...**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is there a benefit of creating such an interface? Is there a scope for this interface being implemented by another class? Is this interface generic enough to be implemented by another class? If the answer to all these questions is no, then I’d definitely recommend avoiding this unnecessary interface that you’ll have to maintain in the future. Martin Fowler explains this really well in his &lt;a href="https://martinfowler.com/bliki/InterfaceImplementationPair.html"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well then, what’s a good use case for an interface? Let’s say we have a class Rectangle and a class Circle that has behavior to calculate perimeter. If there is a requirement, to sum up, the perimeter of all shapes — a use case for polymorphism, then having the interface would make more sense, as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**interface**  **Shape**  **{**
        Double **perimeter();**
 **}**

**class**  **Rectangle**  **implements** Shape **{**
_//data members and constructors_  
    @Override
    **public** Double **perimeter()**  **{**
        **return** 2 **\*** **(this.**length **+**  **this.** breadth**);**
    **}**
 **}**

**class**  **Circle**  **implements** Shape **{**
_//data members and constructors_  
    @Override
    **public** Double **perimeter()**  **{**
        **return** 2 **\*** Math **.** PI **\*** **(this.**radius**);**
    **}**
 **}**

**public**  **double** **totalPerimeter(**List **&amp;lt;** Shape **&amp;gt;** shapes**)**  **{**
    **return** shapes **.** stream**()**
               **.** map**(**Shape **::** perimeter**)**
               **.** reduce**((**a **,** b**)**  **-&amp;gt;** Double **.** sum**(**a **,** b**))**
               **.** orElseGet**(()**  **-&amp;gt;** **(double)** 0**);**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  10. Override hashCode when overriding equals
&lt;/h3&gt;

&lt;p&gt;Objects that are equal because of their values are called &lt;a href="https://martinfowler.com/bliki/ValueObject.html"&gt;value objects&lt;/a&gt;. e. g. money, time. Such classes must override the equals method to return true if the values are the same. The &lt;a href="https://javarevisited.blogspot.com/2013/05/java-mistake-3-using-instead-of-equals.html"&gt;equals&lt;/a&gt;method is usually used by other libraries for comparison and equality checks; hence overriding equals is necessary. Each Java object also has a hash code value that differentiates it from another object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**class**  **Coin**  **{**
    **private**  **final**  **int** value **;**

    Coin**(int** value**)**  **{**
        **this.** value **=** value **;**
    **}**

    @Override
    **public**  **boolean** **equals(**Object o**)**  **{**
        **if** **(this**  **==** o**)**  **return**  **true;**
        **if** **(**o **==**  **null**  **||** getClass**()**  **!=** o **.** getClass**())**  **return**  **false;**
        Coin coin **=** **(**Coin**)** o **;**
        **return** value **==** coin **.** value **;**
    **}**
 **}**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we have overridden only the equals method of Object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HashMap **&amp;lt;** Coin **,** Integer **&amp;gt;** coinCount **=**  **new** HashMap **&amp;lt;** Coin **,** Integer**&amp;gt;()**  **{{**
  put**(new** Coin**(**1**),** 5**);**
  put**(new** Coin**(**5**),** 2**);**
 **}};**

_//update count for 1 rupee coin_  
coinCount **.** put**(new** Coin**(**1**),** 7**);**

coinCount **.** size**();** _// 3 🤯 why?_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We would expect coinCount to update the number of 1 rupee coins to 7 since we override equals. But &lt;a href="https://www.java67.com/2013/02/10-examples-of-hashmap-in-java-programming-tutorial.html"&gt;HashMap&lt;/a&gt; internally checks if the hash code for 2 objects is equal and only then proceeds to test equality via the equals method. Two different objects may or may not have the same hash code but two equal objects must always have the same hash code, as defined by the contract of the hashCode method. So checking for hash code first is an early exit condition. This implies that both equals and hashCode methods must be overridden to express equality.&lt;/p&gt;

&lt;p&gt;If you write or review Java code, DeepSource can help you with &lt;a href="https://deepsource.io/blog/code-review-best-practices/?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=javacodereview"&gt;automating the code reviews&lt;/a&gt; and save you a ton of time. Just add a .deepsource.toml file in the root of the repository and DeepSource will pick it up for scanning right away. The scan will find scope for improvements across your code and help you fix them with helpful descriptions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepsource.io/signup/?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=javacodereview"&gt;Sign up&lt;/a&gt; and see for yourself!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on&lt;/em&gt; &lt;a href="https://deepsource.io/blog/java-code-review-guidelines/?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=contentdistribution&amp;amp;utm_term=javacodereview"&gt;&lt;em&gt;DeepSource Blog&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>tech</category>
      <category>java8</category>
      <category>cleancode</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Tutorial: Intro to React Hooks</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Thu, 01 Apr 2021 07:28:23 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/tutorial-intro-to-react-hooks-1kib</link>
      <guid>https://dev.to/meenakshidhanani/tutorial-intro-to-react-hooks-1kib</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0x7dlviepqny6upgcaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0x7dlviepqny6upgcaa.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.iconbros.com/icons/ib-g-hangman" rel="noopener noreferrer"&gt;Hangman&lt;/a&gt; icon by &lt;a href="https://iconbros.com" rel="noopener noreferrer"&gt;IconBros&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tutorial assumes knowledge of React state and lifecycle concepts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Before We Start the Tutorial
&lt;/h3&gt;

&lt;p&gt;We will be building a small game in this tutorial. This is a practical way of getting accustomed to building react functional components using hooks. We will be walking through each section of this tutorial along with the code snippets so that you can follow along as you build your game. &lt;/p&gt;

&lt;p&gt;This tutorial is divided into the following sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup for the Tutorial&lt;/strong&gt; will equip you with the starter code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overview&lt;/strong&gt; will delve into the basics of hooks with some history&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building the Game&lt;/strong&gt; will use the most common hook in React development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adding a Time Limit&lt;/strong&gt; will extend the game to add a time limit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrapping Up&lt;/strong&gt; will discuss extensions and conclude&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can follow along till you build a basic version of the game to get an understanding of the hooks along with some hands-on.&lt;/p&gt;
&lt;h4&gt;
  
  
  What are We Building?
&lt;/h4&gt;

&lt;p&gt;In this tutorial, we'll build an interactive hangman game using React hooks.&lt;/p&gt;

&lt;p&gt;Hangman is a classic game in which the player has to guess a word one letter at a time. You can play to get comfortable with the game&lt;br&gt;
&lt;a href="https://www.hangmanwords.com/play" rel="noopener noreferrer"&gt;https://www.hangmanwords.com/play&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several rules that can be applied to the game to add more complexities, but we will be focussing on completing just the first iteration of the game. You are encouraged to experiment and extend this solution for more complex use cases suggested in the extensions section.&lt;/p&gt;
&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;p&gt;We'll assume you have used React before and are familiar with creating components, state management, and lifecycle methods. &lt;br&gt;
We are also using features from ES6 - arrow functions, const, let statements. You can check &lt;a href="https://babeljs.io/repl/#?presets=react&amp;amp;code_lz=MYewdgzgLgBApgGzgWzmWBeGAeAFgRgD4AJRBEAGhgHcQAnBAEwEJsB6AwgbgChRJY_KAEMAlmDh0YWRiGABXVOgB0AczhQAokiVQAQgE8AkowAUAcjogQUcwEpeAJTjDgUACIB5ALLK6aRklTRBQ0KCohMQk6Bx4gA" rel="noopener noreferrer"&gt;Babel REPL&lt;/a&gt; to understand what ES6 compiles to. &lt;br&gt;
Note, we are using hooks in this tutorial, since hooks have been introduced in React version 16.8, you would need to have 16.8 as the min. React version for this tutorial. &lt;/p&gt;
&lt;h3&gt;
  
  
  Setup for the Tutorial
&lt;/h3&gt;

&lt;p&gt;Let's get started. &lt;br&gt;
We want to first create a react app. We can either create it from scratch or use create-react-app to reduce boilerplate code. In this tutorial we'll be using &lt;a href="https://reactjs.org/docs/create-a-new-react-app.html" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app react-hangman
cd react-hangman
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet will create a React app with a simple App component. For this tutorial, we won't be focussing on styling and testing the component, so let's go ahead and delete the &lt;code&gt;App.css&lt;/code&gt; and &lt;code&gt;App.test.js&lt;/code&gt; files. Now we can simply edit the &lt;code&gt;App.js&lt;/code&gt; to include &lt;code&gt;Hangman&lt;/code&gt; component. The &lt;code&gt;Hangman.jsx&lt;/code&gt; is what we're going to focus on building in this tutorial. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import Hangman from './Hangman';

const App = () =&amp;gt; &amp;lt;Hangman /&amp;gt;

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/meenakshi-dhanani/react-hangman/commit/3df118d7a3cbf0bf63466d9ad17a2abb39ac9a23" rel="noopener noreferrer"&gt;View the full code at this point&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;Now that you're all set, let's first get an overview of React hooks.&lt;/p&gt;

&lt;h4&gt;
  
  
  What are React Hooks?
&lt;/h4&gt;

&lt;p&gt;Prior to 16.8, class components in React were used to manage state and had logic distributed across lifecycle methods. Functional components were used to extract out some common UI. With React hooks, you can now hook into your functional components state and logic that would earlier be spread across lifecycle methods. Related logic can now be in one place, instead of being split. Logic can also be shared across components by building custom hooks. &lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Game
&lt;/h3&gt;

&lt;p&gt;As part of the first iteration, we want a secret word to be displayed, let's say we mask all the letters with __ and we need all alphabets A-Z to be listed so that the player can select a letter and if that letter is part of the secret word it will reveal itself. &lt;/p&gt;

&lt;p&gt;Let's say the secret word is "HANGMAN". Then the following expression should mask the secret word as &lt;/p&gt;

&lt;p&gt;&lt;code&gt;_ _ _ _ _ _ _&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"HANGMAN".split("").fill("_").join(" ")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start with a basic layout:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Hangman.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

export default function Hangman() {
    const word = "HANGMAN";
    const alphabets = ["A", "B", "C", "D", "E", "F", "G",
        "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
        "S", "T", "U", "V", "W", "X", "Y", "Z"];

    return  &amp;lt;div&amp;gt;
            &amp;lt;p&amp;gt;{word.split("").fill("_").join(" ")}&amp;lt;/p&amp;gt;
            {alphabets
            .map((alphabet, index) =&amp;gt; 
            &amp;lt;button key={index}&amp;gt;{alphabet}&amp;lt;/button&amp;gt;)}
            &amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
At this state, if you click on the buttons no actions occur. Our next step would be to click on an alphabet and guess if the letter is a part of the word. If the letter is indeed a part of the word it would show up and if it isn't it would not reveal itself. For this, we need to persist all the letters that are correctly guessed so that they are displayed as part of the secret word. Now we have a use case for persisting data across a component re-render. This calls for the need for the state. Let's have a look at how we can infuse the state using the State hook in React.&lt;/p&gt;
&lt;h4&gt;
  
  
  The State Hook
&lt;/h4&gt;

&lt;p&gt;We can use the state hook to inject state into functional components in React. This state will be preserved across re-renders of the component. The &lt;code&gt;useState&lt;/code&gt; is a hook that we can use. The &lt;code&gt;useState&lt;/code&gt; returns a pair having the current value for the state and a function that lets you set the state. In class components, we used to do something similar with &lt;code&gt;this.setState&lt;/code&gt;. You can use multiple &lt;code&gt;useState&lt;/code&gt; in a component for different values that need to be preserved. &lt;/p&gt;

&lt;p&gt;We need to persist correctGuesses for the Hangman component. Let's use the useState hook. We modified the word to display __ for all letters not guessed yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, {useState} from 'react';

export default function Hangman() {
    const word = "HANGMAN";
    const alphabets = ["A", "B", "C", "D", "E", "F", "G",
        "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
        "S", "T", "U", "V", "W", "X", "Y", "Z"];
    const [correctGuesses, setCorrectGuesses] = useState([])    

    const maskedWord = word.split('').map(letter =&amp;gt; 
    correctGuesses.includes(letter) ? letter : "_").join(" ");

    return  &amp;lt;div&amp;gt;
            &amp;lt;p&amp;gt;{maskedWord}&amp;lt;/p&amp;gt;
            {alphabets
            .map((alphabet, index) =&amp;gt; 
            &amp;lt;button key={index} onClick={() =&amp;gt; {
                if (word.includes(alphabet)) {
                    setCorrectGuesses([...correctGuesses, alphabet])
                }
            }}&amp;gt;{alphabet}&amp;lt;/button&amp;gt;)}
            {!maskedWord.includes("_") &amp;amp;&amp;amp; &amp;lt;p&amp;gt;You won!&amp;lt;/p&amp;gt;}
            &amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding a Time Limit
&lt;/h3&gt;

&lt;p&gt;Now that we have a fair working solution, let's add some rules to this game. We'll have a max time limit of 2 minutes for the word to be guessed, if the word is not guessed within 2 minutes, we'll display "Game Over". &lt;/p&gt;

&lt;p&gt;We will need to inject a timeout in this case. The timeout will affect the results of this game. Let's look at the effect hook to understand how we can add the logic of this timeout inside our component. &lt;/p&gt;

&lt;h4&gt;
  
  
  The Effect Hook
&lt;/h4&gt;

&lt;p&gt;The effect hook is another one of the most commonly used hooks in React. It takes in a function(effect) that runs when any one of its dependant variables is changed. The effect (short for side effect) hook, is used to manage any side effects on the component - manipulating DOM elements, fetching data, subscriptions, etc. In our case, we will use the &lt;code&gt;useEffect&lt;/code&gt; to set a timeout. The &lt;code&gt;useEffect&lt;/code&gt; runs by default for every component render unless we mention &lt;code&gt;[]&lt;/code&gt; as its parameter, in which case it runs only during the first render of the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';

export default function Hangman({duration = 120000}) {
    const word = "Hangman".toUpperCase();
    const alphabets = ["A", "B", "C", "D", "E", "F", "G",
        "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
        "S", "T", "U", "V", "W", "X", "Y", "Z"];
    const [correctGuesses, setCorrectGuesses] = useState([])
    const [timeUp, setTimeUp] = useState(false);

    useEffect(() =&amp;gt; {
        const timeout = setTimeout(() =&amp;gt; {
            setTimeUp(true);
        }, duration);

        return () =&amp;gt; clearTimeout(timeout);
    }, [])


    const maskedWord = word.split('').map(letter =&amp;gt; correctGuesses.includes(letter) ? letter : "_").join(" ");
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;p&amp;gt;{maskedWord}&amp;lt;/p&amp;gt;
            {alphabets.map((alphabet, index) =&amp;gt; &amp;lt;button key={index} onClick={() =&amp;gt; {
                if (word.includes(alphabet)) {
                    setCorrectGuesses([...correctGuesses, alphabet])
                }
            }}&amp;gt;{alphabet}&amp;lt;/button&amp;gt;)}
            {timeUp ? 
            &amp;lt;p&amp;gt;You lost!&amp;lt;/p&amp;gt; : 
            !maskedWord.includes("_") &amp;amp;&amp;amp;  &amp;lt;p&amp;gt;You won!&amp;lt;/p&amp;gt;}
        &amp;lt;/div&amp;gt;
    );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we are preserving the state of timeUp using &lt;code&gt;useState&lt;/code&gt;.  In the second parameter of &lt;code&gt;useEffect&lt;/code&gt; we mention &lt;code&gt;[]&lt;/code&gt;, so the timeout is set only during the first render of Hangman. In the end, when the component unmounts since the game gets over, we clear up the effect, in &lt;code&gt;return () =&amp;gt; clearTimeout(timeout)&lt;/code&gt;. This can be used to unsubscribe, clear up resources used in the effect. &lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Congratulations! You have a hangman game that :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's you play hangman&lt;/li&gt;
&lt;li&gt;Has a time cap for you to guess&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We hope you've got a hang(pun intended) of the basic hooks. &lt;/p&gt;

&lt;p&gt;The tutorial was an attempt to get you started on react hooks. We would further encourage you to explore more hooks, eg. useContext, useHistory, create your own custom hooks. etc. Check out a detailed explanation on hooks &lt;a href="https://reactjs.org/docs/hooks-overview.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are a lot of rules that can be applied and the game can be further extended. It will be a good exercise for you to try your hand at these functional components using hooks. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Max number of guesses allowed can be 6&lt;/li&gt;
&lt;li&gt;Display time left on the timer&lt;/li&gt;
&lt;li&gt;Limiting guesses on vowels&lt;/li&gt;
&lt;li&gt;Fetch a list of words based on themes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the code sample in &lt;a href="https://github.com/meenakshi-dhanani/react-hangman" rel="noopener noreferrer"&gt;this&lt;/a&gt; repo. Feel free to write to me at &lt;a href="mailto:meena24dhanani@gmail.com"&gt;meena24dhanani@gmail.com&lt;/a&gt; for any feedback. You can also submit PRs that extend the game. &lt;/p&gt;

</description>
      <category>react</category>
      <category>reacthooks</category>
      <category>tutorial</category>
      <category>game</category>
    </item>
    <item>
      <title>Kubernetes Tutorial: Your Complete Guide to Deploying an App on AWS with Postman</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Tue, 05 Jan 2021 12:35:38 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/kubernetes-tutorial-your-complete-guide-to-deploying-an-app-on-aws-with-postman-25gj</link>
      <guid>https://dev.to/meenakshidhanani/kubernetes-tutorial-your-complete-guide-to-deploying-an-app-on-aws-with-postman-25gj</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jTBpC1s_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/kubernetes-postman.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jTBpC1s_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/kubernetes-postman.png" alt="Kubernetes tutorial: Using Postman to deploy an app on AWS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; is an open source system that is useful for container orchestration. In this tutorial, we are going to use &lt;a href="https://www.postman.com/collection/"&gt;Postman Collections&lt;/a&gt; to learn Kubernetes and use its API to deploy an app on a Kubernetes cluster hosted on &lt;a href="https://aws.amazon.com/eks/?whats-new-cards.sort-by=item.additionalFields.postDateTime&amp;amp;whats-new-cards.sort-order=desc&amp;amp;eks-blogs.sort-by=item.additionalFields.createdDate&amp;amp;eks-blogs.sort-order=desc"&gt;AWS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a hands-on tutorial. Don't fret if you aren’t familiar with Kubernetes and containerization, because we'll go over each of the following:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Prerequisites&lt;/li&gt;
    &lt;li&gt;Brief overview on containers&lt;/li&gt;
    &lt;li&gt;Kubernetes&lt;/li&gt;
    &lt;li&gt;Creating a Kubernetes cluster&lt;/li&gt;
    &lt;li&gt;Accessing the Kubernetes API from Postman&lt;/li&gt;
    &lt;li&gt;Authorizing Postman Collection&lt;/li&gt;
    &lt;li&gt;Deploy an app&lt;/li&gt;
    &lt;li&gt;Pod&lt;/li&gt;
    &lt;li&gt;Deployment&lt;/li&gt;
    &lt;li&gt;Expose your app&lt;/li&gt;
    &lt;li&gt;Service&lt;/li&gt;
    &lt;li&gt;Clean up&lt;/li&gt;
    &lt;li&gt;What next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Note: &lt;/b&gt;We will be creating the Kubernetes cluster on AWS EKS, but you can also follow the tutorial with a cluster hosted on any other cloud providers or locally using Minikube.&lt;/p&gt;

&lt;h2&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;Familiarity with &lt;a href="https://blog.postman.com/rest-api-definition/"&gt;REST APIs&lt;/a&gt; is a prerequisite. In addition you also need to do the following:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Create an &lt;a href="https://portal.aws.amazon.com/billing/signup?refid=em_127222&amp;amp;redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start"&gt;AWS account&lt;/a&gt;
&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html"&gt;Install&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html"&gt;configure&lt;/a&gt; AWS ALI to configure credentials&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://eksctl.io/introduction/#installation"&gt;Install eskctl&lt;/a&gt;,a command utility to interact and create the cluster on EKS&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/"&gt;Install kubectl&lt;/a&gt;, a command-line utility to work with Kubernetes clusters&lt;/li&gt;
    &lt;li&gt;Clone Github &lt;a href="https://github.com/meenakshi-dhanani/k8s-postman-tutorial"&gt;repository&lt;/a&gt; containing .yaml files required in upcoming sections&lt;/li&gt;
    &lt;li&gt;Create your Amazon Cluster IAM role to access the cluster&lt;/li&gt;
    &lt;li&gt;Setting up Amazon EKS cluster VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a  helpful  &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html"&gt;Amazon EKS guide&lt;/a&gt; that has all of the prerequisites mentioned above and instructions to install them.&lt;/p&gt;

&lt;p&gt;Explore this blog post in an interactive format by using our companion template. Just import the &lt;a href="https://documenter.getpostman.com/view/13059338/TVmLCyNi"&gt;&lt;b&gt;Deploy with Amazon EKS and Kubernetes API&lt;/b&gt;&lt;/a&gt; collection by clicking on &lt;b&gt;Run in Postman&lt;/b&gt; to follow this tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://god.gw.postman.com/run-collection/b64f762a9c9375e6640b#?env%5BAWS%5D=W3sia2V5Ijoia3ViZS1hcGktc2VydmVyIiwidmFsdWUiOiI8QVBJIFNlcnZlciBFbmRwb2ludD4iLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6ImF1dGgtdG9rZW4iLCJ2YWx1ZSI6IjxCZWFyZXIgVG9rZW4+IiwiZW5hYmxlZCI6dHJ1ZX1d"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V37vEqA7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://run.pstmn.io/button.svg" alt="Run in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I-qlWvhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I-qlWvhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image20.png" alt="Deploy with Amazon EKS and Kubernetes API Template "&gt;&lt;/a&gt; &lt;a href="https://documenter.getpostman.com/view/13059338/TVmLCyNi"&gt;Deploy with Amazon EKS and Kubernetes API Template &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;A brief overview of containers&lt;/h2&gt;

&lt;p&gt;Are you familiar with the “But it works on my machine” problem? A lot of times your application doesn’t perform as it does in your local environment. It may be because the production environment has different versions of the libraries, a different operating system, different system dependencies, etc. Containers provide you with a sustainable environment because your application now runs in a box (container) that includes all dependencies required by your app to run and is isolated from other applications running in other containers. They are preferred over virtual machines (VMs) since they use operating system-level virtualization and are lighter than VMs. &lt;a href="https://www.docker.com/products/container-runtime"&gt;Docker&lt;/a&gt; can be used as the container runtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3h5coPjv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3h5coPjv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image5.png" alt="Benefits of containerization"&gt;&lt;/a&gt; Benefits of containerization&lt;/p&gt;

&lt;h2&gt;Enter Kubernetes&lt;/h2&gt;

&lt;p&gt;Each app/service now runs in a container, so there can be a separation of concerns. Services don’t need to be intertwined with each other, and a microservices architecture works best with containerization. We have established why the world is moving towards containers, but who is going to manage these containers and how do you roll out a release? How do you run health checks against your services and get them back up if they are failing? Kubernetes automates all of this for you. You can easily scale up and scale down your services with Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ORYu4xer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ORYu4xer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image18.png" alt="Container orchestration in Kubernetes"&gt;&lt;/a&gt; Container orchestration in Kubernetes&lt;/p&gt;

&lt;p&gt;You can use Kubernetes anywhere for on-premise deployments or even hybrid clouds. For instance, you can have your cluster on GCE, AWS, Azure, or any cloud provider. For this Kubernetes tutorial, let's create a cluster on AWS.&lt;/p&gt;

&lt;p&gt;Read more about the benefits of containerization and container orchestration with Kubernetes &lt;a href="https://cloud.google.com/containers"&gt;here&lt;/a&gt;. This is a really enthralling space, especially for folks interested in DevOps.&lt;/p&gt;

&lt;h2&gt;Creating a Kubernetes cluster&lt;/h2&gt;

&lt;p&gt;Assuming you have followed the steps in the prerequisites section, you should have eksctl installed. Follow the steps below to create a Kubernetes cluster.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Run the following command to check if eksctl can successfully access the AWS account and list any existing clusters:&lt;/p&gt;

&lt;pre&gt;eksctl get cluster --region us-east-1&lt;/pre&gt;

&lt;p&gt;In case this command fails, you may want to make sure your credentials are set up correctly, as mentioned &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, create a cluster and assign some resources to it. The &lt;a href="https://github.com/meenakshi-dhanani/k8s-postman-tutorial/blob/main/cluster.yaml"&gt;cluster.yaml&lt;/a&gt; is present in the Github project we cloned, as mentioned in the prerequisites. You can customize the configuration for the cluster based on the resources you want to assign to your cluster. You could choose a different region, maybe add more nodes, or also a different instance type. For this tutorial, we do not need as much CPU or memory.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata: 
  name: playground 
  region: us-east-1

nodeGroups: 
  - name: ng-1 
    instanceType: t2.small 
    desiredCapacity: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;b&gt;A word of caution&lt;/b&gt;: The pricing for larger instances and more number of nodes would be more.&lt;/p&gt;

&lt;p&gt;Use the  following command to create the cluster:&lt;/p&gt;

&lt;pre&gt;eksctl create cluster -f cluster.yaml&lt;/pre&gt;

&lt;p&gt;It may take a while for the cluster to be ready. Once this command succeeds, assuming you have kubectl installed, the configuration for kubectl to access the cluster would be stored at:&lt;/p&gt;

&lt;pre&gt;~/.kube/config&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Try fetching the nodes on the cluster using kubectl. You should be able to see the two nodes if you used the cluster configuration as mentioned above.&lt;/p&gt;

&lt;pre&gt;kubectl get nodes&lt;/pre&gt;

&lt;h2&gt;Accessing the Kubernetes API from Postman&lt;/h2&gt;

&lt;p&gt;Next, we require a service account to communicate with the Kubernetes API. The service account is authorized to perform certain actions, including creating deployments and listing services by attaching it to a cluster role.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the following command to create a service account:&lt;/p&gt;

&lt;pre&gt;kubectl create serviceaccount postman&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a role definition for the service account. This role definition specifies all actions that are permitted on the resources mentioned. The &lt;a href="https://github.com/meenakshi-dhanani/k8s-postman-tutorial/blob/main/role.yaml"&gt;role.yaml&lt;/a&gt; is present in the GitHub project we cloned,  as mentioned in the prerequisites. We will look at what these resources mean and learn how to create them in the next steps.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: postman-role
rules:
- apiGroups: ["apps", ""] # "" indicates the core API group
  resources: ["pods", "services", "deployments"]
  verbs: ["get", "watch", "list", "create", "update", "delete"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to create the role:&lt;/p&gt;

&lt;pre&gt;kubectl apply -f role.yaml&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;Assign the role to the service account by creating a role-binding:
&lt;pre&gt;kubectl create rolebinding postman:postman-role --clusterrole postman-role --serviceaccount default:postman&lt;/pre&gt;
For every service account created, there is a secret token. Finally, we must extract the following from the token created for the service account:
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;API server URL&lt;/li&gt;
&lt;li&gt;Bearer Token&lt;/li&gt;
&lt;li&gt;CA Certificate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the following command to reveal the secret e.g., postman-token-9lxcc:
&lt;pre&gt;kubectl describe serviceaccount postman&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Next, we must describe the secret:
&lt;pre&gt;kubectl get secret &amp;lt;secret-token&amp;gt; -o json&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Execute the command below to reveal the ca.crt certificate and the token, that is inside a data object. We need to decode these to base64 and use them. This can be simplified using &lt;a href="https://stedolan.github.io/jq/download/"&gt;jq&lt;/a&gt; command-line utility:
&lt;pre&gt;# Extract the token from the Secret and decode
TOKEN=$(kubectl get secret &amp;lt;secret-token&amp;gt; -o json | jq -Mr '.data.token' | base64 -d)&lt;/pre&gt;
&lt;pre&gt;# Extract, decode and write the ca.crt to a file
kubectl get secret &amp;lt;secret-token&amp;gt; -o json | jq -Mr '.data["ca.crt"]' | base64 -d &amp;gt; ca.crt&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;You must get the API server URL from Amazon EKS. If you log in to your Amazon account and see the cluster details for the playground cluster we created, you should find an &lt;b&gt;API server endpoint&lt;/b&gt;, which is the URL for the API server that we are going to be hitting via Postman.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xn9D8Kw---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xn9D8Kw---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image14.png" alt="API server endpoint of Kubernetes cluster on Amazon EKS"&gt;&lt;/a&gt; API server endpoint of Kubernetes cluster on Amazon EKS&lt;/p&gt;

&lt;h2&gt;Authorizing the Postman Collection&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Assuming the collection is already imported as part of the prerequisites, select the &lt;strong&gt;Manage Environments&lt;/strong&gt; button on the top right, and edit the following:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vgA_BsxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vgA_BsxM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image15.png" alt="Environment variables for AWS environment"&gt;&lt;/a&gt; Environment variables for AWS environment&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste the API Server Endpoint into the CURRENT VALUE for kube-api-server and the token into auth-token CURRENT VALUE. Click on &lt;b&gt;Update&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;Pro Tip:&lt;/b&gt; The current value is never shared while sharing the Postman Collection. Also, since these variables have sensitive information, it is best to add them to the environment variables. We could use the same collection and run it on different environments (i.e., GCP, Minikube).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Next, add Authorization to the collection. Adding Authorization at the collection level will ensure all the requests within the collection will be authorized with the same token/credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;b&gt;Edit Collection&lt;/b&gt; and under &lt;b&gt;Authorization&lt;/b&gt;, select &lt;b&gt;OAuth2.0&lt;/b&gt;. We can use the auth-token variable as the Access Token. This token will be passed in the Request Headers for each request.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cLBJs7OK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cLBJs7OK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image23.png" alt="Adding authorization to a collection"&gt;&lt;/a&gt; Adding authorization to a collection&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Almost there! The last step to get our collection ready is adding the CA Certificate. Simply click on &lt;strong&gt;Settings&lt;/strong&gt; for Postman, and under &lt;strong&gt;Certificates&lt;/strong&gt;, turn on the CA Certificates toggle to upload the ca.crt file we created. Alternatively, you can disable certificate verification, but that is not recommended.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DVmHVQ_9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DVmHVQ_9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image13.png" alt="Adding CA Certificates to access Kubernetes APIs"&gt;&lt;/a&gt; Adding CA Certificates to access Kubernetes APIs&lt;/p&gt;

&lt;h2&gt;Deploy an app&lt;/h2&gt;

&lt;p&gt;We are all set to deploy. First, we need something very important. Not surprisingly, it is an app. Let's take a look at the app.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/thecasualcoder/dobby"&gt;Dobby&lt;/a&gt;. Dobby is an open source project, and it's extremely simple to call different APIs on it and manipulate responses.&lt;/p&gt;

&lt;p&gt;We spoke about containerization earlier: a container simply means an app is running in a sandbox. The container is created from an image. If there are any code changes in the app, we recreate the image to reflect the app’s latest changes and rerun the container.&lt;/p&gt;

&lt;p&gt;We can find the publicly available image for Dobby &lt;a href="https://hub.docker.com/r/thecasualcoder/dobby"&gt;here&lt;/a&gt;. We must use the image in the request.&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;Deploy an App &lt;/b&gt;folder in the collection contains requests to create and list Kubernetes objects that will help deploy our app on AWS. Let’s take a quick look at these objects.&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Creating a Kubernetes pod&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;In Kubernetes, pods are a group of containers and also the smallest deployable unit. The pod will define the configuration that is required to create the app container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3ziChbrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3ziChbrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image4.png" alt="Containers in a Kubernetes pod"&gt;&lt;/a&gt; Containers in a Kubernetes pod&lt;/p&gt;

&lt;p&gt;We must create a pod for Dobby. You should find the configuration as json in the request body. We have created a collection variable called project-name, this variable is going to be used throughout the collection while creating resources, so it made perfect sense to extract it. You can rename the variable if you want.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;b&gt;Body&lt;/b&gt; to find the request body as shown in here:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5lgbBt5Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5lgbBt5Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image24.png" alt="Creating a Pod POST Request"&gt;&lt;/a&gt; Creating a Pod POST Request&lt;/p&gt;

&lt;p&gt;You will find fields for metadata name, the name of the pod, and labels. We'll discuss how labels are useful in the subsequent requests. If you scroll below to the spec you will also find the image that we are using for the containers, and the port the app is supposed to run on.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Press &lt;b&gt;Send&lt;/b&gt;. There will be a lot of details in the response body.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;b&gt;Visualize, &lt;/b&gt;and if the response is successful, congratulations are in order! Keep going.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YjoAhOR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YjoAhOR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image2.png" alt="Visualization of successful creation of a pod"&gt;&lt;/a&gt; Visualization of successful creation of a pod&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;Send &lt;/b&gt;the GET request that lists all pods created. Again, click on the &lt;b&gt;Visualize&lt;/b&gt; button:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P5hfqPOg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P5hfqPOg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image22.png" alt="Visualization to list pods created"&gt;&lt;/a&gt; Visualization to list pods created&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the Clean Up folder, and run the &lt;b&gt;Delete Pod&lt;/b&gt; request:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GpkbGWfX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GpkbGWfX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image16.png" alt="Deleting a pod request"&gt;&lt;/a&gt; Deleting a pod request&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Again, click on &lt;b&gt;Visualize &lt;/b&gt;to see the response as a prettier message:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RYNq8miH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RYNq8miH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image21.png" alt="Visualization of successful deletion of a pod"&gt;&lt;/a&gt; Visualization of successful deletion of a pod&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Deployment&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;In the previous section, we created a pod and deleted it. That means our app is no longer running. In a real-world scenario, though, we would want to have multiple instances of our app running so that the requests could be load-balanced across them. These instances (pods) could be running on different nodes/machines. We want to ensure that at least a minimum amount of instances are running. Deployments can help us manage it all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XG-GEDrt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XG-GEDrt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image9.png" alt="Kubernetes deployment"&gt;&lt;/a&gt; Kubernetes deployment&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;b&gt;Body&lt;/b&gt; to review the request body. The body contains the configuration for the deployment:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A1Q6k0HK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A1Q6k0HK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image8.png" alt="Creating a Deployment POST Request"&gt;&lt;/a&gt; Creating a Deployment POST Request&lt;/p&gt;

&lt;p&gt;Components of the body:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;b&gt;Replicas&lt;/b&gt;: Refer to the number of pods that should be running for a deployment. We are assigning the pods that get created via this deployment a label of &lt;b&gt;-pod&lt;/b&gt;.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Labels&lt;/b&gt;: Pods are matched to the respective deployments by these labels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The body also contains a definition for a readiness probe and a liveness probe:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;b&gt;Readiness Probe&lt;/b&gt;: Containers are assigned traffic in Kubernetes based on the readiness probe. This can be used when the container is not ready to serve traffic due to other services it depends on, or if it is loading any data/configuration.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Liveness Probe&lt;/b&gt;: Containers restart based on the liveness probe. So to check if the Dobby app is up, the /health endpoint will be hit. If it returns a 500 then the containers are restarted.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;b&gt;Send &lt;/b&gt;to create a deployment and look into the &lt;b&gt;Visualization&lt;/b&gt; tab for the next steps:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KYn2VSyF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KYn2VSyF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image12.png" alt="Visualization of successful deployment creation"&gt;&lt;/a&gt; Visualization of successful deployment creation&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;Send &lt;/b&gt;the GET request that lists all pods created. See results in the &lt;b&gt;Visualization&lt;/b&gt; tab:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SGph5mXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SGph5mXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image6.png" alt="Visualization listing pods created via deployment"&gt;&lt;/a&gt; Visualization listing pods created via deployment&lt;/p&gt;

&lt;h2&gt;Expose your app&lt;/h2&gt;

&lt;p&gt;In the previous section, we were able to successfully create a deployment. So how do we access it now? The pods created have IP addresses, but what if we want to access one app from another?&lt;/p&gt;

&lt;p&gt;Let's take a look at Kubernetes’ service.&lt;/p&gt;

&lt;h3&gt;&lt;b&gt;Service&lt;/b&gt;&lt;/h3&gt;

&lt;p&gt;We have two apps—frontend and backend. There are separate pods for the frontend and for the backend. We need to expose the pods of the backend so that the frontend app can access it and use the APIs. We usually configure the IP address or URL for the backend into the frontend. However, if the IP address changes for the backend, those changes would have to be reflected in the frontend app as well. With services, we can avoid these changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sopJ_7xA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sopJ_7xA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image1.png" alt="Kubernetes Service"&gt;&lt;/a&gt; Kubernetes Service&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Review the request body by clicking &lt;b&gt;Body&lt;/b&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nB-XOD-s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nB-XOD-s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image7.png" alt="Creating a Service POST Request"&gt;&lt;/a&gt; Creating a Service POST Request&lt;/p&gt;

&lt;p&gt;Components of the body:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;b&gt;Selectors&lt;/b&gt;: The selectors help the service map to the pods that have the matching label.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Exposing&lt;/b&gt;: Services can be exposed within the cluster for other services (frontend) to access the pods, or outside the cluster for the public to access the service. By default, the service would be of ClusterIP type (this would expose the service inside the cluster). We want to expose this externally, so we chose the LoadBalancer type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.&lt;b&gt; Send &lt;/b&gt;and view the&lt;b&gt; Visualization &lt;/b&gt;tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A6I4ZDtb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A6I4ZDtb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image11.png" alt="Visualization of successful creation of service"&gt;&lt;/a&gt; Visualization of successful creation of service&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the list of service requests to find the IP address of the service. Here’s what you should see under &lt;b&gt;Visualize &lt;/b&gt;for the List Services request:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k2io-PpP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k2io-PpP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image17.png" alt="Visualization listing services"&gt;&lt;/a&gt; Visualization listing services&lt;/p&gt;

&lt;p&gt;The following snippet in the &lt;b&gt;Tests&lt;/b&gt; tab will save the external IP for the service to the collection:&lt;/p&gt;

&lt;pre&gt;const service = pm.response.json().items.filter((item) =&amp;gt; item.metadata.name === 
pm.variables.get("project-name")+"-service")[0]pm.collection
Variables.set("service-ip", 
service.status.loadBalancer.ingress[0].hostname)
pm.collectionVariables.set("service-port", service.spec.ports[0].port)&lt;/pre&gt;

&lt;p&gt;Now we need to access an endpoint on the Dobby app to check if the app is running. Note: It might take a while before the service starts serving requests. Once the service is ready, click on the &lt;strong&gt;Say Hello to Dobby&lt;/strong&gt; request. If you hover over the service-ip and service-port variables, you should see their value that was set by the tests in the previous request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rLDbKHTd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-17-at-6.12.19-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rLDbKHTd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/Screen-Shot-2020-12-17-at-6.12.19-PM.png" alt="Dobby health check request"&gt;&lt;/a&gt; Dobby health check request&lt;/p&gt;

&lt;p&gt;Upon pressing &lt;b&gt;Send&lt;/b&gt;, under &lt;b&gt;Visualize &lt;/b&gt;you should see the message we have been working so hard for:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DfNSQNSZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DfNSQNSZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.postman.com/wp-content/uploads/2020/12/image3.png" alt="Visualization message when Dobby is healthy "&gt;&lt;/a&gt; Visualization message when Dobby is healthy&lt;/p&gt;

&lt;h2&gt;Clean up&lt;/h2&gt;

&lt;p&gt;You will find a Clean Up folder in the collection. It contains all the requests to delete the Kubernetes resources—services, deployments, and pods we created throughout this tutorial.&lt;/p&gt;

&lt;p&gt;At the end of the tutorial make sure you delete your cluster, unless you wish to keep it:&lt;/p&gt;

&lt;pre&gt;eksctl delete cluster -f cluster.yaml&lt;/pre&gt;

&lt;h2&gt;What next?&lt;/h2&gt;

&lt;p&gt;Hopefully this tutorial helped you get started with Kubernetes. And there’s so much more to explore. Here are some additional things you can try with this Kubernetes collection:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;b&gt;Creating oth&lt;/b&gt;&lt;b&gt;er Kub&lt;/b&gt;&lt;b&gt;ernetes objects: &lt;/b&gt;In this tutorial, we discussed a few Kubernetes objects, including service accounts, pods, deployments, and services. Next, you could explore other kubernetes objects like namespaces and ConfigMaps.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Automate workflows in Postman: &lt;/b&gt;You could use the collection runner in Postman to execute common workflows. A workflow in Postman is ordering the requests in a collection to accomplish a task eg. running health checks for all services. Take a look at our blog post about &lt;a href="https://blog.postman.com/looping-through-a-data-file-in-the-postman-collection-runner/#:~:text=Postman's%20Collection%20Runner%20lets%20you,Test%20for%20hundreds%20of%20scenarios"&gt;looping through a data file in the postman collection runner&lt;/a&gt; and &lt;a href="https://learning.postman.com/docs/running-collections/building-workflows/"&gt;building workflows in Postman&lt;/a&gt;.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Automate deployments in CI/CD: &lt;/b&gt;In case you want to automate deployments, consider using &lt;a href="https://learning.postman.com/docs/running-collections/using-newman-cli/command-line-integration-with-newman/"&gt;Newman&lt;/a&gt;—command line runner for Postman collections. If you prefer kubectl, you could use that instead.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Experiment with Dobby APIs to learn more: &lt;/b&gt;The Dobby app has APIs such as
/control/health/sick, which will make the app return an internal server error. You can run these and observe their effect on the liveness and readiness probes to learn more.&lt;/li&gt;
    &lt;li&gt;
&lt;b&gt;Fork collection and raise PR: &lt;/b&gt;Additionally, you could also &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/#forking-a-collection"&gt;fork the collection&lt;/a&gt; and raise a &lt;a href="https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/#creating-pull-requests"&gt;pull request&lt;/a&gt; with your changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technical review by Kevin Swiber, lead solutions engineer at Postman.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;What do you think about this topic? Tell us in a comment below. You can also give product feedback through our &lt;/b&gt;&lt;a href="https://community.postman.com/"&gt;&lt;b&gt;Community forum&lt;/b&gt;&lt;/a&gt;&lt;b&gt; and &lt;/b&gt;&lt;a href="https://github.com/postmanlabs/postman-app-support/issues"&gt;&lt;b&gt;GitHub repository&lt;/b&gt;&lt;/a&gt;&lt;b&gt;.&lt;/b&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>postman</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Real-Time Time Series Chart With Kafka and Socket.io</title>
      <dc:creator>Meenakshi</dc:creator>
      <pubDate>Thu, 24 Sep 2020 06:30:42 +0000</pubDate>
      <link>https://dev.to/meenakshidhanani/real-time-time-series-chart-with-kafka-and-socket-io-56i5</link>
      <guid>https://dev.to/meenakshidhanani/real-time-time-series-chart-with-kafka-and-socket-io-56i5</guid>
      <description>&lt;p&gt;Our team at ThoughtWorks, E4R (Engineering for Research) has been working on &lt;a href="https://github.com/thoughtworks/epirust"&gt;&lt;strong&gt;Epirust&lt;/strong&gt;&lt;/a&gt;- an open-source &lt;a href="https://en.wikipedia.org/wiki/Agent-based_model"&gt;agent-based modeling&lt;/a&gt; solution for epidemiological simulations. In the midst of this pandemic, it is crucial for epidemiologists to make quick and effective decisions that would help control the spread of COVID. Epirust is an attempt to simulate a region, say India with its population as agents and visualize the effect of interventions such as vaccines, the lockdown, and an increase in the number of hospitals on an agent’s daily routine. To know more about the motivations behind this project, head over to the &lt;a href="https://github.com/thoughtworks/epirust/wiki/Motivation-Behind-EpiRust"&gt;Epirust wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As part of the E4R team, I had the opportunity to work on the visualizations for this project. In this post, I’ll walk you through the architecture of Epirust and the thought process behind using Kafka and web sockets for building the following real-time time series visualization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RnVxAjDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AOTyU8TvmP8aiJ_XwDF4xSg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RnVxAjDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AOTyU8TvmP8aiJ_XwDF4xSg.gif" alt=""&gt;&lt;/a&gt;Real-time time series chart for a simulation&lt;/p&gt;

&lt;p&gt;The data presented in the visualization is received from the backend engine(written in Rust). The engine encapsulates the core logic of generating counts of susceptible, infected, hospitalized, recovered, and deceased agents per hour. These counts are based on a certain input configuration eg. population size, transport percentage, working population percentage, and disease dynamics for COVID.&lt;/p&gt;

&lt;p&gt;Let’s break this problem into the following 3 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Streaming data from the backend&lt;/li&gt;
&lt;li&gt;API to consume the stream on the frontend&lt;/li&gt;
&lt;li&gt;Charting library to visualize this data&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Streaming data from the backend
&lt;/h4&gt;

&lt;p&gt;The Rust engine generates a number of agents infected per hour. We wanted to visualize the changing curve for each passing hour of the simulation. Here’s a peek into the JSON received from the engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  hour: 1,
  infected_std: 1,
  susceptible_std: 100,
  hospitalized_std: 10,
  recovered_std: 2,
  deceased_std: 0,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need a platform to stream these updated counts for each hour in real-time so that the frontend can react by plotting the curve on the graph for every hour. If we think in terms of events, each count generated by the simulation model is an event. Once this event is published, interested parties can subscribe to it and visualize it in their own ways. This is a typical use case of the pub/sub-model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kafka.apache.org/"&gt;&lt;strong&gt;Kafka&lt;/strong&gt;&lt;/a&gt; is a popular event streaming platform. It’s a distributed platform and hence highly scalable and available. Since the simulations run based on the input configuration, we had certain use cases where we would want the simulation to accept configurations for a city’s climate, population, transport percentage, etc., and scale the model to run on a country level, hence Kafka fit the bill perfectly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--phfQjDSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/916/1%2AEeo7tY4fiRn-aRZCivGVDQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--phfQjDSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/916/1%2AEeo7tY4fiRn-aRZCivGVDQ.png" alt=""&gt;&lt;/a&gt;Kafka components&lt;/p&gt;

&lt;p&gt;We wrote a Kafka Producer in Rust that would push the count for each hour to a &lt;strong&gt;&lt;em&gt;counts_updated&lt;/em&gt;&lt;/strong&gt; topic. The &lt;strong&gt;&lt;em&gt;counts_updated&lt;/em&gt;&lt;/strong&gt; topic was further subscribed by the Kafka Consumer on the server. Our idea of having a server component between the Rust engine and the frontend was so that we could persist the simulation data generated for a particular input. eg. We could persist simulation results for 1000 hours having 3000 agents and compare it with 2000 hours having1000 agents.&lt;/p&gt;

&lt;h4&gt;
  
  
  API to consume data on frontend
&lt;/h4&gt;

&lt;p&gt;We need the frontend to receive the hour messages in real-time. If the frontend were to make an HTTP request to receive the updated counts, it would have to poll for changes making it very difficult for the frontend to know the frequency of polling for messages. Furthermore, this would not be real-time, some delay would have to be factored in. Since we understood that HTTP wouldn’t work in this scenario, we started looking at other means of pushing messages to the client for updates.&lt;/p&gt;

&lt;p&gt;Web sockets allow to the establishment of a connection between a web browser and a server. Messages can be relayed in real-time by the server to the client using this connection. For this purpose, we used the library &lt;a href="https://socket.io/"&gt;socket.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Socket.io has two components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A server that integrates with NodeJS&lt;/li&gt;
&lt;li&gt;A client library that loads messages on the browser side&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On consuming the updated counts from the Kafka Consumer, an event &lt;strong&gt;&lt;em&gt;epidemicStats&lt;/em&gt;&lt;/strong&gt; with updated counts is emitted from the server on the socket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;socket.emit('epidemicStats', {
  infected_std: 3,
  susceptible_std: 200,
  hospitalized_std: 5,
  recovered_std: 4,
  deceased_std: 0,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This event would then be received by the frontend React app listening on the socket for messages. We use the &lt;a href="https://www.npmjs.com/package/socket.io-client"&gt;socket.io-client&lt;/a&gt; library for this purpose. If the simulation ends, then a message denoting the same is sent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;socket.on('epidemicStats', _function_ (messageRaw) {
    _const_ message = messageRaw;

   _if_ ("simulation_ended" _in_ message) {
        simulationEndedTemp = _true_;
        socket.close();
    }
    _else_ {
        _const_ { hour,
            susceptible, susceptible_std,
            infected, infected_std,
            hospitalized, hospitalized_std,
            recovered, recovered_std,
            deceased, deceased_std } = message;

        _const_ perHourStats = [hour,
            susceptible, susceptible_std,
            infected, infected_std,
            hospitalized, hospitalized_std,
            recovered, recovered_std,
            deceased, deceased_std
        ];

        buff.push(perHourStats);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Charting library to visualize real-time graphs
&lt;/h4&gt;

&lt;p&gt;The time-series graph would be updated frequently, so we needed a library that could accommodate the changes quickly without breaking the UI. After a performance comparison between &lt;a href="https://www.chartjs.org/"&gt;chart.js&lt;/a&gt;, &lt;a href="https://vega.github.io/vega-lite/"&gt;vega-lite&lt;/a&gt;, and &lt;a href="https://dygraphs.com/"&gt;dygraphs&lt;/a&gt;, we realized dygraphs to be the most performant.&lt;/p&gt;

&lt;p&gt;Here’s how you create your multiline line chart using dygraphs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_let_ options = {
    legend: 'always',
    animatedZooms: _true_,
    title: 'Time Series Graph',
    ylabel: 'Number of Agents',
    xlabel: 'Hours',
    showRoller: _true_,
    errorBars: _true_,
    rollPeriod: 24
}
_const_ visualisationDiv = document.getElementById("vis");
_const_ graphInstance = _new_ Dygraph(visualisationDiv, convertToCsv(buff), options);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dygraphs charts can handle large datasets without getting bogged down. The chart is also very interactive, giving us an easy option to pan and zoom. It accepts a rollPeriod based on which it averages out the curve. Since the data we generated was on an hourly basis, we averaged it out to 24 hours.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;We discussed the Rust engine that generates counts of agents that are infected, diseased, hospitalized, etc., and pushes it onto Kafka where a Kafka Consumer on the server reads them and puts them onto the web sockets. This data is received by a React app listening on the socket to plot a line chart that updates in real-time.&lt;/p&gt;

&lt;p&gt;The following is an architecture diagram of Epirust. I hope this helps you get the big picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MR5E19K5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/955/0%2A5xNxG5QO5wvZ8zOx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MR5E19K5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/955/0%2A5xNxG5QO5wvZ8zOx.jpg" alt=""&gt;&lt;/a&gt;Architecture Diagram for Epirust&lt;/p&gt;

&lt;p&gt;I’m going to be coming up with part 2 for this series where I’ll talk about the performance comparisons we did among the charting libraries. In the later stages of this project, we also built a grid visualization to track the movements of the agents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3rhBY1e_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJ8HtHVbXkH9Sp0YKdfkMNQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3rhBY1e_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJ8HtHVbXkH9Sp0YKdfkMNQ.gif" alt=""&gt;&lt;/a&gt;Agent movement across the grid&lt;/p&gt;

&lt;p&gt;All the code snippets are taken from the open-source project &lt;a href="https://github.com/thoughtworks/epirust"&gt;Epirust&lt;/a&gt;. Feel free to explore the project and read more about agent-based modeling. Watch out for the subsequent parts of this series.&lt;/p&gt;

&lt;p&gt;Reach out for any feedback and how you think we could have done this better. Happy to hear from you!&lt;/p&gt;

&lt;p&gt;Check out the Epirust project-&lt;a href="https://github.com/thoughtworks/epirust"&gt;https://github.com/thoughtworks/epirust&lt;/a&gt;&lt;/p&gt;

</description>
      <category>socketio</category>
      <category>timeseriesdata</category>
      <category>kafka</category>
      <category>agentbasedmodeling</category>
    </item>
  </channel>
</rss>
