RESTEasyとJPAとAngularJSを使ってWebアプリを作ってみる７（サービスクラスの公開）

[RESTEasyとJPAとAngularJSを使ってWebアプリを作ってみる４（JPAでデータ取得）](http://qiita.com/1roh/items/0c71441371f3ba76b3c9)で作成したサービスクラス公開してブラウザからアクセスできるようにします。

# web.xml の編集
RESTEasyが仕事をするように以下のように編集します。

```xml:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

	<display-name>homework</display-name>

	<context-param>
		<param-name>resteasy.scan</param-name>
		<param-value>true</param-value>
	</context-param>
	<context-param>
		<param-name>resteasy.scan.provider</param-name>
		<param-value>true</param-value>
	</context-param>

	<listener>
		<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
	</listener>

	<servlet>
		<servlet-name>JAX-RS Servlet</servlet-name>
		<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>JAX-RS Servlet</servlet-name>
		<url-pattern>/api/*</url-pattern>
	</servlet-mapping>

</web-app>
```

# アノテーションの指定
サービスクラスにアノテーションを設定します。
web.xml の設定で /api/ でリクエストされたものが対象としているので、/api から始まるリクエストにマッピングするようにします。

```java:UserService.java
@Path("/api/user")
public class UserService extends BaseService {
	..........
	@Path("/login")
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	@ServiceLogging
	public Responce login(User auth) {
		Responce responce = new Responce();
		User user = authenticate(auth.getAccountId(), auth.getPassword());
		responce.setUser(user);
		if (user != null) {
			responce.setAnswers(getLatestWrongAnswers(user));
		}
		return responce;
	}
	..........
}
```

- ユーザサービスクラスなので /api/user でリクエストされたものを対象とするように、クラスに @Path アノテーションを指定します。
- ログイン処理は /api/user/login でリクエストされたときに実行されるように @Path アノテーションで /login を指定します。
- POST リクエスト時に実行されるように @POST アノテーションを指定します。
- 要求は accountId と password 要素を持った JSON で行うので @Consumes アノテーションで JSON を指定します。
- 応答は User と List<Answer> を持ったビーンを JSON で返すので @Produces アノテーションで JSON を指定します。
- @ServiceLogging アノテーションは入出力をログに出したいので指定します。これについては次に説明します。

# サービスの入出力をログで出力
フィルタークラスを作成してログを出力します。

アノテーション定義は以下の通りです。

```java:ServiceLogging.java
package homework.extend;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.ws.rs.NameBinding;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,
         ElementType.METHOD})
public @interface ServiceLogging {
}
```

フィルタークラスは以下の通り。
ログレベルがデバッグ以上の場合にログを出力するようにしてあります。

```java:ServiceLoggingFilter.java
package homework.extend;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map.Entry;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;

import org.apache.commons.io.IOUtils;
import org.jboss.logging.Logger;

/**
 * ロギングフィルタークラス。
 * @author satake
 */
@ServiceLogging
@Provider
public class ServiceLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter {

	private Logger logger = Logger.getLogger(ServiceLoggingFilter.class);

	/**
	 * リクエストフィルター。
	 */
	@Override
	public void filter(ContainerRequestContext request) throws IOException {
		if (logger.isDebugEnabled()) {
			UriInfo uriInfo = request.getUriInfo();
			logger.debug("******************** Request ********************");
			logger.debug("  Method: " + request.getMethod());
			logger.debug("  Path:   " + uriInfo.getPath());
			logger.debug("  Header:");
			for (Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
				logger.debug("    " + entry.getKey() + ": " + entry.getValue());
			}
			if (request.getEntityStream() != null) {
				logger.debug("  Entity Stream:");
				ByteArrayOutputStream output = new ByteArrayOutputStream();
				IOUtils.copy(request.getEntityStream(), output);
				byte[] requestData = output.toByteArray();
				logger.debug("    " + new String(requestData, "UTF-8"));
				request.setEntityStream(new ByteArrayInputStream(requestData));
			}
			logger.debug("*************************************************");
		}
	}

	/**
	 * レスポンスフィルター。
	 */
	@Override
	public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException {
		if (logger.isDebugEnabled()) {
			logger.debug("******************** Response ********************");
			logger.debug("  Status: " + response.getStatus());
			logger.debug("  Entity: " + response.getEntity());
			logger.debug("**************************************************");
		}
	}
}
```

# サーバーの作成
とりあえず、eclipse からローカルの wildfly で実行するようにサーバーを作成します。

- サーバービューがパースペクティブに存在しない場合は、eclipse メニューの「ウインドウ」－「ビューの表示」－「その他」を選択し、「サーバー」－「サーバー」を選択して、「OK」ボタンをクリックします。
- サーバービューで「使用可能なサーバーがありません。このリンクをクリックして新規サーバーを作成してください」リンクをクリックし、「JBoss コミュニティー」－「WildFly  9.x 」を選択し、「次へ」ボタンをクリックします。
- 「新規 JBoss サーバーを作成します」画面ではデフォルト設定のまま、「次へ」ボタンをクリックします。
- 「追加および除去」画面で、左側にある homework を選択して「追加」ボタンをクリックして、「完了」ボタンをクリックします。

# サーバーの起動設定
log4jdbc を有効にするために、ログデリゲーターを指定します。

- サーバービューに表示されている「Wildfly 9.x」をダブルクリックします。
- 「概要」画面の一般情報にある「起動構成を開く」リンクをクリックします。
- 「起動構成プロパティーの編集」画面の「引数」タブの「VM引数」の最後に「-Dlog4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator」を追記して、「OK」ボタンをクリックします。

# ログの設定
アプリケーションのデバッグログの出力と、単体テストと同様のlog4jdbcの設定を行います。
wildfly（E:\develop\pleiades\wildfly\wildfly-9.0.2.Final）配下の standalone\configuration にある standalone.xml を編集します。

```xml:standalone.xml
    ..........
    <profile>
        <subsystem xmlns="urn:jboss:domain:logging:3.0">
            <console-handler name="CONSOLE">
                <!-- コンソールの出力レベルを「INFO」⇒「DEBUG」に変更 -->
                <level name="DEBUG"/>
                <formatter>
                    <named-formatter name="COLOR-PATTERN"/>
                </formatter>
            </console-handler>
            .........
            <!-- ロガーの指定を追加する -->
            <logger category="homework">
                <level name="DEBUG"/>
            </logger>
            <logger category="jdbc">
                <level name="ERROR"/>
            </logger>
            <logger category="jdbc.sqltiming">
                <level name="INFO"/>
            </logger>
            <logger category="jdbc.resultsettable">
                <level name="INFO"/>
            </logger>
            <root-logger>
                <level name="INFO"/>
                <handlers>
                    <handler name="CONSOLE"/>
                    <handler name="FILE"/>
                </handlers>
            </root-logger>
            .........
```

# サーバーの起動確認
- サーバービューに表示されている「Wildfly 9.x」で右クリックし、「開始」を選択します。
- エラーがなく（スタックがログに表示されない）「WildFly Full 9.0.2.Final (WildFly Core 1.0.2.Final) started in 5294ms」というメッセージが表示されれば、設定に問題はなさそうです。


[RESTEasyとJPAとAngularJSを使ってWebアプリを作ってみる８（画面）](http://qiita.com/1roh/items/397ba092a44473cbd224)へ