2017-07-14 4 views
0

Je veux que mon serveur udp s'exécute dans un thread déclencher un événement chaque fois qu'il reçoit un datagramme, en envoyant les données au format json.Comment déclencher un événement CDI à partir d'un thread s'exécutant sur le serveur?

public class UDPServer extends Thread { 

     private SocketUDPCommunication comm; 

     @Inject @Notify 
     private StatusChangeHandler sch; 

     public UDPServer() { 
      comm = new SocketUDPCommunication(); 
     } 


     @Override 
     public void run() { 

      DatagramPacket response; 

      comm.setPort(Utils.UDP_SERVER_PORT); 
      comm.createSocket(); 

      while (!Thread.currentThread().isInterrupted()) { 
       System.out.println("Waiting for clients to connect on port:" + comm.getSocket().getLocalPort()); 
       try { 
        response = comm.receiveResponse(); 
       } catch (SocketTimeoutException e) { 
        continue; 
       }       

       byte[] byteSend = comm.discardOffset(response); 

       Status status = frameToJson(byteSend); 

       Genson genson = new Genson(); 
       String json = genson.serialize(status); 

       sch.sendChangedStatus(json); //Raise the cdi event, sch not initialized!! 
      } 

     } 

     @Override 
     public void interrupt() { 
      super.interrupt(); 
      comm.closeConnection(); 
     } 
    } 

Il y a défini un écouteur pour cet événement qui fera appel à une méthode de point final de websocket pour diffuser ce message à tous les clients connectés:

public class StatusChangeObserver { 

     public void statusChanged(@Observes StatusChange sce) { 
      WebsocketEndPoint.sendAll(sce.getJson()); 
     } 
    } 

    @ServerEndpoint(value="/websocket") 
    public class WebsocketEndPoint { 
     private static Set<Session> userSessions = Collections.synchronizedSet(new HashSet<Session>()); 

     @OnOpen 
     public void onOpen(Session userSession) { 
      System.out.println("Opening new connection"); 
      userSessions.add(userSession); 
     } 

     @OnClose 
     public void onClose(Session userSession) { 
      System.out.println("Connection closed. Id: " + userSession.getId()); 
      userSessions.remove(userSession); 
     } 


     public static void sendAll(String message) { 
      for (Session session : userSessions) { 
       if (session.isOpen()) { 
        session.getAsyncRemote().sendText(message); 
       } 
      }  
     } 
    } 

Et le gestionnaire qui fait déclencher l'événement:

@Notify 
    public class StatusChangeHandler { 

     @Inject 
     private Event<StatusChange> statusChangedEvent; 

     public void sendChangedStatus(String json) { 
      StatusChange sce = new StatusChange(json); 
      statusChangedEvent.fire(sce); 
     } 
    } 

StatusChange est un simple POJO qui contiendra le message à diffuser. Le qualificatif @Notify:

@Qualifier 
    @Retention(RUNTIME) 
    @Target({METHOD, FIELD, PARAMETER, TYPE}) 
    public @interface Notify { 
    } 

Ce sont mes premiers pas avec l'injection de dépendance, donc je ne suis pas sûr de savoir comment je déclenche l'événement à l'intérieur du fil, et comment initialiser l'objet sch. J'ai trouvé this page qui suggère d'utiliser Weld et WeldContainer classes pour initialiser CDI, mais je ne suis pas en mesure de trouver ces classes avec maven. Est-ce la bonne approche pour le faire? Dans ce cas, quelqu'un sait comment inclure ces classes à mon projet?

+1

Si vous déployez sur Tomcat, vous devez utiliser Weld Servlet https://docs.jboss.org/weld/reference/latest/en-US/html/environments.html#weld-servlet au lieu de Soudure SE. –

Répondre

0

Ici vous avez un référentiel public avec des bibliothèques de soudure.

https://mvnrepository.com/artifact/org.jboss.weld

Mais, qu'est-ce que vous avez besoin? Dans quel environnement l'utiliserez-vous? Par exemple, dans wildfly, cdi 1.1 ou cdi 1.2 est intégré, et vous n'avez pas besoin d'ajouter ces bibliothèques.

Pour plus d'informations, utilisez http://weld.cdi-spec.org/

+0

J'utilise Tomcat8, et la dépendance de maven indiquée dans la documentation de Weld est incluse dans "pom.xml". Vide "beans.xml" est dans WEB-INF, et "context.xml" dans META-INF. Cependant, je ne peux pas importer "org.jboss.weld.environment.se.Weld" – Juan

0

Puisque vous êtes sur Tomcat, nous parlons servlet environnement. Pour cela, Weld fournit un JAR de servlet qui va automatiquement démarrer le CDI pour vous. Pas besoin de gérer Weld/WeldContainer manuellement.

Voici un link to Weld documentation qui explique l'artefact/dépendance dont vous avez besoin et comment l'utiliser. Après avoir ajouté cela, CDI devrait simplement amorcer pour vous lorsque vous déployez votre application sur Tomcat.