[make it easy] Let's Create a Rest API Service

When we talk about Rest API, we usually talk about how to connect and use it. Let's create a service this time.
# Rest Event
EFW rest events are stored in the tomcat/WEB-INF/efw/event folder just like web events. The difference is that they are written differently.
https://github.com/efwGrp/efw4.X/blob/master/help/api_restevent.md

# Image of Test
Send from jsp to server. Forward from js event to RestAPI event, perform RestAPI DB processing and return the result. A light security check will be performed to check whether the token is correct.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/8429a5b1-0bbf-c6cd-a613-bf84dae6e967.png)

# JSP
```jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="efw" uri="efw" %>
<!DOCTYPE HTML>
<HTML>
<HEAD>
	<title>Rest API Server and Client Test</title>
	<efw:Client lang="jp"/>
</HEAD>
<BODY>
	<button onclick="Efw('helloRestAPI_submit',{mode:'0'})">初期化（テーブル作成）</button><br><br>
	ID：<input type="text" id="customerId">
	Name：<input type="text" id="customerName"><br>
	token:<input type="text" id="token" value="1234567890">※httpヘッダからセキュリティ情報送信のテスト<br>
	<button onclick="Efw('helloRestAPI_submit',{mode:'1'})">顧客追加</button>
	<button onclick="Efw('helloRestAPI_submit',{mode:'2'})">顧客変更</button>
	<button onclick="Efw('helloRestAPI_submit',{mode:'3'})">顧客削除</button>
	<button onclick="Efw('helloRestAPI_submit',{mode:'4'})">顧客取得</button><br><br>
	<textarea style="width:800px;height:300px;">
	</textarea><br><br>
	<button onclick="Efw('helloRestAPI_submit',{mode:'9'})">終了（テーブル削除）</button><br><br>
</BODY>
</HTML>
```

# Js Event
```javascript
var helloRestAPI_submit={};
helloRestAPI_submit.paramsFormat={
	mode:null,
	"#customerId":null,
	"#customerName":null,
	"#token":null,
};
helloRestAPI_submit.fire=function(params){
	if (params.mode=="0"){
		db.change("helloRestAPI","createTbl",{});
		return new Result().alert("テーブルを作成しました。");
	}else if (params.mode=="9"){
		db.change("helloRestAPI","dropTbl",{});
		return new Result().alert("テーブルを削除しました。");
	}
	var url="http://localhost:8080/helloworld/efwRestAPI/customer";
	try{
		var ret=null;
		if (params.mode=="1"){//新規追加の場合
			ret=rest.post(url,
				{id:params["#customerId"],nm:params["#customerName"]},
				{token:params["#token"]});
		}else if (params.mode=="2"){//更新の場合
			ret=rest.put(url+"/"+params["#customerId"],
				{nm:params["#customerName"]},
				{token:params["#token"]});
		}else if (params.mode=="3"){//削除の場合
			ret=rest.delete(url+"/"+params["#customerId"],{token:params["#token"]});
		}else if (params.mode=="4"){//取得の場合
			ret=rest.get(url+"/"+params["#customerId"],{token:params["#token"]});
		}
		return new Result()
		.runat("body")
		.withdata({
			"textarea":rest.getStatus()+"\n"+JSON.stringify(ret),
		});
	}catch(e){//失敗の場合
		return new Result()
		.runat("body")
		.withdata({
			"textarea":rest.getStatus()+"\n"+e.getMessage(),
		});
	}
}
```

# RestAPI Event
```javascript
var customer={};
customer.POST=function(keys,params){//新規作成
	var token=Packages.efw.framework.getRequest().getHeader("token");
	if("1234567890"!=token){throw new Error("セキュリティエラー");}
	db.change("helloRestAPI","insertRow",{"id":params.id,"name":params.nm});
	return {url:"efwRestAPI/customer/"+params.id}
};
customer.PUT=function(keys,params){//更新
	var token=Packages.efw.framework.getRequest().getHeader("token");
	if("1234567890"!=token){throw new Error("セキュリティエラー");}
	var rt=db.change("helloRestAPI","updateRow",{"id":keys[0],"name":params.nm});
	if (rt==0) throw new Error("更新対象のデータは存在しません。");
	return null;
};
customer.DELETE=function(keys){//削除
	var token=Packages.efw.framework.getRequest().getHeader("token");
	if("1234567890"!=token){throw new Error("セキュリティエラー");}
	var rt=db.change("helloRestAPI","deleteRow",{"id":keys[0]});
	if (rt==0) throw new Error("削除対象のデータは存在しません。");
	return null;
};
customer.GET=function(keys){//取得
	var token=Packages.efw.framework.getRequest().getHeader("token");
	if("1234567890"!=token){throw new Error("セキュリティエラー");}
	return db.select("helloRestAPI","selectRow",{"id":keys[0]}).getSingle();
};
```

