JAX-RS/ジャージーのカスタマイズについてのエラー処理?
-
06-09-2019 - |
質問
私は学習JAX-RS(通称:JSR-311)を用いています。私に正常に作成したルー資源及びamので色々と遊んでいてパラメータ:
@Path("/hello")
public class HelloWorldResource {
@GET
@Produces("text/html")
public String get(
@QueryParam("name") String name,
@QueryParam("birthDate") Date birthDate) {
// Return a greeting with the name and age
}
}
この作品は、応してフォーマットを問わず現在のロケールで理解することを目指して日(String)コンストラクタ(YYYY/mm/dd mm/dd/YYYY).でもいいの価値が無効または未だに解明されていないか404に応じます。
例えば:
GET /hello?name=Mark&birthDate=X
404 Not Found
たいのですがカスタマイズ本的に振る舞えるのでしょうか?その国の異なる応答コード(おそらく"400Bad Request")?何かいつもログインエラー?その追加記述の問題("悪い日付フォーマット)カスタムヘッダへの援助をブ?または戻り全体のエラー応答の内容の詳細は、5xx状態コードについて教えてください。
解決
JAX-RSとエラー処理の動作をカスタマイズするには、いくつかのアプローチがあります。ここでは簡単な方法の3つがあります。
第1のアプローチはWebApplicationExceptionを拡張例外クラスを作成することである。
例:
public class NotAuthorizedException extends WebApplicationException {
public NotAuthorizedException(String message) {
super(Response.status(Response.Status.UNAUTHORIZED)
.entity(message).type(MediaType.TEXT_PLAIN).build());
}
}
そしてスローするように、この新規例外を作成します単純ます:
@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
// An unauthorized user tries to enter
throw new NotAuthorizedException("You Don't Have Permission");
}
お知らせ、あなたはWebApplicationExceptionは、実行時例外であるため、throws節で例外を宣言する必要はありません。これは、クライアントに401レスポンスを返します。
二かつ簡単なアプローチは、単にあなたのコードに直接WebApplicationExceptionのインスタンスを構築することです。このアプローチは、独自のアプリケーションの例外を実装する必要はありません限り動作します。
例:
@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
// An unauthorized user tries to enter
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
このコードは、あまりにもクライアントに401を返します。
もちろん、これは単純な例です。必要な場合は、例外がはるかに複雑にすることができ、そして、あなたがする必要があり、これまでどのようなHTTPレスポンスコードを生成することができます。
もう一つのアプローチは、既存の例外、@Providerアノテーションを付けExceptionMapperインタフェースを実装する小さなラッパークラスと、おそらくObjectNotFoundExceptionをラップすることです。これは、ラップされた例外が発生した場合、ExceptionMapperで定義された応答コードを返すことを、JAX-RSランタイムに指示します。
他のヒント
@Provider
public class BadURIExceptionMapper implements ExceptionMapper<NotFoundException> {
public Response toResponse(NotFoundException exception){
return Response.status(Response.Status.NOT_FOUND).
entity(new ErrorResponse(exception.getClass().toString(),
exception.getMessage()) ).
build();
}
}
クラスの上に作成します。これは、404(NotFoundException)を処理すると、ここでtoResponse方法では、あなたのカスタム応答を与えることができます。同様にカスタマイズされた応答を提供するために、マッピングする必要がありますParamExceptionなどがあります。
ジャージーはcom.sun.jersey.api.ParamExceptionをスローします:
@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
@Override
public Response toResponse(ParamException exception) {
return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
}
}
またQueryParam注釈付きの変数のための再利用可能なクラスを書くことができます。
public class DateParam {
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
private Calendar date;
public DateParam(String in) throws WebApplicationException {
try {
date = Calendar.getInstance();
date.setTime(format.parse(in));
}
catch (ParseException exception) {
throw new WebApplicationException(400);
}
}
public Calendar getDate() {
return date;
}
public String format() {
return format.format(value.getTime());
}
}
このようにそれを使用します:
private @QueryParam("from") DateParam startDateParam;
private @QueryParam("to") DateParam endDateParam;
// ...
startDateParam.getDate();
エラー処理は(400レスポンスを投げる)この場合は自明であるが、、このクラスを使用すると、あなたは因子アウトするなどのロギングなどがあります一般的にパラメータ処理することができます。
1つの明白な解決策:あなた自身を日付に変換、文字列に取ります。そうすれば、あなたが望む形式、キャッチ例外とどちらかの再スローを定義したり、送信されているエラーをカスタマイズすることができます。 解析するために、SimpleDateFormatのは、正常に動作する必要があります。
私はあまりにもデータ型のハンドラをフックする方法がある確信している、おそらく簡単なコードの少しは、あなたが、この場合に必要なすべてのです。
Iすぎ StaxMan の希望のようなおそらく、必要に応じて再スロー、QueryParamはStringとして、その後、変換を処理することを実装します。
ロケール固有の動作は、希望と期待される動作は、の場合は、400 BAD REQUESTエラーを返すために、次の使用することになります:
throw new WebApplicationException(Response.Status.BAD_REQUEST);
<のhref = "http://www.jboss.org/file-access/default/members/resteasy/freezone/docs/1.0.0.GA/javadocs/javax/ws/rs/のJavadocを参照してくださいコア/ Response.Status.html」のrel = "nofollowをnoreferrer"> javax.ws.rs.core.Response.Status をより多くのオプションのために。
@QueryParam文書という
"の型の注釈を付けられたパラメータには、分野や産 のいずれかの
1)プリミティブ型
2)コンストラクタを受け入れるシングル 文字列引数
3についてはstaticという名前のメソッドvalueOfはfromString を受け入れる単一の文字列の引数(例えば、 整数となります。valueOf(String))
4)しての登録の実施 javax.ws.rs.ext.ParamConverterProvider JAX-RS延長SPIる を返しまjavax.ws.rs.ext.ParamConverterインスタンスできる、"から 文字列に変換します。
5)リストの設定または SortedSet、Tを満たす2、3、4ます。この結果、 収集は読み取り専用になります。"
したい場合は管理対応がユーザーがクエリパラメータの文字列形式変換できませんごシリコーンコーティング処理を、スローされる可能性がありますWebApplicationException.Dropwizardに付属の以下*Param授業の際に使用できます。
BooleanParam,DateTimeParam,IntParam,LongParam,LocalDateParam,NonEmptyStringParam,UUIDParam.見 https://github.com/dropwizard/dropwizard/tree/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/params
が必要な場合はJoda DateTime、利用Dropwizard DateTimeParam.
いになる場合は、あらかなニーズに合わせを明らかにし、自分の延長AbstractParam.オーバーライド構文解析方法。が必要な場合は制御エラー応答体、オーバーライドエラー。
良い記事はコーダヘールはこの時 http://codahale.com/what-makes-jersey-interesting-parameter-classes/
import io.dropwizard.jersey.params.AbstractParam;
import java.util.Date;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
public class DateParam extends AbstractParam<Date> {
public DateParam(String input) {
super(input);
}
@Override
protected Date parse(String input) throws Exception {
return new Date(input);
}
@Override
protected Response error(String input, Exception e) {
// customize response body if you like here by specifying entity
return Response.status(Status.BAD_REQUEST).build();
}
}
日(String arg)コンストラクタでは推奨されていません。混雑して待たされることがJava8日に授業の場合Java8.その他joda日時を推奨します。
これは実際には正しい動作です。ジャージーは、あなたの入力のためのハンドラを見つけようとしますと、提供された入力からオブジェクトを構築しようとします。この場合、Xは、コンストラクタに提供された値を使用して新しいDateオブジェクトを作成しようとします。これは無効な日付であることから、慣例によりジャージーの404を返します。
何を書き換え、Stringとして誕生日を入れて行うことができ、その後、(解析し、あなたが望むものを得ることはありませんならば、あなたは例外マッピングメカニズムのいずれかによって、あなたが望む任意の例外をスローすることは自由ですしてみてください)いくつかがあります。
念のため@Steven Lavineの答えへの拡張として、あなたは、ブラウザのログインウィンドウを開くようにしたいです。私はそれは難しい適切に応答( MDN HTTP認証)ユーザがまだ認証されなかった場合のフィルタから
このヘッダの追加変更に注意し、ブラウザのログインを強制的にレスポンスを構築するために私を助けました。これは401にステータスコードを設定し、ユーザー名/パスワードのダイアログを開くには、ブラウザの原因となるヘッダーを設定します。
// The extended Exception class
public class NotLoggedInException extends WebApplicationException {
public NotLoggedInException(String message) {
super(Response.status(Response.Status.UNAUTHORIZED)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.header("WWW-Authenticate", "Basic realm=SecuredApp").build());
}
}
// Usage in the Filter
if(headers.get("Authorization") == null) { throw new NotLoggedInException("Not logged in"); }