jersey-clientでリクエスト/レスポンスのログを出す

# やりたいこと

リクエスト/レスポンスのbodyをログに出したい。

# 依存関係

```xml
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>2.35</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>2.35</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>2.35</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.7</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.7</version>
        </dependency>
    </dependencies>
```

# フィルタの実装

リクエストはノーチェックでjsonとしてパースしているので、実際に使用する場合は`clientRequestContext.getMediaType()`でタイプチェックしたほうがよい。

```java
package jp.co.neosystem.wg;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import java.io.*;

public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter  {

	private static final Logger LOGGER = LoggerFactory.getLogger(LoggingFilter.class);

	@Override
	public void filter(ClientRequestContext clientRequestContext) throws IOException {
		if (!clientRequestContext.hasEntity()) {
			return;
		}

		Object entity = clientRequestContext.getEntity();

		ObjectMapper mapper = new ObjectMapper();
		String entityString = mapper.writeValueAsString(entity);

		LOGGER.info(entityString);
		return;
	}

	@Override
	public void filter(ClientRequestContext clientRequestContext, ClientResponseContext clientResponseContext) throws IOException {
		if (!clientResponseContext.hasEntity()) {
			return;
		}

		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		try (InputStream stream = clientResponseContext.getEntityStream()) {
			while (true) {
				byte[] b = new byte[1024];
				int length = stream.read(b);
				if (length <= 0) {
					break;
				}
				outputStream.write(b, 0, length);
			}
		}
		ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
		clientResponseContext.setEntityStream(inputStream);

		LOGGER.info(outputStream.toString());
		return;
	}
}
```

# 利用法

```java

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;

// 途中省略
	private static final Client CLIENT;

	static {
		CLIENT = ClientBuilder.newClient().register(LoggingFilter.class);
	}
```