これはより一般的なJava質問ですが、私は何をしようとしているのかを説明し、誰かが私に正しい方法を教えてくれることを願っています。Dropwizard抽象リソースデザイン
私のすべてのリソースが拡張できる汎用抽象クラスを作成しようとしています。
抽象クラスは、標準のもののための基本的なCRUD実装を持っている
私は単純に@Path("/movies")
public class MovieResource extends AbstractResource {
public MovieResource(MovieRepository repository) {
super(repository);
}
}
をやって問題なくこれを使用することができますし、私は今、すべてのメソッドにアクセスすることができ、必要に応じて上書き
@Produces("application/vnd.api+json")
@Consumes("application/vnd.api+json")
public abstract class AbstractResource {
static final Logger LOGGER = LoggerFactory.getLogger(AbstractResource.class);
AbstractRepository repository;
AbstractResource(AbstractRepository repository) {
this.repository = repository;
}
@GET
public Response getAll(@Auth User user, @QueryParam("query") String query) {
String result = query != null ? repository.getByQuery(query) : repository.getAll();
return Response.status(Response.Status.OK).entity(result).build();
}
@GET
@Path("/{id}")
public Response getById(@Auth User user, @PathParam("id") String id) {
String result = repository.getById(id);
return Response.status(Response.Status.OK).entity(result).build();
}
@POST
public Response save(@Auth User user, String payload) {
String result = repository.save(payload);
return Response.status(Response.Status.OK).entity(result).build();
}
@PATCH
@Path("/{id}")
public Response update(@Auth User user, @PathParam("id") String id, String payload) {
String result = repository.update(payload);
return Response.status(Response.Status.OK).entity(result).build();
}
@DELETE
@Path("/{id}")
public Response delete(@Auth User user, @PathParam("id") String id) {
repository.delete(id);
return Response.status(Response.Status.NO_CONTENT).build();
}
}
。
問題が発生するのは、メソッドをオーバーロードする必要があるときです。一例として、抽象クラスから最初のgetAll
方法を取る、私は唯一のMovie.class
@Path("/movies")
public class MovieResource extends AbstractResource {
public MovieResource(MovieRepository repository) {
super(repository);
}
@GET
public Response getAll(@Auth User user, @QueryParam("query") String query, @QueryParam("limit") String limit, @QueryParam("page") String page) {
String result = repository.getPaginated(limit, page);
return Response.status(Response.Status.OK).entity(result).build();
}
}
でパラメータを変更したいのでgetAll
方法はただMovie.class
のパラメータの異なるセットを持っています。これは、抽象の元getAll
方法が既に@GET
注釈を持っているため
[[FATAL] A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by"@Consumes" and "@Produces" annotations at Java methods public javax.ws.rs.core.Response space.cuttlefish.domain.resources.MovieResource.getAll(space.cuttlefish.domain.model.User,java.lang.String,java.lang.String,java.lang.String) and public javax.ws.rs.core.Response space.cuttlefish.domain.resources.AbstractResource.getAll(space.cuttlefish.domain.model.User,java.lang.String) at matching regular expression /movies. These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='[email protected]']
を爆破するジャージーの原因となります。
どうすればこの問題を解決できますか?
抽象クラスからすべての注釈を削除してから、各リソースの注釈を上書きして再追加する必要がありますか?それはちょうど乱雑になり、エラーになりやすい...ここにはもっと良い解決策があるはずですか?
私はただ見落としてしまった何かが目に見えて明白ですか?
いくつかのヘルプが大好きです。
あなたはすべてのサブクラスが短い署名でのgetAllメソッドを持ってしたくない場合は、それは抽象ベースクラスであってはなりません。継承されたメソッドは確かにここでトラブルを引き起こします。質問にJerseyタグまたはJAX-RSタグを追加することができます。 – JayK
タグチップありがとうございました。うーん、それは私が現時点で行ってきたことですが、1つのクラスだけが異なるものを扱うケースを解決するために、同じコードを20の異なるクラスにコピーしても、愚かなようです。 –
mixinメカニズムはいいと思います。非常に曖昧な答えは「継承を超える合成」ですが、今までJAX-RSを使ったことがないので、このマントラをここでうまく適用できるかどうかはわかりません。 – JayK