2016-09-02 6 views
8

APIプロジェクトのアーキテクチャに必要なオプションを見つけようとしています。JAX-RS API、ServiceLocator、リモートEJBを使ってプロジェクトを整理するオプション

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

これまでのところ、私はこれを行うことができ、動作します。しかし、私は解決策に満足していません。私のパッケージの処分を参照してください。 com.organization.api.v1.services.UserV1Service

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

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

} 

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

/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.services.UserService

public class UserV1Service extends UserService { 

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

} 

例:

public class UserService { 

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

} 
私の懸念は、コードの後に​​記述されています私のプロジェクトのの

いくつかの要件:UserServiceを使用してUserV1ServiceUserV2Service:同じバージョン管理サービスの異なるAPIのバージョンがコードを共有することができV1、V2など

    • APIはバージョンがあります。
    • 異なるバージョンのサービスの異なるAPIバージョンでは、UserV1ServiceOrderV2Serviceのコードを共有できます(AnotherServiceを使用)。
    • 各バージョンには独自のビューオブジェクト(UserV1VOで、UserVOではない)があります。

      1. このServiceLocatorクラスそれはない私のために良い方法:上記のコードについて教えてbotters何

    。このクラスは古いライブラリのレガシーコードを使用しています。このクラスの仕組みについて多くの質問があります。 ServiceLocatorを使用する方法は私にとっても非常に奇妙で、この戦略はnot good to mock the servicesfor my unit testsです。私は新しいServiceLocatorを作成したり、依存関係注入戦略(または別のより良いアプローチ)を使用したいと思います。

  • OrderServiceのような別の「外部」サービスでは、UserServiceクラスを使用することはできません。 UserVxServiceの場合のみです。しかし、将来的には、多分OrderServiceは、私は、私は自分のコードの中lookupsの多くを行う必要がありますServiceLocatorを使用して、最後の問題を無視した場合でもUserService ...
  • からいくつかのコードを使用したいと思います。サイクリック依存関係を作成する機会(serviceOne参照サービス2参照)が非常に高いです。
  • この方法では、バージョン管理サービス(com.organization.api.services)では、UserV1VOのようなVOを使用できますが、これは起こりません。良いアーキテクチャーは許可されていないものを許可しません。私はapi-servicesのような新しいプロジェクトを作成し、これを避けるためにそこにcom.organization.api.servicesを入れる考えがあります。これは良い解決策ですか?
  • だから...アイデア?

    答えて

    2

    私が見物事のカップル:

    • UserServiceは、理想的には、インタフェースをオフに基づいている必要があります。彼らは同様の契約を持っているようですが、唯一の違いはソース(RemoteEJB、LocalServiceLocator)です。これらはDTOを返すべきです

    • UserV1Service extends UserService should は継承を使用しませんが、代わりにの構成を推奨します。同じサービスのv2で何をする必要があるか考えてみましょう。あなたの例に基づいて、UserV2Service extends UserServiceが得られます。 1つのバージョンに固有の抽象メソッドで基底クラスが終了する場合、これは理想的ではありません。その後、突然のバージョン管理されたサービスのすべてがこれに対応する必要があります。 のServiceLocator

      • あなたはあなたのケースでは春またはおそらくCDIのような依存性注入フレームワークを使用した方がいいでしょうについては

      。プロジェクトが新規の場合は、これは自分のコードにのみ適用されます。

    • 単体テストが難しい場合は、RemoteEJB呼び出しを独自のインタフェースにラップして、簡単にモックアウトすることができます。 RemoteEJBのテストは、このプロジェクトの統合テストになります。

    UserServiceのクラスがOrderServiceのように、他の「外部」のサービスで使用されるものではありません。それはUserVxServiceのためだけです。しかし、おそらくOrderServiceはUserServiceのコードを使用したいかもしれません。

    お互いに話すために同じレイヤーのサービスに問題はありません。このアプローチでは

    、VOSが、UserV1VOのように、私の バージョン管理外のサービス(com.organization.api.services)で使用することができるが、これは が発生することはできません。良いアーキテクチャーは許可されていないものを許可しません。 私は、api-servicesのような新しいプロジェクトを作成し、これを避けるために com.organization.api.servicesを配置するという考えがあります。これは良い ソリューションですか?

    あなたが何かを "できた"という理由だけで、あなたがすべきことではありません。レイヤーを独自のプロジェクトに分けることは良い考えのように思えますが、実際には、開発者がそのプロジェクトで同じクラスを再作成したり、クラスパスにjarを含めたり、同じクラスを使用したりすることはありません。私はそれを分割することは間違っていると言っているのではなく、ちょうど「何のシナリオか」の代わりに分割する必要があるということです。

    +0

    こんにちは!答えをありがとう。悲しいことに、私のServiceLocatorは静的メソッドを呼び出します。私はこのメソッド(http://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface)のインターフェースを作成することはできません。 java 6. – Dherik

    +1

    @DherikあなたはおそらくJava 6に関する質問を編集したいと思っています... –

    +0

    完了!私はこの情報を含む私の質問を編集しました@ Shiraaz.M – Dherik

    0

    私は、このソリューション(Shiraaz.M @感謝)で終わる:

    • 私はすべてが私のサービスに延び削除し、に危険なのServiceLocatorクラスを削除します。このinheritances without a good purposeservice locatorはどちらも良い考えではありません。私はGuiceを使って自分のJax-rsバージョンのRESTリソースであるbut it's not so easy to do thatの依存関係を注入しようとしています。私の解決策は簡単だったので、しかし、私のサービスは、非常にシンプルで簡単に作成できます:

      @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については、チームと話し合い、組織の仕組みを説明しました。チームはこれをよく理解しており、誰もこのアーキテクチャを壊すことはありません。
    関連する問題