1

JerseyTest クラスで奇妙な問題が発生しています。

テスト コードを実行し、 org.glassfish.jersey.message.internal.ReaderInterceptorExecutor の 203 行目にブレーク ポイントを配置すると、リーダーが reader.workers にないことがわかります。ただし、以下に示すように、この MessageBodyReader を ResourceConfig に登録します。

関連するすべてのコードを以下に示します。

私のカスタム MessageBodyReader/Writer

@Provider
@Produces({V1_JSON})
@Consumes({V1_JSON})
public class JsonMessageBodyHandlerV1
    implements
      MessageBodyWriter<Object>,
      MessageBodyReader<Object> {
  ...
}

はい、trueisReadableを返します。

デバッグすると、コードはヒットしますが、ヒットwriteToしませ readFrom

失敗するテスト コード

public class TestLocationResource extends JerseyTest {

  public static class LocationResourceHK2Binder extends AbstractBinder {

    @Override
    protected void configure() {
      // Singleton bindings.
      bindAsContract(LocationDao.class).in(Singleton.class);

      // Singleton instance bindings.
      bind(new FakeLocationDao()).to(LocationDao.class);
    }
  }

  @Test
  public void basicTest() {

    LocationListV1 actualResponse = /**/
    /**/target(LocationResourceV1.PathFields.PATH_ROOT)
    /*   */.path(LocationResourceV1.PathFields.SUBPATH_LIST)
    /*   */.request(V1_JSON)
    /*   */.header(HEADER_API_KEY, "abcdefg")
    /*   */.get(LocationListV1.class);

    assertEquals(10, actualResponse.getLocations().size());
  }

  @Override
  protected Application configure() {
    enable(TestProperties.LOG_TRAFFIC);
    enable(TestProperties.DUMP_ENTITY);

    ResourceConfig rc = new ResourceConfig();
    rc.registerClasses(LocationResourceV1.class, JsonMessageBodyHandlerV1.class);
    rc.register(new LocationResourceHK2Binder());

    return rc;
  }
}

(この例から引っ張ってきます。)

テストしているリソース...

public class LocationResourceV1 implements ILocationResourceV1 {
  ...

  @Inject
  private LocationDao daoLoc;

  private final LocationTranslator translator = new LocationTranslator();

  @Override
  public LocationListV1 listV1(String apiKey) {
    return translator.translate(daoLoc.query(LocationFilters.SELECT_ALL));
  }

  ...

  @VisibleForTesting
  public void setLocationDao(LocationDao dao) {
    this.daoLoc = dao;
  }
}

(@GET などの Web サービス アノテーションがインターフェイスにあることに注意してください。)

この失敗トレースを生成します

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: メディア タイプ = application/vnd.com.company-v1+json、タイプ = クラス com.company.rest.v1.resources.location.json.LocationListV1 の MessageBodyReader が見つかりません。 genericType=class com.company.rest.v1.resources.location.json.LocationListV1. org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:207) で org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutorjava.:139) で org.glassfish.jersey org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851) の .message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109) org.glassfish.jersey.message.internal.

...このコンソール出力で

[...]
INFO: [HttpServer] Started.
Oct 29, 2013 4:26:16 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * LoggingFilter - Request received on thread main
1 > GET http://localhost:9998/location/list
1 > Accept: application/vnd.com.company-v1+json
1 > X-ApiKey: abcdefg

Oct 29, 2013 3:30:21 PM org.glassfish.jersey.internal.Errors logErrors
WARNING: The following warnings have been detected: WARNING: HK2 service reification failed for [com.company.persistence.dao.intf.LocationDao] with an exception:
MultiException stack 1 of 2
java.lang.NoSuchMethodException: Could not find a suitable constructor in com.company.persistence.dao.intf.LocationDao class.
    at org.glassfish.jersey.internal.inject.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:189)
    at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:159)
    at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:125)
    at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:176)
    at org.jvnet.hk2.internal.SystemDescriptor.internalReify(SystemDescriptor.java:649)
    at org.jvnet.hk2.internal.SystemDescriptor.reify(SystemDescriptor.java:604)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.reifyDescriptor(ServiceLocatorImpl.java:396)
    [...]
MultiException stack 2 of 2
java.lang.IllegalArgumentException: Errors were discovered while reifying SystemDescriptor(
    implementation=com.company.persistence.dao.intf.LocationDao
    contracts={com.company.persistence.dao.intf.LocationDao}
    scope=org.glassfish.jersey.process.internal.RequestScoped
    qualifiers={}
    descriptorType=CLASS
    descriptorVisibility=NORMAL
    metadata=
    rank=0
    loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@568bf3ec
    proxiable=null
    proxyForSameScope=null
    analysisName=null
    id=143
    locatorId=0
    identityHashCode=2117810007
    reified=false)
    at org.jvnet.hk2.internal.SystemDescriptor.reify(SystemDescriptor.java:615)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.reifyDescriptor(ServiceLocatorImpl.java:396)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.narrow(ServiceLocatorImpl.java:1916)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.access$700(ServiceLocatorImpl.java:113)
    at org.jvnet.hk2.internal.ServiceLocatorImpl$6.compute(ServiceLocatorImpl.java:993)
    at org.jvnet.hk2.internal.ServiceLocatorImpl$6.compute(ServiceLocatorImpl.java:988)
    [...]
    [...]
    (Above is repeated 4 times)
    [...]
    [...]

これに続いて、成功した応答があったことを意味します

Oct 29, 2013 3:30:22 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * LoggingFilter - Response received on thread main
2 < 200
2 < Date: Tue, 29 Oct 2013 22:30:21 GMT
2 < Content-Length: 16
2 < Content-Type: application/vnd.com.company-v1+json
{"locations":[]}

Oct 29, 2013 3:30:22 PM org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory$GrizzlyTestContainer stop
INFO: Stopping GrizzlyTestContainer...
Oct 29, 2013 3:30:22 PM org.glassfish.grizzly.http.server.NetworkListener stop
INFO: Stopped listener bound to [localhost:9998]

誰が私が間違っているのか知っていますか?

4

1 に答える 1

3

最初のスタック トレースは、メッセージ本文プロバイダーをクライアントに登録していない (そのため見つからない) ため、クライアントから取得されます。JerseyTest#configureメソッドは、サーバー側のみを構成するために使用されることになっています。クライアント側で使用するためのJerseyTest#configureClientという別のメソッドがあります。カスタム プロバイダーを使用する場合は、両方のメソッドをオーバーライドする必要があります。

2 番目のスタック トレースは、LocationResourceHK2Binder. に

bindAsContract(LocationDao.class).in(Singleton.class);

クラスをシングルトンとしてインスタンス化する必要があることをHK2に伝えてLocationDaoおり、HK2はそれをLocationDao型に注入します。次のようなものを使用するようにバインダーを変更することをお勧めします。

bind(new FakeLocationDao()).to(LocationDao.class);

このトピックの詳細については、カスタム インジェクションとライフサイクル管理を参照してください。

于 2013-10-30T10:25:22.650 に答える