2017-02-27 6 views
0

J'essaie de trouver CDI et la meilleure méthode qui convient à mes besoins. J'ai un service (TcpServiceImpl) qui interagit avec la communication tcp simple. Maintenant, ce service a quelques points où il doit informer quelqu'un que quelque chose est arrivé. Pour ces informations, j'ai l'interface TcpConnection qui doit être injectée CDI à l'implémentation correcte. Un autre problème est que le service TcpServiceImpl lui-même est injecté dans un travail (TcpConnectionJob) qui s'exécute périodiquement et appelle le service pour faire des choses. Cela signifie que le service TcpServiceImpl va exister plusieurs fois. Chacun ayant une autre connexion tcp qu'il gère et ayant un autre périphérique qui a besoin d'un autre pilote/protocole à injecter dans l'interface TcpConnection.Injectind Implémentation automatique à l'exécution sur CDI

Permettez-moi de montrer les trois éléments qui participent à ce scénario:

Voici l'interface qui obtenir plusieurs implémentations:

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; 
} 

Aussi voici un exemple extrait de quand cela sera appelé mon service existant:

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(); 
} 
} 

Voici la classe qui appelle le service, qui doit ensuite injecter dynamiquement la mise en œuvre correcte L'interface.

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

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

L'injection de service callback doit être liée à la mise en œuvre du bon « protocole » ou « pilote » qui se traduira par les données ou gérer la logique de l'appareil. Il y aura plusieurs implémentations de pilote de l'interface agissant différemment et j'ai besoin d'injecter le bon. Un qualificateur pour cette décision pourrait être le nom de l'appareil. Maintenant, je regardais les liens suivants:

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?

Question:

Mais je suis encore pas sûr de quelle manière/méthode à utiliser et quelle est la manière correcte. Toute aide serait appréciée. J'ai d'abord pensé à copier mon interface sur une interface de qualificatif et à ajouter celle-ci avec la possibilité d'entrer le qualificatif. est-ce une bonne idée?

Répondre

0

Voici donc ma solution que je suis venu avec. Le seul problème est maintenant de faire fonctionner un callback, mais c'est quelque chose de différent.Heres la solution qui a fonctionné pour moi:

/** 
* 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(); 
} 

La valeur par défaut mise en œuvre juste pour l'interface Qualifier:

/** 
* 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; 
    } 

} 

maintenant une implémentation de test pour tester:

@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"); 
    } 

}

Last but not least, la façon dont j'ai injecté tout cela dans mon service:J'espère que cela aidera quelqu'un ayant les mêmes exigences que j'ai eues.

PS: Un petit journal pour montrer cela fonctionne si vous vérifiez les sorties de journaux dans la mise en œuvre de test, puis regardez le journal :)

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

Malheureusement je ne peux pas utiliser des événements CDI. Au départ, je voulais le faire de cette façon, mais comme on s'attend à ce qu'il y ait énormément de trafic et de données dans l'application, ma recommandation a été refusée. Autant que je sache, les événements sont synchrones, aussi le déclenchement d'un événement obligera le programme à attendre que tous les observateurs soient terminés jusqu'à ce que le code soit exécuté. Mais que se passe-t-il si je dois surveiller davantage de données entrantes lors de la notification aux autres que les données sont entrées? – Nico

+0

@Nico: jetez un oeil à cet article intéressant qui explique comment vous pouvez rendre CDI Event asynchrone. Cela peut être une solution pour vous: http://piotrnowicki.com/2013/05/asynchronous-cdi-events/ – Rouliboy

+0

Merci pour votre article. Vraiment bon à savoir et je vais l'enregistrer, mais je voudrais penser à une solution sans utiliser les événements CDI. Disons que ce n'est pas possible à cause du rejet de quelqu'un. Mes pensées étaient de créer un producteur en combinaison avec un qualificatif en quelque sorte. Est-ce une stratégie valable? – Nico