Java and RapidAPI use case

APIs and tooling like Jupyter docs allows many opportunities in fields like Data Science. As more and more developers use APIs, they build standards in how you setup a client, send requests and receive information...

  • An HttpClient can be used to send requests and retrieve their responses
  • An HttpRequest sets up header and body to API provider
  • An HttpResponse is returned as a result of sending an HttpRequest
  • Typically a response body will be received, if all goes well
  • Next step, is to format the response body according to your data science needs
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

//RapidAPI header  https://rapidapi.com/spamakashrajtech/api/corona-virus-world-and-india-data
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://corona-virus-world-and-india-data.p.rapidapi.com/api"))
    .header("x-rapidapi-key", "dec069b877msh0d9d0827664078cp1a18fajsn2afac35ae063")
    .header("x-rapidapi-host", "corona-virus-world-and-india-data.p.rapidapi.com")
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();

//RapidAPI request and response
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

//RapidAPI Body
System.out.println(response.body());

Build your own Web Service

To build a Web Service in the backend allows you to control information and errors between your app and the user. A proper Web Service requires more code:RESTful interface, error handling, and in this case reducing the calls to the service according to update frequency.- There are benefits of building service in Java vs JavaScript:

- Firewall will not be blocked as backend server on AWS is outside the firewall
- Selecting frontend service https://nighthawkcodingsociety.com that has been cleared through IT.
- Many APIs have usage costs or usage limits, backend can serve while limiting direct API access.
package com.nighthawk.spring_portfolio.mvc.covid;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Date;
import java.util.HashMap;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController // annotation to create a RESTful web services
@RequestMapping("/api/covid")  //prefix of API
public class CovidApiController {
    private JSONObject body; //last run result
    private HttpStatus status; //last run status
    String last_run = null; //last run day of month

    // GET Covid 19 Stats
    @GetMapping("/daily")   //added to end of prefix as endpoint
    public ResponseEntity<JSONObject> getCovid() {

        //calls API once a day, sets body and status properties
        String today = new Date().toString().substring(0,10); 
        if (last_run == null || !today.equals(last_run))
        {
            try {  //APIs can fail (ie Internet or Service down)

                //RapidAPI header
                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://corona-virus-world-and-india-data.p.rapidapi.com/api"))
                    .header("x-rapidapi-key", "dec069b877msh0d9d0827664078cp1a18fajsn2afac35ae063")
                    .header("x-rapidapi-host", "corona-virus-world-and-india-data.p.rapidapi.com")
                    .method("GET", HttpRequest.BodyPublishers.noBody())
                    .build();

                //RapidAPI request and response
                HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

                //JSONParser extracts text body and parses to JSONObject
                this.body = (JSONObject) new JSONParser().parse(response.body());
                this.status = HttpStatus.OK;  //200 success
                this.last_run = today;
            }
            catch (Exception e) {  //capture failure info
                HashMap<String, String> status = new HashMap<>();
                status.put("status", "RapidApi failure: " + e);

                //Setup object for error
                this.body = (JSONObject) status;
                this.status = HttpStatus.INTERNAL_SERVER_ERROR; //500 error
                this.last_run = null;
            }
        }

        //return JSONObject in RESTful style
        return new ResponseEntity<>(body, status);
    }
}

