8

API プロジェクトのアーキテクチャに使用できるオプションを見つけようとしています。

JAX-RS バージョン 1.0 を使用して API を作成したいと考えています。この API は、大きくて古い複雑なアプリケーションからリモート EJB (EJB 3.0) を使用します。私はJava 6を使用しています。

これまでのところ、私はこれを行うことができ、動作します。しかし、私は解決策に満足していません。私のパッケージの処分を参照してください。私の懸念は、コードの後に​​説明されています。

/api/
    /com.organization.api.v1.rs -> Rest Services with the JAX-RS annotations
    /com.organization.api.v1.services -> Service classes used by Rest Services. Basically, they only have the logic to transform the DTOs objects from Remote EJBs in JSON. This is separated by API version, because the JSON can be different in each version.
    /com.organization.api.v1.vo -> View Objects returned by the Rest Services. They will be transformed in JSON using Gson.
    /com.organization.api.services -> Service classes used by versioned Services. 
        Here we have the lookup for Remote EJBs and some API logic, like validations. This services can be used by any versioned of each Service.

の例com.organization.api.v1.rs.UserV1RS:

@Path("/v1/user/")
public class UserV1RS {

  @GET
  public UserV1VO getUsername() {
     UserV1VO userVO = ServiceLocator.get(UserV1Service.class).getUsername();
     return userVO;
  }

}

の例com.organization.api.v1.services.UserV1Service:

public class UserV1Service extends UserService {

  public UserV1VO getUsername() {
    UserDTO userDTO = getUserName(); // method from UserService
    return new UserV1VO(userDTO.getName);
  }

}

の例com.organization.api.services.UserService:

public class UserService {

  public UserDTO getUsername() {
    UserDTO userDTO = RemoteEJBLocator.lookup(UserRemote.JNDI_REMOTE_NAME).getUser();
    return userDTO;
  }

}

私のプロジェクトのいくつかの要件:

  • API には、v1、v2 などのバージョンがあります。
  • バージョン管理された同じ Service の異なる API バージョンは、コードを共有できます:UserV1ServiceおよびUserV2Serviceを使用しUserServiceます。
  • 異なるバージョンのサービスの異なる API バージョンは、コードを共有できます:UserV1ServiceおよびOrderV2Serviceを使用しAnotherServiceます。
  • 各バージョンには独自のビュー オブジェクトがあります (UserV1VOではありませんUserVO)。

上記のコードについて私を悩ませているのは:

  1. このServiceLocatorクラスは私にとって良いアプローチではありません。このクラスは古いライブラリのレガシー コードを使用しており、このクラスがどのように機能するかについて多くの質問があります。の使用方法ServiceLocatorは私にとっても非常に奇妙であり、この戦略は単体テスト用のサービスをモックするのには適していません 。新しい ServiceLocator を作成するか、依存性注入戦略 (または別のより良いアプローチ) を使用したいと考えています。
  2. このUserServiceクラスは、 などの別の「外部」サービスによって使用されることを意図していませんOrderService。のみですUserVxService。しかし、将来的には、OrderServiceいくつかのコードを使用したいと思うかもしれませんUserService...
  3. 最後の問題を無視したとしても、 を使用すると、コード内でServiceLocator多くのことを行う必要があります。lookups循環的な依存関係 (serviceOne をルックアップする serviceTwo が serviceThree をルックアップする serviceOne をルックアップする) が作成される可能性は非常に高くなります。
  4. このアプローチでは、 のような VO をUserV1VOバージョン管理されていないサービス ( com.organization.api.services) で使用できますが、これは実現できません。優れたアーキテクチャは、許可されていないものを許可しません。これを避けるために、新しいプロジェクトを作成してそこにapi-services置くという考えがあります。com.organization.api.servicesこれは良い解決策ですか?

それで... アイデア?

4

2 に答える 2

0

私はこの解決策で終わります(@ Shiraaz.Mに感謝します):

  • Services のすべての extends を削除し、危険な ServiceLocator クラスを削除します。適切な目的とサービス ロケーターのないこの継承は、どちらも悪い考えです。Guice を使用して REST リソースに依存関係を挿入しようとしていますが、Jax-rs バージョンでそれを行うのはそれほど簡単ではありません。しかし、私のサービスは非常にシンプルで簡単に作成できるので、私のソリューションは単純です。

    @Path("/v1/user/")
    public class UserV1RS {
    
      private UserV1Service userV1Service;
    
      public UserV1RS() {
         this.userV1Service = new UserV1Service();
      }
    
      // only for tests!
      public UserV1RS(UserV1Service userV1Service) {
        this.userV1Service = userV1Service;
      }
    
      @GET
      public UserV1VO getUsername() {
        UserV1VO userVO = this.userV1Service.getUsername();
        return userVO;
      }
    
    }
    

そして私のUserV1Service:

    public class UserV1Service {

      private UserService userService;

      public UserV1Service() {
        this.userService = new UserService();
      }

      // for tests
      public UserV1Service(UserService userService) {
        this.userService = new UserService();
      }

      public UserV1VO getUsername() {
        UserDTO userDTO = userService.getUserName();
        return new UserV1VO(userDTO.getName);
      }

    }

この戦略により、構成された他のサービスを利用しやすくなります。

  • 必要に応じて、将来、Guice を導入して、残りのリソースとサービス (少なくともサービス) に依存関係を注入し、依存関係のあるサービスから既定のコンストラクターを削除し、テストと運用で同じコンストラクターを使用します。 .
  • 項目 4 については、チームと話し、組織がどのようになっているのかを説明しました。チームはこれをよく理解しており、誰もこのアーキテクチャを壊していません。
于 2016-10-18T12:15:25.233 に答える