読者です 読者をやめる 読者になる 読者になる

JAX-RS (Jersey) でパラメータとして独自のクラスをインジェクトする (1)

@QueryParamアノテーションで、パラメータをインジェクトすることができますが(パラメータに含まれない場合はnullになる)、パラメータがあまりに多いとメソッドシグネチャが見にくくなり、値をBeanにコピーしたりするのも面倒です。このような場合には、、

@GET
@Produces({MediaType.APPLICATION_JSON})
public List<Contact> getContacts(@QueryParam("offset") Integer offset, @QueryParam("limit") Integer limit) {
    // 省略
}

UriInfoをインジェクトする

JavaによるRESTfulシステム構築では、以下のように、UriInfoをインジェクトして、そこからMultivaluedMap経由でパラメータを取得する方法が記載されています。

@GET
@Produces({MediaType.APPLICATION_JSON})
public List<Contact> getContacts(@Context UriInfo uiInfo) {
    int offset= uriInfo.getQueryParameters().getFirst("offset")
    int limit = uriInfo.getQueryParameters().getFirst("limit");
    // ....
}

MultivaluedMapからBean(DTOなど)にイテレータ経由でまとめてパラメータをコピーするような使い方もできそうです。

ResourceContextをインジェクトする

これ以外には、クエリパラメータがインジェクトされたBeanを取得する方法があります。例えばリストのページング検索条件用にこんなクラスを作ります。値をインジェクトしたいフィールドにアノテーションを付けておきます。

public class PagingParams {
	@QueryParam("limit")
	private String limit;

	@QueryParam("offset")
	private String offset;

	@QueryParam("sort")
	private String sort;

	@QueryParam("direction")
	private Direction direction;

	public String getLimit() {
		return limit;
	}

	public void setLimit(String limit) {
		this.limit = limit;
	}

	public String getOffset() {
		return offset;
	}

	public void setOffset(String offset) {
		this.offset = offset;
	}

	public String getSort() {
		return sort;
	}

	public void setSort(String sort) {
		this.sort = sort;
	}

	public Direction getDirection() {
		return direction;
	}

	public void setDirection(Direction direction) {
		this.direction = direction;
	}

	/**
	 * ソートの方向
	 */
	public enum Direction{
		ASC, DESC;
	}
}

enumのDirectionも自動で変換してくれます(コンストラクタがString1個のみのか、staticなvalueOf(String)を持つ型は自動変換してくれます)。
リソースクラスでは、ResourceContextをインジェクトして、PagingParamsのオブジェクトを取り出します。

@GET
@Produces({MediaType.APPLICATION_JSON})
public List<Contact> getContacts(@Context ResourceContext rc) {
    PagingParams params = rc.getResource(PagingParams.class);
    // ....    
}

さらに、以下のJerseyのMLにある方法を使えば直接、PagingParamsをインジェクトすることもできるようです。
Jersey - Custom Parameter Binding