(0)目次&概説
(1) 目的
(1-1) 記事の目的
(2) APIの概要
(2-1) APIとは?
(2-2) Web APIとは?
(2-3) Web APIの様々な呼び方
(2-3-1) curlコマンドで呼び出し
(2-3-2) JSP/Servletプログラムから呼び出し
(3) WebAPIコールの基本プログラム
(3-1) ソースコード
(4) エラー対応
(4-1) java.net.MalformedURLException: no protocol:
(4-2) java.io.FileNotFoundException: [URL]
(1) 目的
(1-1) 記事の目的
APIを初めて使う方に向けて、GitHubのAPIの一つである「Users」をJava Servletプログラムからコールして、指定したユーザーのメタ情報を取得する際に行った手順を記録も兼ねて紹介します。
https://developer.github.com/v3/users/
>目次にもどる
(2) APIの概要
(2-1) APIとは?
(2-2) Web APIとは?
(2-3) Web APIの様々な呼び方
前述の通りWebAPIはURLをベースに呼び出しを行うため、様々な方法での呼び出しが可能です。今回はその呼び出し方の例をいくつか紹介します。
(2-3-1) curlコマンドで呼び出し
curlとはコマンドラインツールで、コマンド実行によりネットワーク越しにリクエスト(Request)を作成できるコマンドです。URLを指定してAPI実行を行う事もでき、下記はその一例としてGitHubのユーザ情報を取得するURLを指定したAPIコールを照会します。
curl -u [Your GitHub User Name] https://api.github.com/user
実行するとJSON形式のレスポンスが返ってきます。
(図231)

↓JSON形式の応答が帰ってくる

(2-3-2) JSP/Servletプログラムから呼び出し
当記事のメイントピックで2章以降で手順を解説します。最終的なアウトプットとしては、ブラウザからServletのURLを入力するとAPIコールが実行されて、画面上にその取得結果が表示されるようになります。
(図232)

(3) WebAPIコールの基本プログラム
(3-1) ソースコード
この節ではGitHubのユーザー情報取得APIをJavaからコールした際のサンプルプログラムを紹介します。
package studyc;
package studyc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Base64;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class WebAPI_Test4
*/
@WebServlet("/WebAPI_Test4")
public class WebAPI_Test4 extends HttpServlet {
private static final long serialVersionUID = 1L;
public WebAPI_Test4() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String token = "6e83a69b5f9946971d3f2911ec113383e6c4ae56";
String url = "api.github.com/users/XXXXXXXX";
response.getWriter().append("Served at: ").append(request.getContextPath());
//getGithubContentUsingHttpClient(token,url);
getGithubContentUsingURLConnection(request,response,token,url);
}
//### メソッド名称: getGithubContentUsingURLConnection
//### メソッド概要: GitHubのAPI
//### 【引数3】String token :WebAPIを利用するためのトークン
//### 【引数4】String url :WebAPIのURL
public static void getGithubContentUsingURLConnection(HttpServletRequest request, HttpServletResponse response, String token,String url) throws IOException {
//### APIコールのためのURL組み立て
String newURL = "https://" + url;
//### InputStream型の変数を初期化
InputStream crunchifyInStream = null;
//### 変数の初期化
String result = ""; //最終結果を格納するための変数
String tmp = ""; //読み込んだデータを格納するための一時変数
try {
//### URLオブジェクトをインスタンス化
//### 【引数】newURL :APIのURL
URL myURL = new URL(newURL);
//### URLクラスのopenConnection()メソッドを使って、URLConnectionクラスをインスタンス化
URLConnection connection = myURL.openConnection();
//### Base64.getEncoder()でBasic型のエンコーダの名称を取得(リクエストヘッダーにセット)
//### 【参考1】https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
String authString = "Basic " + Base64.getEncoder();
//### setRequestProperty()メソッドでRequest(リクエスト)のプロパティ情報(リクエストヘッダー)をセットしています。
//### 【参考1】https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
//### 【引数1】String key :リクエストを表現するキーワード
//### 【引数2】String value :付帯する値の情報
connection.setRequestProperty("Authorization", authString);
//### getInputStream()メソッドでURLConnectionクラスにてオープンしている接続から、データを読むInputStreamクラスのインスタンス作成
//### 【参考1】https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
crunchifyInStream = connection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
//### InputStreamReaderクラスはByteストリームとCharacterストリームの橋渡しを行います。
//### InputStreamReaderクラスのコンストラクタで引数を指定していないため、デフォルトの文字コードでインスタンス化しています。
//### BufferedReaderクラスのコンストラクタを用いて、バッファリングによる最高効率の読込みを可能にしています(メモリアクセスによって読込みを行いディスクI/Oを削減する)
BufferedReader in = new BufferedReader(new InputStreamReader(crunchifyInStream));
//3.Parse the data
try {
//### 行がnullでない間、1行ずつ読んでいき、最終結果のresultに追加していく
while((tmp = in.readLine())!=null) {
result += tmp;
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
//### 画面出力
//### 文字コードや出力形式の指定
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
//### 画面のHTMLに改行(<br />)を追記
out.println("<br />");
//### 画面に最終結果を表示
response.getWriter().append(result);
}
}
(4) エラー対応
(4-1) java.net.MalformedURLException: no protocol:
(4-1-1) 発生状況
WebAPIをコールするServlet画面をブラウザから呼び出した際に下記エラーが発生。
エラーメッセージ例(※一部抜粋)
java.net.MalformedURLException: no protocol:
at java.net.URL.(URL.java:593)
at java.net.URL.(URL.java:490)
at java.net.URL.(URL.java:439)
at WebAPI_Test.getResult(WebAPI_Test.java:16)
at WebAPI_Test.main(WebAPI_Test.java:10)
(4-1-2) 原因
URLクラスのコンストラクタ「URL(String spec)」にて、引数に指定した文字列にプロトコル(例:http://やhttps://)が含まれていない場合、構文解析をした結果「java.net.MalformedURLException」エラーになっています。
(図411)

(4-1-3) 対処
引数に与える文字列に正しい構文のURLを入力する事で解消します。
下図の例では「https://api.github.com/users/:username」という形でhttpsプロトコルのURLを与えています(例では結果として別のエラーが発生してしまっていますが、当該エラーは解消)。
(図412)

(4-2) java.io.FileNotFoundException: [URL]
(4-2-1) 発生状況
エラーメッセージ例(※一部抜粋)
java.io.FileNotFoundException: https://api.github.com/users/:Tatsuya-Yazaki
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1896)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
at studyc.WebAPI_Test4.getGithubContentUsingURLConnection(WebAPI_Test4.java:60)
at studyc.WebAPI_Test4.doGet(WebAPI_Test4.java:43)
(4-2-2) 原因
原因は該当するデータが存在しないためです。上記は悲しいミスで「https://api.github.com/users/」の直後に不要なコロン「:」が入ってしまっているため、正しくデータを取得出来ていませんでした。
GitHubのAPIドキュメントには「GET /users/:username」のような例が書かれていたりするので、私は知らずにコロン「:」を残してusernameの所だけを変えるというミスをしていました。これで時間を取られてしまい非常に勿体なかったので、みなさまも同じ目に遭わない事を願って書いています。
(図422)

(4-2-3) 対処
実際にコロン「:」を除いて実行したのが以下の図です。
(図423)正しく動作するとcurlコマンドと同じJSON形式の結果が返ってくる
