1

jersey-clientを使用してRESTサービスを利用しています。要求されたエンティティとLast-Modifiedヘッダーの両方が必要です。

だから私は次のことをします:

ClientResponse response = webResource.get(ClientResponse.class);
Person person = response.getEntity(Person.class);

それはうまくいきます。応答があり、エンティティ(XML)をPOJOにマーシャリングできます。デバッグして応答のヘッダーを調べると、Last-Modifiedヘッダーセットがあることがわかります。

しかし、私が経由して日付を取得しようとすると

response.getLastModified();

URLConnectionClientHandlerのどこかにNPEがあります。

誰かが私が間違っていることの手がかりを持っていますか?

編集:要求に応じてトレース

java.lang.NullPointerException: null
at com.sun.jersey.api.client.ClientResponse.getLastModified(ClientResponse.java:647) ~[jersey-client-1.12.jar:1.12]
at a.o.u.user.dao.impl.uds.PersonenUdsClient.getPerson(PersonenUdsClient.java:103) ~[um-user-2.5.0-Beta1-SNAPSHOT.jar:na]
at a.o.u.user.dao.impl.UserDaoUdsImpl.mergeWithUdsUser(UserDaoUdsImpl.java:282) ~[um-user-2.5.0-Beta1-SNAPSHOT.jar:na]
at a.o.u.user.dao.impl.UserDaoUdsImpl.getUserWithEmail(UserDaoUdsImpl.java:124) ~[um-user-2.5.0-Beta1-SNAPSHOT.jar:na]
at ...

編集: npeが提案したように、私はコードを掘り下げました。私は問題を見つけたと思います。jersey-clientのほかに、クラスパスにcxfもあります。jerseyとcxfはどちらも、 RuntimeDelegateImplというクラスを提供します。ただし、CXFバージョンにはDateHeaderDelegateはありません。RuntimeDelegateImplの間違ったバージョン(CXF)が使用されていると思います。

今のところ、 RuntimeDelegateImplを明示的に使用するように設定する方法がわかりません。

4

2 に答える 2

2

ソース、ルークを使用してください

バージョン1.12の実装はClientResponse#getLastModified()次のようになります。

/*639*/  /**
/*640*/   * Get the last modified date.
/*641*/   *
/*642*/   * @return the last modified date, otherwise <code>null</code> if not present.
/*643*/   */
/*644*/  public Date getLastModified() {
/*645*/      String d = getHeaders().getFirst("Last-Modified");
/*646*/  
/*647*/      return (d != null) ? dateDelegate.fromString(d) : null;
/*648*/  }

行647を取得するNullPointerExceptionので、それdateDelegateは表示されますnull。これで、dateDelegateオブジェクトは次のように321行目で初期化されます。

/*321*/  protected static final HeaderDelegate<Date> dateDelegate =
/*322*/          RuntimeDelegate.getInstance().createHeaderDelegate(Date.class);

現在、フィールドはであるため、この初期化後に変更することはfinalできません。つまり、最初からです。つまり、何らかの構成の問題があり、デリゲートが作成されません。dateDelegatenull

さらに、デリゲートは次のようにAbstractRuntimeDelegateクラス(ここでは1.12のソース)に作成されます。

/* 88*/  map.put(Date.class, _createHeaderDelegate(Date.class));

このうさぎの穴はどんどん深くなっていくので、ここでやめますが、道はご存知でしょう。

そして最後に、大事なことを言い忘れましたが、デバッガーはあなたの友達、私の友達です;-)

于 2012-06-21T09:26:16.867 に答える
1

それをラップにするために。

問題は、クラスパスにjersey-clientとcxfの両方があることです。RuntimeDelegateImplの両方。ただし、CXFバージョンにはDateHeaderDelegateはありません。RuntimeDelegateImplの間違ったバージョン(CXF)が使用されます。

最終変更ヘッダーを「手動で」取得することで問題を解決しました。

private Date getLastModified(ClientResponse response){
    String lastModifiedString = response.getHeaders().getFirst(
            "Last-Modified");
    if (StringUtils.isEmpty(lastModifiedString)) {
        LOG.warn("Expect to get Last-Modified header when retrieving a Person by pnr "
                + "but there is none.");
        return null;
    } else {
        try {
            // format is Thu, 21 Jun 2012 08:00:42 GMT
            return new SimpleDateFormat(
                    "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US)
                    .parse(lastModifiedString);
        } catch (ParseException e) {
            LOG.error("Could not parse Last-Modified date "
                    + e.getMessage());
            return null;
        }
    }
}

ヒントをnpeしてくれてありがとう。

于 2012-06-22T12:26:48.967 に答える