通过CDI

时间:2017-02-27 11:10:34

标签: java ejb javabeans cdi

我想弄清楚CDI和最适合我需要的方法。 我有一个与普通tcp通信交互的服务(TcpServiceImpl)。现在这个服务有一些点需要通知某人发生了什么事。对于这个信息,我有接口TcpConnection,需要将CDI注入到正确的实现中。另一个问题是服务TcpServiceImpl本身被注入到定期执行的作业(TcpConnectionJob)中并调用服务来执行操作。 这意味着服务TcpServiceImpl将多次存在。每个都有另一个tcp连接,它处理并有另一个设备,需要在接口TcpConnection中注入另一个驱动程序/协议。

让我展示参与这个场景的三个元素:

这是将获得多个实现的接口:

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?

问题:

但我仍然不确定使用哪种方式/方法以及正确的方法。任何帮助将不胜感激。

我的第一个想法是将我的界面复制到限定符界面并附加这个可以输入限定符的界面。这是个好主意吗?

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分: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