2017-02-27 12 views
0

私はCDIと私のニーズに合った最適な方法を見つけようとしています。 私は単純なtcp通信とやりとりするサービス(TcpServiceImpl)を持っています。今、このサービスは何かが起こったことを誰かに知らせる必要があるいくつかのポイントを持っています。この情報については、正しい実装にCDIを注入する必要があるInterface TcpConnectionがあります。別の問題は、サービスTcpServiceImpl自体が定期的に実行されるジョブ(TcpConnectionJob)に注入され、サービスを呼び出して処理を行うことです。 これは、サービスTcpServiceImplが複数回存在することを意味します。それぞれ別のtcp接続を持ち、別のドライバ/プロトコルをインターフェイスTcpConnectionに注入する必要がある別のデバイスを処理しています。CDIで実行時に自動的にInjectindの実装

私は、このシナリオに参加して三つの要素を表示してみましょう。ここでは

は、複数の実装を取得するインタフェースである。また、ここで

public interface TcpConnection 
{ 

    /** 
    * Connected. 
    * 
    * @throws NGException the NG exception 
    */ 
    public void connected() throws NGException; 

    /** 
    * This method will send the received data from the InputStream of the connection. 
    * 
    * @param data the received data 
    * @throws NGException the NG exception 
    */ 
    public void received(byte[] data) throws NGException; 

    /** 
    * Usable for the protocol to send data to the device. 
    * 
    * @param data the data to send to the device (Will be converted to byte[] with getBytes()) 
    * @throws NGException the NG exception 
    */ 
    public void send(String data) throws NGException; 

    /** 
    * Usable for the protocol to send data to the device. 
    * 
    * @param data the data to send to the device (Will be send as is) 
    * @throws NGException the NG exception 
    */ 
    public void send(byte[] data) throws NGException; 

    /** 
    * This method will inform the protocol that the connection got closed. 
    * 
    * @throws NGException the NG exception 
    */ 
    public void closed() throws NGException; 
} 

がこの中に呼び出されるときの例スニペットです私の既存のサービス:

public class TCPServiceImpl implements TCPService, Runnable 
{ 
/** The callback. */ 
private TcpConnection callback; 
private void disconnect() 
{ 
    connection.disconnect(); 
    if (!getStatus(jndiName).equals(ConnectionStatus.FAILURE)) 
    { 
    setStatus(ConnectionStatus.CLOSED); 
    } 
    /* TODO: Tell driver connection is closed! */ 
    callback.closed(); 
} 
} 

以下は、サービスを呼び出すクラスです。サービスを呼び出すクラスは、インタフェース。

public class TcpConnectionJob implements JobRunnable 
{ 
    /** The service. */ 
    private TCPService service; 

    public void execute() 
    { 
    service.checkConnection(connection); 
    } 
} 

サービス注入callbackは、データを変換またはデバイスのロジックを処理する正しい「プロトコル」または「ドライバ」の実装にリンクされなければなりません。インターフェースの複数のドライバー実装が異なって動作し、正しいものを注入する必要があります。この決定のための修飾子は、デバイスの名前である可能性があります。今、私は、次のリンクを見て:

Understanding the necessity of type Safety in CDI

How to programmatically lookup and inject a CDI managed bean where the qualifier contains the name of a class

How to use CDI qualifiers with multiple class implementations?

質問:

しかし、私はまだ使用する方法/方法と何が約わかりませんよ正しい方法。どんな助けもありがとう。

私の最初の考えは、私のインタフェースを修飾子インタフェースにコピーし、このインタフェースに修飾子を入力する可能性を付加することでした。それは良いアイデアですか?

答えて

0

だから、これは私が思い付いた私の解決策です。唯一の問題は、コールバックを取得することですが、それは異なるものです。私のために働いたソリューション相続人:

/** 
* The Qualifier interface TcpDriver. The value of this annotation is the name the implementation 
* is found under. Please only enter values that are configured in the wildfly config as the name of 
* the device. 
*/ 
@Documented 
@Qualifier 
@Retention(RUNTIME) 
@Target({ TYPE, FIELD, METHOD, PARAMETER }) 
public @interface TcpDriver 
{ 

    /** 
    * Value. 
    * 
    * @return the string 
    */ 
    String value(); 
} 

