【Java】Eclipse+Maven+Ontologyで作成したWebアプリケーションをHerokuでデプロイ

# はじめに

Eclipse+Maven+Ontologyで作成したWebアプリケーションをHerokuでデプロイするまでをまとめます
Herokuのデプロイに関しては以下のサイトを参考にさせていただきました

[Heroku初心者がJavaで作成したWebアプリをGitHub連携でデプロイする時つまずいた4つのこと](https://qiita.com/ShandyGaffLover/items/0dad6ebf48d649aab761)

なお、このやり方はあくまで一例になりますので、その点ご了承ください

ソースコードは以下に置いてあります
https://github.com/YasufumiNakama/heroku-java-practice

# 内容
* Eclipse+Maven+OntologyでWebアプリケーションを作成
* Herokuにデプロイ

# Eclipse+Maven+OntologyでWebアプリケーションを作成
### Mavenプロジェクトの作成
Eclipseのインストールなどについては省略します
まずEclipseからMavenプロジェクトを選択しましょう
<img width="864" alt="スクリーンショット 0031-08-09 2.09.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/d05eda2c-544b-5577-efdb-5abeffaa7ee1.png">
グループIDとアーティファクトIDを入力します
<img width="671" alt="スクリーンショット 0031-08-09 3.41.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/35ec0e2b-a89b-15b3-ba11-e215d5869178.png">
すると、以下のようにディレクトリが構成されるので、ここからコードを書いていきましょう
<img width="288" alt="スクリーンショット 0031-08-09 3.43.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/e7469e9b-ecd5-d622-601a-8dcdf2e2a714.png">
### resourcesの準備
今回はresourcesとして、（ラーメン）オントロジーが記述されたowlファイルを用います（作成済みのものがあったのと、シンプルで楽だったので）
<img width="195" alt="スクリーンショット 0031-08-09 2.34.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/e9656687-67ff-b8c4-f04a-423764b9289c.png">
簡単な例として、「ラーメン」クラスのサブクラスを、クエリを投げて取ってきて、htmlに出力するということをやってみます（本当はユーザの入力に対して何か取ってくるみたいにすると面白かったですが、Herokuにデプロイするまでが目的なので、手を抜きます）
### pom.xmlの準備
resourcesにオントロジーを用いてやり取りするので、testに使うjunitの他にjena、jersey、gsonを\<dependencies\>として用います

* junit
* jena
* jersey
* gson

また\<build\>については公式から説明があるので、[ここ](https://devcenter.heroku.com/articles/java-webapp-runner#configure-maven-to-download-webapp-runner)からコードをそのまま用います
他にも手を加えているので、詳細はソースコードを見てください

### web.xmlの準備
src/main/webapp/WEB-INF/web.xmlを作成して、jerseyの設定をします
詳細はソースコードの通りです

### javaソースコード
自分はグループIDをcom.heroku-java-practiceとしたので、src/main/java/com/heroku_java_practice以下にjavaソースコードを書いていきます（testの方はsrc/test/java/heroku_java_practice以下）
まずは、ramen.javaという、resourcesとして（ラーメン）オントロジーが記述されたowlファイルから「ラーメン」クラスのサブクラスをクエリを投げて取ってくるプログラムを書きました

```ramen.java
package com.heroku_java_practice;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.util.*;
import com.hp.hpl.jena.query.*;

public class ramen {
	
	public static String path = new File(".").getAbsoluteFile().getParent();
	public static String Resources = path + "/src/main/resources/";

    public static HashSet<String> get_ramen() throws FileNotFoundException {
        // owlファイルの読み込み
        Model model = FileManager.get().loadModel(Resources + "owl/ramen.owl");
        // query
        String queryString = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n" +
        		             "SELECT ?y\n" +
                			 "WHERE{\n" +
                             "?y rdfs:subClassOf <http://www.semanticweb.org/nakamayasufumi/ontologies/2019/5/untitled-ontology-30#ラーメン>\n" +
                             "}";
        // result
        HashSet<String> result = new HashSet<>();
        // SPARQLクエリの読み込み
        Query query = QueryFactory.create(queryString);
        // SPARQLクエリの実行
        QueryExecution qexec = QueryExecutionFactory.create(query, model);
        try {
            ResultSet results = qexec.execSelect();
            for (; results.hasNext(); ) {
                QuerySolution soln = results.nextSolution();
                Resource y = soln.getResource("y");
                result.add(y.toString().split("#")[y.toString().split("#").length-1]);
            }
        } finally {
            qexec.close();
        }
        return result;
    }
}

```
では、ramen.javaが想定通りの挙動をしているか、testで確認しましょう

```RamenTest.java
package heroku_java_practice;

import static org.junit.Assert.*;
import org.junit.Test;

import com.heroku_java_practice.*;

public class RamenTest {
	
	@Test
	public void test() {
		try {
			ramen status = new ramen();
			System.out.println(status.get_ramen());
		} catch(Exception e) {
			e.printStackTrace();
			fail(e.toString());
		}
	}
	
}
```
RamenTest.javaをJUnitテストで実行すると、出力結果は以下のようになっていて、想定通りの挙動をしていることが確認できました
<img width="535" alt="スクリーンショット 0031-08-09 3.57.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/027fb2a6-45fa-be2a-23ef-973c4210f482.png">
最後に、この出力結果をWebに反映させるために、main.javaを書きましょう
jersey便利ですね

```main.java
package com.heroku_java_practice;

import java.io.FileNotFoundException;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@Path("webmethods")
public class main {

	@Path("/ramen")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public String return_ramen() throws FileNotFoundException {
		ramen status = new ramen();
		Gson gson = new GsonBuilder().serializeNulls().create();
		String output = gson.toJson(status.get_ramen());
		return output;
	}

}
```
main.javaの挙動も確認しておきましょう

```RamenTest.java
package heroku_java_practice;

import static org.junit.Assert.*;
import org.junit.Test;

import com.heroku_java_practice.*;

public class RamenTest {
	
	/*
	@Test
	public void test() {
		try {
			ramen status = new ramen();
			System.out.println(status.get_ramen());
		} catch(Exception e) {
			e.printStackTrace();
			fail(e.toString());
		}
	}
	*/
	
	@Test
	public void test() {
		try {
			main status = new main();
			System.out.println(status.return_ramen());
		} catch(Exception e) {
			e.printStackTrace();
			fail(e.toString());
		}
	}
	
}
```
<img width="529" alt="スクリーンショット 0031-08-09 4.06.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/3d785c63-654d-5c2d-a94b-b493f9404c89.png">
大丈夫そうですね

### HTMLとJavaScript
HTMLとJavaScriptをsrc/main/webapp/以下に作成しましょう

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>project-ramen</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="index.js"></script>
</head>
<body>
    <h2>ラーメン</h2>
    <table id="ramen"></table>
    <hr style="border-style:dashed">
</body>
</html>
```

```index.js
const MethodURI =  "https://heroku-java-practice.herokuapp.com/webapi/webmethods/";

function gebi(id) {
    return document.getElementById(id);
}

window.onload = function(){
	var uri = MethodURI+'ramen';
	$.getJSON(uri,
	    function(data){
            for(var i=0; i<data.length; i++){
	            var table = gebi("ramen");
	            $(table).append("<tr></tr>").find("tr:last").append("<td>"+"・"+data[i]+"</td>")
	        }
        }
	);
}
```
このjsで先ほどの出力をテーブル形式に並べることができます
ちなみにMethodURIに関しては、あらかじめHeroku側のApp nameを確保してから書くようにするのがいいです
webapi/webmethods/に関しては、それぞれweb.xmlとmain.javaで設定したものになります

# Herokuにデプロイ
### Create App
デプロイするためのApp nameを確保しましょう
<img width="1328" alt="スクリーンショット 0031-08-09 4.22.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/d90e00c0-ff12-ed08-be0b-9304cb5d9def.png">

### デプロイする前に
デプロイする前に、デプロイに必要なファイルがいくつかあります

* [Procfile](https://devcenter.heroku.com/articles/java-webapp-runner#deploy-your-application-to-heroku)
* [system.properties](https://devcenter.heroku.com/articles/java-support#specifying-a-java-version)

以上のファイルは用意しておきましょう

### Githubにpush
以上のファイルを追加したら、デプロイしたいソースコードをGithubにpushしておきましょう

### デプロイ
ここではGithubからのデプロイをしてみます
![screencapture-dashboard-heroku-apps-heroku-java-practice-deploy-heroku-git-2019-08-09-04_33_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/c4661368-732b-7a06-18b5-6df98ac217dc.png)
Githubのアイコンのところをクリックして
<img width="1230" alt="スクリーンショット 0031-08-09 4.48.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/4fd8b47e-8ae0-98c6-fdbf-19f24f004c9e.png">
デプロイしたいGithubレポジトリと連携すればOKです
<img width="1440" alt="スクリーンショット 0031-08-09 4.50.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/e579b756-ce56-1e4e-b61d-577cb807fb33.png">
Automatic deploysでもManual deployでもどちらでもいいので、クリックすればデプロイされます
<img width="1323" alt="スクリーンショット 0031-08-09 6.16.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340468/9e005c6f-8215-3e6a-9ae6-722de8e15c9e.png">

### デプロイしたアプリケーションのファイル構成
デプロイしたアプリケーションのファイル構成は、以下のようにして確認することができます

```
$ heroku login
$ heroku run bash -a <appName>
$ pwd
/app
$ ls
```
参考：[How to see files and file structure on a deployed Heroku app](https://stackoverflow.com/questions/38924458/how-to-see-files-and-file-structure-on-a-deployed-heroku-app)

# おわりに
以上でとりあえずは 【Java】Eclipse+Maven+Ontologyで作成したWebアプリケーションをHerokuでデプロイ が完成となります
また何かあれば追記するかもしれません（2019/8/9）