

（Windows、Java1.8.0）  
JAX-RS（Jersey）を使うAPIとして現在、下記のようなコードを書いています。

[code]

        @Path("API_01") // API呼出し時のURL
        
        @POST
        @Produces(MediaType.APPLICATION_JSON)
        public ResponseObj execute(RequestObj request) {
            
            ResponseObj reponse = new ResponseObj();
            reponse.status = "00";
            reponse.message = "";
            
            return reponse;
        }
    
[/code]

[code]

    ※POSTリクエストを送信すると上記のexecuteメソッドがJerseyから自動的に呼び出されます。
    ※JSON形式のリクエスト内容がJerseyによって RequestObj に変換されます。
    ※RequestObj、ResponseObjはスカラーのメンバ変数を持つ単純なVOです。
    
[/code]

上記について、以下のようにしたいと考えています。  
①API処理を記述するクラスの基底クラス作り、基底クラスのexecuteメソッド内で  
共通処理を記述したい  
（実際に作成するAPIは複数個あるので、それらの共通処理を基底クラスに記述したい）  
（共通処理の記述後に、executeSub(...) といった抽象メソッドを呼び出しておく  
形にする想定）  
  
②API処理を記述するクラスは上記のexecuteSub()をover rideし個別の処理はそちらに記述させたい  
  
③リクエストオブジェクト、レスポンスオブジェクトにはそれぞれ、複数のAPIに跨る共通の変数を持っているので、リクエストオブジェクトの基底クラス、レスポンスオブジェクトの基底クラスを持たせる形にしたい  
例 リクエストオブジェクトの基底クラス：RequestObjBase  
レスポンスオブジェクトの基底クラス：ResponseObjBase  
  
API1用 リクエストオブジェクト Request1 extends RequestObjBase  
レスポンスオブジェクト Response1 extends ResponseObjBase  
  
ここで、下記の記述方法が分かっていません。  
・基底クラスの executeメソッドの引数と戻り値の型をどのように記述すればよいか  
（今回実装するすべてのAPIのリクエスト、レスポンスの型を総称的に扱える記述にしたい）  
  
・リクエスト、レスポンスの型を総称的に扱えるメソッド定義となった時、それをOver ride  
した具象クラスのメソッド内で、どのように記述すれば Request1型のオブジェクトが受け取れるか  
  
上記の記述方法や、あるいは実装の構成案自体についてどうするべきかなど、ご教示頂けると大変助かります。

※試みに、基底クラスのメソッド引数と戻り値を、リクエスト・レスポンス用のオブジェクト基底クラスで指定してみましたがリクエストの内容のダウンキャストができず、また戻り値の型も不一致のコンパイルエラーとなるため断念しました。  
※クラス型を抽象的/相称的に扱うための Class<? extends
RequestObjBase>やジェネリクスを使えば実装できそうな気がして調べてみましたが知見が乏しく、今回の目的のためにどのように記述すべきか分かりませんでした。  
※メソッド引数と戻り値を Object
にし、強制的にHashMapにキャストすることはできましたが、記述が煩雑となるため、できれば実装は上述のRequest1、Response1などの型を使って記述したいと考えています。


CC BY-SA 4.0
2021-06-17T09:10:27.670
77627
2021-06-18T21:02:43.477
42710
question
java api ジェネリクス
APIのメソッドの引数、戻り値を抽象的に定義したい


`<RESP extends ResponseObjBase>`
のような[境界型パラメータ](https://docs.oracle.com/javase/tutorial/java/generics/bounded.html)で、利用できる型を制限できます。

基底クラス:

[code]

    public abstract class MyAbstractResource<RESP extends ResponseObjBase, REQ extends RequestObjBase> {
    
        @POST
        @Produces(MediaType.APPLICATION_JSON)
        public RESP execute(final REQ request) {
    
            // ...
            // 共通処理実行
    
            return executeSub(request);
        }
    
        protected abstract RESP executeSub(REQ request);
    
    }
    
[/code]

具象リソースクラス:

[code]

    @Path("/example1")
    public class MyConcreteResource extends MyAbstractResource<Response1, Request1> {
    
        @Override
        protected Response1 executeSub(final Request1 request) {
    
            final Response1 reponse = new Response1();
            reponse.status = "00";
            reponse.message = "";
    
            return reponse;
        }
    }
    
[/code]


CC BY-SA 4.0
2021-06-18T21:02:43.477
77647
2021-06-18T21:02:43.477
2808
77627
answer