(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形式の結果が返ってくる