私は多くのリソースを持っている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を使用して正しいかどうか、そしてこのメッセージを無視できるかどうかは本当に疑問です。リソースが多数ある場合に、リソースがどのように編成されているかを知ることは興味深いでしょう。