6

私は多くのリソースを持っているJerseyでアプリを開発しています。これらのリソースの主な機能はさまざまですが、多くの一般的な方法(リスト、読み取り、更新など)を共有しています。アプリはGoogleAppEngineで実行され、依存性注入にGuiceを使用します。

私の最初のアプローチは、すべての共通ロジックを含む汎用AbstactResourceを用意することでした。これは、必要なカスタムメソッドを追加する他のすべてのリソースによってそれぞれ拡張されます。

public class AbstractResource<T> {

@GET
public ListPage<T> list(@QueryParam("limit") Integer limit,
    @QueryParam("start") Integer start) {
    // ... implementation
}

@GET
@Path("/{id}")
public T get(@PathParam("id") Long id) {
    // ... implementation
}

サンプルリソースは次のようになります。

public class TenantResource extends AbstractResource<Tenant> {
    // custom resource related methods here
}

この場合、すべてが正常に機能します。抽象化のレベルをもう1つ追加すると、問題が発生します。一部のリソースの履歴と変更ログのみを保存したい場合を考えてみましょう。必要な機能を追加するAudiatableResourceと呼ばれるAbstractResourceを拡張するもう1つの抽象クラスを作成しました。

public abstract class AuditableResource<T extends AuditableModel> 
    extends AbstractResource {
        // here I override update and create methods to save changelogs
}

ご覧のとおり、この場合のtypeパラメーターは変更されています(現在はAuditableModelを拡張しています)。

新しい具体的なリソースは次のようになります。

public class PropertyResource extends AuditableResource<Tenant> {
    // custom resource related methods here
}

この場合、すべては引き続き機能しますが、今回は起動時に多くの警告メッセージが表示されます。

WARNING: Return type T of method public T com.pkg.AbstractResource.get(java.lang.Long) is not resolvable to a concrete type
WARNING: Return type T of method public T com.pkg.AbstractResource.getNew() is not resolvable to a concrete type
WARNING: Return type com.pkg.data.ListPage<T> of method public com.pkg.ListPage<T> com.pkg.AbstractResource.list(java.lang.Integer,java.lang.Integer) is not resolvable to a concrete type

このアプローチがJerseyを使用して正しいかどうか、そしてこのメ​​ッセージを無視できるかどうかは本当に疑問です。リソースが多数ある場合に、リソースがどのように編成されているかを知ることは興味深いでしょう。

4

1 に答える 1

4

1つの方法は、リソースの定義を実装から分離することです。

  • 提供したいさまざまなサービスを定義する、非常に単純なリソースクラスを用意します。このようにして、RESTを通じて公開するAPIを簡単に見つけて監査できます。異なるメソッドはおそらく実装クラスへのデリゲートです
  • リソースのビジネスロジックを実装に実装します。ここでは、継承を使用して一般的な動作を考慮に入れることができます。

実行時にこれらのメッセージを受け取る理由は、jerseyがリソースのタイプに関する実行時情報を使用するためです。ジェネリック型情報はコンパイル時に消去されるため、ジェネリッククラスメソッドの実際の戻り型を取得できません。実装にREST「ファサード」を提供する場合は、これを明示的にすることができます。

public class Facade {
  private final PropertyResource propertyResource;
  public Facade() {
    propertyResource = new PropertyResource();
  }
  @GET
  @Path("somepath")
  public Tenant something() {
    return propertyResource.something();
  }
}
于 2012-05-04T21:18:25.133 に答える