# Sql
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqls>
<sqls>
<sql id="createTbl">
	CREATE TABLE tbl_customer(
		id character varying(10) NOT NULL,
		name character varying(20),
		CONSTRAINT tbl_customer_pkey PRIMARY KEY (id)
	)
</sql>
<sql id="dropTbl">
	DROP TABLE tbl_customer;
</sql>
<sql id="selectRow">
	SELECT
		id,
		name
	FROM tbl_customer
	WHERE
		id=:id;
</sql>
<sql id="insertRow">
	INSERT INTO tbl_customer(
		id,
		name
	)VALUES (
		:id,
		:name
	);
</sql>
<sql id="updateRow">
	UPDATE tbl_customer
	SET
		name=:name
	WHERE id=:id;
</sql>
<sql id="deleteRow">
	DELETE FROM tbl_customer
	WHERE id=:id;
</sql>
</sqls>
```

# Explanation


POST：insert, url http://localhost:8080/helloworld/efwRestAPI/customer
The return value is the URL of the inserted data, the http status is 200
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/c3f4565c-4627-1982-c647-04ff71dcd266.png)
PUT：update, url http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
No return value, http status is 204
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/1fc29609-f85e-7efd-2142-0fcc0d158eaf.png)

GET：acquisition, http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
The return value is the retrieved data, http status is 200
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/fae71c61-261e-be52-fa93-53048a95d107.png)

DELETE：delete, http://localhost:8080/helloworld/efwRestAPI/customer/[customerID]
No return value, http status is 204
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/378b7656-5770-51e5-2e0b-8ae47cacbf1e.png)

When an error occurs,
For example, in the case of duplicate insert keys, no update/delete data, etc.
Return value is error information, http status is 500
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/3ca21048-f73c-d7b8-3e7e-ef8631f7c7ce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/c311f9b6-d2f6-b7e3-75b6-a7d3b0231fc1.png)

# Test tool connection
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/e0c31519-6c91-c2fb-dfea-1f00c1789f86.png)

# Test from browser
When testing from a browser, the purpose is to see if the implementation is compatible with cors.
```jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="efw" uri="efw" %>
<!DOCTYPE HTML>
<HTML>
<HEAD>
	<title>Rest API Server and Client Test</title>
	<efw:Client lang="jp"/>
</HEAD>
<BODY>
	ID：<input type="text" id="customerId">
	Name：<input type="text" id="customerName"><br>
	token:<input type="text" id="token" value="1234567890">※httpヘッダからセキュリティ情報送信のテスト<br>

<script>
	function browserTest(samedomain){
		var domain=samedomain?"localhost":"127.0.0.1";
		var url="http://"+domain+":8080/helloworld/efwRestAPI/customer/"+$("#customerId").val();
		$.ajax({
			url:url,
			xhrFields: { withCredentials: true },
			headers:{ token:$("#token").val()},
			type: "GET",
			cache: false,
			async: true,
			dataType: "json",// send or get data by json type
			contentType: "application/json;charset=UTF-8",
			success:function(result){
				window.alert(JSON.stringify(result));
			},
			error:function(errorResponse){
				window.alert(JSON.stringify(errorResponse));
			}
		})
	}
</script>
<button onclick="browserTest(true)">ブラウザーテスト</button>
<button onclick="browserTest(false)">別ドメインテスト</button>
</BODY>
</HTML>
```
The two buttons send from localhost and 127.0.0.1 respectively. And when you compare it with the referer, one will always be judged as cors.
The first time is to send options.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/bc8466e7-89db-5432-e720-75529f32c8dc.png)
The second time is a get transmission.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476221/c2c8bf7e-42c7-cc0b-8e9d-d1f55c8ef6ab.png)

This is a link for explanations related to cors.
https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34

# Environmental Preparation
Since DB is also used, please refer to the following article.
https://qiita.com/changkejun/items/b273b3ae64c76e5b016a

This sample can be downloaded from the link below.

https://github.com/efwGrp/qittaSamples