web-dev-qa-db-ja.com

CXF JAXRS-日付をQueryParamとして渡す方法

次のように定義されたサービスがあります。

public String getData(@QueryParam("date") Date date)

私はクライアントからJava.util.Dateを渡そうとしています(これは一般的なHTTPクライアントやブラウザではなく、CXFのjaxrs:clientです)。

私のサービスは、HTTP URLでThu Mar 01 22:33:10 IST 2012として日付を受け取ります。 CXFはこの文字列を使用してDateオブジェクトを作成できないため、クライアントは404エラーを受け取ります。サービス側でParameterHandlerを使用しようとしましたが、特定の形式の日付を期待していないため、正常に解析できません。

この投稿 のように、Dateを渡すことはそのままで動作するはずですが、基本的なケースを動作させることはできません。クライアントからサービスにDateオブジェクトを正常に渡すために何かする必要がありますか?ヘルプを感謝します。

ありがとう

44
domino

問題は、JAX-RSがパラメーターのアンバンドリングを次の2つの方法のいずれかで行うことを指示していることです。

  1. パラメーターBeanには、ストリングを受け入れるパブリックコンストラクターがあります
  2. パラメーターBeanには、静的valueOf(String)メソッドがあります。

あなたの場合、Dateは、クライアントが送信している入力形式を処理できないDate(String)コンストラクターによってアンバンドルされています。これを改善するためのオプションがいくつかあります。


オプション1

クライアントに送信する前に日付の形式を変更するよう依頼してください。これは理想ですが、おそらく達成するのが最も難しいでしょう!


オプション2

クレイジーな日付形式を処理します。これのオプションは次のとおりです。

文字列を受け入れるようにメソッドシグネチャを変更します。それからDateオブジェクトを作成し、それが失敗した場合は、独自のカスタムSimpleDateFormatクラスを使用して解析します。

_static final DateFormat CRAZY_FORMAT = new SimpleDateFormat("");

public String getData(@QueryParam("date") String dateString) {
    final Date date;
    try {
        date = new Date(dateString); // yes, I know this is a deprecated method
    } catch(Exception e) {
        date = CRAZY_FORMAT.parse(dateString);
    }
}
_

上記のロジックを実行する独自のパラメータークラスを定義します。ロジックを起動する文字列コンストラクターまたは静的valueOf(String)メソッドを指定します。すべてのことを言って完了した日付を取得します。

_public class DateParameter implements Serializable {
    public static DateParameter valueOf(String dateString) {
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }

    private Date date;
    // Constructor, Getters, Setters
}

public String getData(@QueryParam("date") DateParameter dateParam) {
    final Date date = dateParam.getDate();
}
_

または、最後に、日付のパラメーターハンドラーを登録できます。そのロジックは、上記の他のオプションで説明したものと単純に同じです。少なくともCXFを使用する必要があることに注意してください2.5.3デフォルトのアンバンドリングロジックを試行する前にパラメーターハンドラーを評価するため

_public class DateHandler implements ParameterHandler<Date> {
    public Map fromString(String s) {
        final Date date;
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }
}
_
56
Perception

Percepitonの答え は非常に便利でしたが、ParameterHandlerはApache-cxf 3.0で非推奨になりました。 Apache-cxf 3.0移行ガイド を参照してください。

CXF JAX-RS ParameterHandlerは削除されました。JAX-RS2.0 ParamConverterProviderを使用してください。

ParamConverterProviderを使用して例を追加します。

public class DateParameterConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
        if (Date.class.equals(type)) {
            @SuppressWarnings("unchecked")
            ParamConverter<T> paramConverter = (ParamConverter<T>) new DateParameterConverter();
            return paramConverter;
        }
        return null;
    }

}

public class DateParameterConverter implements ParamConverter<Date> {

    public static final String format = "yyyy-MM-dd"; // set the format to whatever you need

    @Override
    public Date fromString(String string) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            return simpleDateFormat.parse(string);
        } catch (ParseException ex) {
            throw new WebApplicationException(ex);
        }
    }

    @Override
    public String toString(Date t) {
        return new SimpleDateFormat(format).format(t);
    }

}

@SuppressWarningsは、コンパイル中の「未チェックまたは安全でない操作」の警告を抑制するために必要です。詳細については、「 未チェックのキャスト警告に対処する方法 」を参照してください。

ParamConverterProviderはプロバイダーとして登録できます。ここに私がそれをした方法があります:

  <jaxrs:server id="myService" address="/rest">
      <jaxrs:serviceBeans>
           ...
      </jaxrs:serviceBeans>

      <jaxrs:providers>
          <ref bean="dateParameterConverterProvider" />
      </jaxrs:providers>
  </jaxrs:server>

  <bean id="dateParameterConverterProvider" class="myPackage.DateParameterConverterProvider"/>

詳細については、 Apache-cxf JAX-RS:Services Configuration を参照してください。

13
Christophe Weis

カスタムDateParamクラスを使用するのが最も安全なオプションのようです。次に、そのメソッドシグネチャを基にして、valueOf()メソッドまたはクラスコンストラクター内にい変換ロジックを実装できます。また、プレーンな文字列を使用するよりも自己文書化されています

1
Cristian Botiza

@Perceptionは、オプション2で、日付を処理できることを示唆しています。ただし、次を使用する必要があります。

private Date getDateFromString(String dateString) {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        Date date = df.parse(dateString);
        return date;
    } catch (ParseException e) {
        //WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
    }
}

リソース内から次のように呼び出します

Date date = getDateFromString(dateString);//dateString is query param.
0
kasavbere