だけ修飾子インタフェースのデフォルトの実装:今すぐ

/** 
* The Class TcpDriverImpl. 
*/ 
public class TcpDriverImpl extends AnnotationLiteral<TcpDriver> implements TcpDriver 
{ 

    /** The Constant serialVersionUID. */ 
    private static final long serialVersionUID = 1L; 

    /** The name. */ 
    private final String name; 

    /** 
    * Instantiates a new tcp driver impl. 
    * 
    * @param name the name 
    */ 
    public TcpDriverImpl(final String name) 
    { 
    this.name = name; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public String value() 
    { 
    return name; 
    } 

} 

それをテストするためのテスト実装:

@TcpDriver("terminal1") 
@Dependent 
public class TestDriverImpl implements TcpConnection 
{ 

    /** The log. */ 
    private Log log; 

    @Inject 
    public void init(Log log) 
    { 
    this.log = log; 
    } 

    @Override 
    public void connected() throws NGException 
    { 
    // TODO Auto-generated method stub 
    log.info("IT WORKS!!"); 
    } 

    @Override 
    public void received(byte[] data) throws NGException 
    { 
    // TODO Auto-generated method stub 

    } 

    @Override 
    public void send(String data) throws NGException 
    { 
    // TODO Auto-generated method stub 

    } 

    @Override 
    public void send(byte[] data) throws NGException 
    { 
    // TODO Auto-generated method stub 

    } 

    @Override 
    public void closed() throws NGException 
    { 
    // TODO Auto-generated method stub 
    log.info("BYE BYE"); 
    } 

}

最後に、これを私のサービスですべて注射した方法:

/** The callback Instance for the driver to find. */ 
    @Inject 
    @Any 
    private Instance<TcpConnection> callback; 

    private TcpConnection driver; 
    /** 
    * Inject driver. 
    */ 
    private void injectDriver() 
    { 
    final TcpDriver driver = new TcpDriverImpl(name); 
    this.driver = callback.select(driver).get(); 
    } 

私は、これが私と同じ要件を持つ誰かに役立つことを願っています。

PS:あなたはテスト実装にログ出力をチェックして、ログを見れば、それは働く表示する小さなログ:)

2017-02-28 08:37:00,011 INFO starting TCPConnection: TcpDevice1 with status: NOT_CONNECTED 
2017-02-28 08:37:00,018 INFO initializing terminal1 
2017-02-28 08:37:00,019 INFO Creating socket for: terminal1 with port: XXXXX 
2017-02-28 08:37:00,023 INFO Updated Status to CONNECTED for connection TcpDevice1 
2017-02-28 08:37:00,024 INFO opened connection to terminal1 
2017-02-28 08:37:00,026 INFO (terminal1) IT WORKS!! 
2017-02-28 08:37:00,038 INFO (terminal1) terminal1: In threaded method run 
2017-02-28 08:37:00,039 INFO (terminal1) waiting for data... 
2017-02-28 08:39:00,045 INFO (terminal1) Socket closed! 
2017-02-28 08:39:00,045 INFO (terminal1) BYE BYE 
1
+0

悲しいことに、私はCDIイベントを使用することはできません。私はもともとそうしたいと思っていましたが、トラフィックとデータがアプリケーションを通過することが予想されるため、私の推奨は拒否されました。 私が知る限り、イベントは同期しているので、イベントを発生させると、プログラマは、さらなるコードが実行されるまで、すべてのオブザーバが終了するまで待機します。しかし、データが入ったことを他人に知らせる際に、より多くの着信データを監視する必要がある場合はどうすればよいでしょうか? – Nico

+0

@Nico:CDIイベントを非同期にする方法を説明するこの興味深い記事を見てください。それはあなたのための解決策になります:http://piotrnowicki.com/2013/05/asynchronous-cdi-events/ – Rouliboy

+0

あなたの記事をありがとう。本当に知って良いと私はそれを保存しますが、私はCDIイベントを使用しないで解決策について考えてみたいと思います。誰かからの拒否のために不可能であるとしましょう。私の考えは、何らかの形で修飾子と組み合わせてプロデューサーをつくることでした。それは有効な戦略ですか? – Nico

関連する問題