Hack - API Raw Output

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpRequest request = HttpRequest.newBuilder()
		.uri(URI.create("https://ultimate-tennis1.p.rapidapi.com/live_leaderboard/50"))
		.header("X-RapidAPI-Key", "af654d789amshce4b35d071f3bd2p1c0cc8jsn8db3aa6a8acc")
		.header("X-RapidAPI-Host", "ultimate-tennis1.p.rapidapi.com")
		.method("GET", HttpRequest.BodyPublishers.noBody())
		.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
{
  "Players": "50", 
  "data": [
    {
      "Age": "19", 
      "Championship Points": "7,240", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "6,740", 
      "Name": "Carlos Alcaraz", 
      "Next win points": "6,785", 
      "Points": "6,740", 
      "Points Difference": "-", 
      "Rank": 1, 
      "Rank Diff": "-", 
      "id": "a0e2"
    }, 
    {
      "Age": "36", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "5,810", 
      "Name": "Rafael Nadal", 
      "Next win points": "-", 
      "Points": "5,810", 
      "Points Difference": "-", 
      "Rank": 2, 
      "Rank Diff": "-", 
      "id": "n409"
    }, 
    {
      "Age": "23", 
      "Championship Points": "6,100", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "5,645", 
      "Name": "Casper Ruud", 
      "Next win points": "5,645", 
      "Points": "5,645", 
      "Points Difference": "-", 
      "Rank": 3, 
      "Rank Diff": "-", 
      "id": "rh16"
    }, 
    {
      "Age": "26", 
      "Championship Points": "5,565", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "5,065", 
      "Name": "Daniil Medvedev", 
      "Next win points": "5,110", 
      "Points": "5,065", 
      "Points Difference": "-", 
      "Rank": 4, 
      "Rank Diff": "-", 
      "id": "mm58"
    }, 
    {
      "Age": "25", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "5,040", 
      "Name": "Alexander Zverev", 
      "Next win points": "-", 
      "Points": "5,040", 
      "Points Difference": "-", 
      "Rank": 5, 
      "Rank Diff": "-", 
      "id": "z355"
    }, 
    {
      "Age": "24", 
      "Championship Points": "5,265", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "4,810", 
      "Name": "Stefanos Tsitsipas", 
      "Next win points": "4,810", 
      "Points": "4,810", 
      "Points Difference": "-", 
      "Rank": 6, 
      "Rank Diff": "-", 
      "id": "te51"
    }, 
    {
      "Age": "35", 
      "Championship Points": "4,320", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "3,820", 
      "Name": "Novak Djokovic", 
      "Next win points": "3,865", 
      "Points": "3,820", 
      "Points Difference": "-", 
      "Rank": 7, 
      "Rank Diff": "-", 
      "id": "d643"
    }, 
    {
      "Age": "27", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "3,445", 
      "Name": "Cameron Norrie", 
      "Next win points": "-", 
      "Points": "3,445", 
      "Points Difference": "-", 
      "Rank": 8, 
      "Rank Diff": "-", 
      "id": "n771"
    }, 
    {
      "Age": "24", 
      "Championship Points": "3,800", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "3,345", 
      "Name": "Andrey Rublev", 
      "Next win points": "3,345", 
      "Points": "3,345", 
      "Points Difference": "-", 
      "Rank": 9, 
      "Rank Diff": "-", 
      "id": "re44"
    }, 
    {
      "Age": "25", 
      "Championship Points": "3,675", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "3,175", 
      "Name": "Hubert Hurkacz", 
      "Next win points": "3,220", 
      "Points": "3,175", 
      "Points Difference": "-", 
      "Rank": 10, 
      "Rank Diff": "-", 
      "id": "hb71"
    }, 
    {
      "Age": "24", 
      "Championship Points": "3,510", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "3,055", 
      "Name": "Taylor Fritz", 
      "Next win points": "3,055", 
      "Points": "3,055", 
      "Points Difference": "-", 
      "Rank": 11, 
      "Rank Diff": "-", 
      "id": "fb98"
    }, 
    {
      "Age": "21", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "3,040", 
      "Name": "Jannik Sinner", 
      "Next win points": "_", 
      "Points": "3,040", 
      "Points Difference": "-", 
      "Rank": 12, 
      "Rank Diff": "-", 
      "id": "s0ag"
    }, 
    {
      "Age": "22", 
      "Championship Points": "3,405", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "2,950", 
      "Name": "Felix Auger-Aliassime", 
      "Next win points": "2,950", 
      "Points": "2,950", 
      "Points Difference": "-", 
      "Rank": 13, 
      "Rank Diff": "-", 
      "id": "ag37"
    }, 
    {
      "Age": "34", 
      "Championship Points": "2,995", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "2,495", 
      "Name": "Marin Cilic", 
      "Next win points": "2,540", 
      "Points": "2,495", 
      "Points Difference": "-", 
      "Rank": 14, 
      "Rank Diff": "-", 
      "id": "c977"
    }, 
    {
      "Age": "31", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "2,360", 
      "Name": "Pablo Carreno Busta", 
      "Next win points": "-", 
      "Points": "2,360", 
      "Points Difference": "-", 
      "Rank": 15, 
      "Rank Diff": "-", 
      "id": "cd85"
    }, 
    {
      "Age": "26", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "2,360", 
      "Name": "Matteo Berrettini", 
      "Next win points": "_", 
      "Points": "2,360", 
      "Points Difference": "-", 
      "Rank": 16, 
      "Rank Diff": "-", 
      "id": "bk40"
    }, 
    {
      "Age": "30", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "2,110", 
      "Name": "Diego Schwartzman", 
      "Next win points": "_", 
      "Points": "2,110", 
      "Points Difference": "-", 
      "Rank": 17, 
      "Rank Diff": "-", 
      "id": "sm37"
    }, 
    {
      "Age": "26", 
      "Championship Points": "2,445", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,990", 
      "Name": "Karen Khachanov", 
      "Next win points": "1,990", 
      "Points": "1,990", 
      "Points Difference": "-", 
      "Rank": 18, 
      "Rank Diff": "-", 
      "id": "ke29"
    }, 
    {
      "Age": "24", 
      "Championship Points": "2,440", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,940", 
      "Name": "Frances Tiafoe", 
      "Next win points": "1,985", 
      "Points": "1,940", 
      "Points Difference": "-", 
      "Rank": 19, 
      "Rank Diff": "-", 
      "id": "td51"
    }, 
    {
      "Age": "27", 
      "Championship Points": "2,280", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,780", 
      "Name": "Nick Kyrgios", 
      "Next win points": "1,825", 
      "Points": "1,780", 
      "Points Difference": "-", 
      "Rank": 20, 
      "Rank Diff": "-", 
      "id": "ke17"
    }, 
    {
      "Age": "34", 
      "Championship Points": "2,250", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,760", 
      "Name": "Roberto Bautista Agut", 
      "Next win points": "1,795", 
      "Points": "1,760", 
      "Points Difference": "-", 
      "Rank": 21, 
      "Rank Diff": "-", 
      "id": "bd06"
    }, 
    {
      "Age": "23", 
      "Championship Points": "2,245", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,745", 
      "Name": "Denis Shapovalov", 
      "Next win points": "1,790", 
      "Points": "1,745", 
      "Points Difference": "-", 
      "Rank": 22, 
      "Rank Diff": "-", 
      "id": "su55"
    }, 
    {
      "Age": "23", 
      "Championship Points": "2,200", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,745", 
      "Name": "Alex de Minaur", 
      "Next win points": "1,745", 
      "Points": "1,745", 
      "Points Difference": "-", 
      "Rank": 23, 
      "Rank Diff": "-", 
      "id": "dh58"
    }, 
    {
      "Age": "31", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,640", 
      "Name": "Grigor Dimitrov", 
      "Next win points": "_", 
      "Points": "1,640", 
      "Points Difference": "-", 
      "Rank": 24, 
      "Rank Diff": "-", 
      "id": "d875"
    }, 
    {
      "Age": "32", 
      "Championship Points": "1,970", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,490", 
      "Name": "Daniel Evans", 
      "Next win points": "1,515", 
      "Points": "1,490", 
      "Points Difference": "-", 
      "Rank": 25, 
      "Rank Diff": "-", 
      "id": "e687"
    }, 
    {
      "Age": "19", 
      "Championship Points": "1,953", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,461", 
      "Name": "Holger Rune", 
      "Next win points": "1,498", 
      "Points": "1,461", 
      "Points Difference": "-", 
      "Rank": 26, 
      "Rank Diff": "-", 
      "id": "r0dg"
    }, 
    {
      "Age": "20", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,437", 
      "Name": "Lorenzo Musetti", 
      "Next win points": "_", 
      "Points": "1,437", 
      "Points Difference": "-", 
      "Rank": 27, 
      "Rank Diff": "-", 
      "id": "m0ej"
    }, 
    {
      "Age": "25", 
      "Championship Points": "1,905", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,405", 
      "Name": "Borna Coric", 
      "Next win points": "1,450", 
      "Points": "1,405", 
      "Points Difference": "-", 
      "Rank": 28, 
      "Rank Diff": "-", 
      "id": "cg80"
    }, 
    {
      "Age": "24", 
      "Championship Points": "1,879", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,394", 
      "Name": "Francisco Cerundolo", 
      "Next win points": "1,424", 
      "Points": "1,394", 
      "Points Difference": "-", 
      "Rank": 29, 
      "Rank Diff": "-", 
      "id": "c0au"
    }, 
    {
      "Age": "25", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "1,375", 
      "Name": "Tommy Paul", 
      "Next win points": "-", 
      "Points": "1,375", 
      "Points Difference": "-", 
      "Rank": 30, 
      "Rank Diff": "-", 
      "id": "pl56"
    }, 
    {
      "Age": "23", 
      "Championship Points": "1,860", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,370", 
      "Name": "Alejandro Davidovich Fokina", 
      "Next win points": "1,405", 
      "Points": "1,370", 
      "Points Difference": "-", 
      "Rank": 31, 
      "Rank Diff": "-", 
      "id": "dh50"
    }, 
    {
      "Age": "25", 
      "Championship Points": "1,728", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,269", 
      "Name": "Maxime Cressy", 
      "Next win points": "1,273", 
      "Points": "1,269", 
      "Points Difference": "-", 
      "Rank": 32, 
      "Rank Diff": "-", 
      "id": "c0bc"
    }, 
    {
      "Age": "23", 
      "Championship Points": "1,750", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,256", 
      "Name": "Miomir Kecmanovic", 
      "Next win points": "1,295", 
      "Points": "1,256", 
      "Points Difference": "-", 
      "Rank": 33, 
      "Rank Diff": "-", 
      "id": "ki95"
    }, 
    {
      "Age": "26", 
      "Championship Points": "1,707", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,233", 
      "Name": "Botic van de Zandschulp", 
      "Next win points": "1,252", 
      "Points": "1,233", 
      "Points Difference": "-", 
      "Rank": 34, 
      "Rank Diff": "-", 
      "id": "v812"
    }, 
    {
      "Age": "21", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,205", 
      "Name": "Sebastian Baez", 
      "Next win points": "_", 
      "Points": "1,205", 
      "Points Difference": "-", 
      "Rank": 35, 
      "Rank Diff": "-", 
      "id": "b0bi"
    }, 
    {
      "Age": "30", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "1,185", 
      "Name": "Nikoloz Basilashvili", 
      "Next win points": "-", 
      "Points": "1,185", 
      "Points Difference": "-", 
      "Rank": 36, 
      "Rank Diff": "-", 
      "id": "bg23"
    }, 
    {
      "Age": "25", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,185", 
      "Name": "Reilly Opelka", 
      "Next win points": "_", 
      "Points": "1,185", 
      "Points Difference": "-", 
      "Rank": 37, 
      "Rank Diff": "-", 
      "id": "o522"
    }, 
    {
      "Age": "36", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,105", 
      "Name": "Gael Monfils", 
      "Next win points": "_", 
      "Points": "1,105", 
      "Points Difference": "-", 
      "Rank": 38, 
      "Rank Diff": "-", 
      "id": "mc65"
    }, 
    {
      "Age": "29", 
      "Championship Points": "1,585", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,085", 
      "Name": "Aslan Karatsev", 
      "Next win points": "1,130", 
      "Points": "1,085", 
      "Points Difference": "-", 
      "Rank": 39, 
      "Rank Diff": "-", 
      "id": "kc56"
    }, 
    {
      "Age": "34", 
      "Championship Points": "1,565", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,085", 
      "Name": "Albert Ramos-Vinolas", 
      "Next win points": "1,110", 
      "Points": "1,085", 
      "Points Difference": "-", 
      "Rank": 40, 
      "Rank Diff": "-", 
      "id": "r772"
    }, 
    {
      "Age": "27", 
      "Championship Points": "1,569", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,077", 
      "Name": "Yoshihito Nishioka", 
      "Next win points": "1,114", 
      "Points": "1,077", 
      "Points Difference": "-", 
      "Rank": 41, 
      "Rank Diff": "-", 
      "id": "n732"
    }, 
    {
      "Age": "21", 
      "Championship Points": "-", 
      "Last Match Comment": "-", 
      "Live Points": "1,072", 
      "Name": "Jenson Brooksby", 
      "Next win points": "_", 
      "Points": "1,072", 
      "Points Difference": "-", 
      "Rank": 42, 
      "Rank Diff": "-", 
      "id": "b0cd"
    }, 
    {
      "Age": "25", 
      "Championship Points": "1,525", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "1,045", 
      "Name": "Alexander Bublik", 
      "Next win points": "1,070", 
      "Points": "1,045", 
      "Points Difference": "-", 
      "Rank": 43, 
      "Rank Diff": "-", 
      "id": "bk92"
    }, 
    {
      "Age": "37", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "1,005", 
      "Name": "John Isner", 
      "Next win points": "-", 
      "Points": "1,005", 
      "Points Difference": "-", 
      "Rank": 44, 
      "Rank Diff": "-", 
      "id": "i186"
    }, 
    {
      "Age": "22", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "985", 
      "Name": "Sebastian Korda", 
      "Next win points": "-", 
      "Points": "985", 
      "Points Difference": "-", 
      "Rank": 45, 
      "Rank Diff": "-", 
      "id": "k0ah"
    }, 
    {
      "Age": "35", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "975", 
      "Name": "Andy Murray", 
      "Next win points": "-", 
      "Points": "975", 
      "Points Difference": "-", 
      "Rank": 46, 
      "Rank Diff": "-", 
      "id": "mc10"
    }, 
    {
      "Age": "21", 
      "Championship Points": "1,454", 
      "Last Match Comment": "Will play next in the R32.", 
      "Live Points": "974", 
      "Name": "Brandon Nakashima", 
      "Next win points": "999", 
      "Points": "974", 
      "Points Difference": "-", 
      "Rank": 47, 
      "Rank Diff": "-", 
      "id": "n0ae"
    }, 
    {
      "Age": "24", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "971", 
      "Name": "Alex Molcan", 
      "Next win points": "-", 
      "Points": "971", 
      "Points Difference": "-", 
      "Rank": 48, 
      "Rank Diff": "-", 
      "id": "mv14"
    }, 
    {
      "Age": "20", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "961", 
      "Name": "Jack Draper", 
      "Next win points": "-", 
      "Points": "961", 
      "Points Difference": "-", 
      "Rank": 49, 
      "Rank Diff": "-", 
      "id": "d0co"
    }, 
    {
      "Age": "27", 
      "Championship Points": "-", 
      "Last Match Comment": "", 
      "Live Points": "960", 
      "Name": "Lorenzo Sonego", 
      "Next win points": "-", 
      "Points": "960", 
      "Points Difference": "-", 
      "Rank": 50, 
      "Rank Diff": "-", 
      "id": "su87"
    }
  ]
}