« 依存性:REST(3) | トップページ | infomodel,ejb,dto の引っ越し:REST(5) »

2015年2月22日 (日)

InitDatabase の実行まで:REST(4)

  • JsonConverter の作成
    Json encode/decode のためのクラス。ContextResolver を implement して作る。これを登録すると,このクラスの Jackson ObjectMapper が使用されるようになる。 Lazy fetch を追いかけないために Hibernate4Module を登録している。
     hbm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
     hbm.configure(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION, false);
     mapper.registerModule(hbm);
    
    これをサーバ側では web.xml に加える。
     <context-param>
         <param-name>resteasy.providers</param-name>
         <param-value>open.dolphin.JsonConverter</param-value>
     </context-param>
    
    クライアント側では ResteasyClient に登録する。
    ResteasyClient client = new ResteasyClientBuilder().build();
    client.register(new JsonConverter());
    
  • open.dolphin.infomodel に以下のファイルをコピー
    • InfoModel
    • IInfoModel
    • UserModel
    • UserLiteModel
    • LicenseModel
    • DepartmentModel
    • FacilityModel
    • RoleModel
    • RadiologyMethodValue
  • bi-directional reference の解消
    UserModel と RoleModel はお互いにお互いのフィールドを参照しているため,そのままだと json 化の時に無限ループに入ってしまって Stack Overflow となる。対策には色々あるようだが,一番簡単そうな @JsonIdentityInfo を使う方法を使った。
    @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class)
    public class UserModel extends InfoModel  {
      :
    
    @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class)
    public class RoleModel extends InfoModel  {
      :
    
    これで UserModel を json 化すると,以下のように UserModel の roles 内に出てくる UserModel が,親の UUID "f0c88e43-23bd-4aa4-8a71-e42ab6b2e257" への参照としてシリアライズされる。
    {
      "@id" : "f0c88e43-23bd-4aa4-8a71-e42ab6b2e257",
      "id" : 0,
      "roles" : [ {
        "@id" : "e0c1c1ce-06a1-45da-8795-afb59bb71ccf",
        "id" : 0,
        "user" : "f0c88e43-23bd-4aa4-8a71-e42ab6b2e257"
      } ]
    }
    
  • RemoteSystemService, RemoteSystemServiceImpl の改変
    RMI では @Remote を使っていたが,REST では @Path と @GET/@PUT/@POST/@DELETE を使う。また,json を使うために @Pruduces と @Consumes を付ける。これらを置き換えた SystemServiceSystemServiceImpl を作る。GET/PUT/POST の使い分けが難しいが,引数が1個の場合はとりあえず POST にしておけば,message body にパラメータを埋め込んでくれる。(引数が複数の場合は,@PathParam など,URL にパラメータを埋め込む必要がある)
  • クライアントからのアクセス方法
    以下のような手順で remote の Service クラスが取れる。ここらへんの手続きを DolphinClientContext というクラスにまとめた。
    // Resteasy
    ResteasyClient client = new ResteasyClientBuilder().connectionPoolSize(20).build();
    // register providers
    try {
        AuthorizationFilter authorizationFilter = new AuthorizationFilter(userId, hashPass);
        JsonConverter jsonConverter = new JsonConverter();
        client.register(authorizationFilter);
        client.register(jsonConverter);
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
    String restUrl = String.format(("http://%s/%s"), hostAddress, DOLPHIN_PATH);
    ResteasyWebTarget target = client.target(restUrl);
    SystemService service = target.proxy(SystemService.class);
    
    connectionPoolSize を設定しないと pool を使い果たした時点で以下のようなエラーとなる
    javax.ws.rs.ProcessingException: Unable to invoke request
    Caused by: java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
    Make sure to release the connection before allocating another one.
    
  • NetBeans でちょっと混乱したところ
    server を「ビルド」すると war と -classes jar ファイルができて client に反映される。しかし「ビルド」は deploy には影響しない。server を「実行」すると現在の class がデプロイされる。server のファイルを編集して保存するとすぐ deploy されるが,この時 -classes.jar ファイルはできていないので client はその編集を知らない。client に反映させるためには「ビルド」が必要になる。

« 依存性:REST(3) | トップページ | infomodel,ejb,dto の引っ越し:REST(5) »

OpenDolphin」カテゴリの記事