Bonjour,
En gros j'ai une appli Web qui écoute le port COM1 quand je clique sur un bouton. Au clic sur le bouton j'appelle une action qui créé le thread. Dans le thread, je voudrais rediriger vers une autre action ou une autre page. Mais là je ne vois pas comment faire ? Auriez-vous une idée ?
Ce n'est pas au niveau du thread que vous devez faire la redirection/action mais au niveau de l'appelant . La thread que vous créez ne fait plus partie du processus courant à l'application web.
__________________________
La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : rien ne fonctionne et personne ne sait pourquoi...
L'appelant c'est ma classe action, le problème c'est que je crée le thread dans cette classe et que je suis obligé d'attendre que le thread se termine pour continuer et renvoyer l'ActionForward. Ce que je voudrais c'est que mon thread puisse créé une action et rediriger vers une autre page.
En effet je n'avais pas totalement cerné où se trouvait le problème.
Je vous conseillerai de regarder sur le web quelques exemples sur le multithreading en java afin de régler vos problèmes de synchronisation.
Sachez par contre que votre thread ne pourra tout de même pas créer une nouvelle action !
Ce que je vous conseille de faire est de créer un service en standalone que vous pourrez monitorer à partir d'une interface ( je ne parle pas d'interface graphique ). Pour cette interface vous implementez une classe qui va gérer une thread ainsi que les méthodes de votre interface.
Du coté de l'application web vous n'aurez qu'à simplement communiquez avec les méthodes de l'interface.
La raison à cette séparation du code est que d'après un vague souvenir , l'utilisation de Thread au sein d'une application Web pose des problèmes lorsque la Thread est utilisé au sein même du code Web ( dans les classes actions ). C'est à confirmer ou à corriger , je regarderai normalement ce soir pour vous faire une explication plus complète par rapport à cela.
Par contre pourriez-vous indiquer le bout de code appellant du Thread dans votre class Action ( Je pense que vous utilisez Struts 2 ).
__________________________
La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : rien ne fonctionne et personne ne sait pourquoi...
public ActionForward lectureCom() {
ActionForward action = null;
// Récuperation du port en argument
String port = "COM1";
// lancement de l'appli
EcouteurCom ecoutCom = new EcouteurCom(port);
ecoutCom.start();
while(ecoutCom.isAlive()){
if(ecoutCom.getAction() != null){
action = ecoutCom.getAction();
ecoutCom.stopThread();
return action;
}
}
// "interface utilisateur"
System.out.println("taper q pour quitter");
// construction flux lecture
BufferedReader clavier = new BufferedReader(new InputStreamReader(
System.in));
// lecture sur le flux entrée.
try {
String lu = clavier.readLine();
while (!lu.equals("q")) {
if(ecoutCom.getAction() != null){
action = ecoutCom.getAction();
return action;
}
}
} catch (IOException e) {
}
ecoutCom.stopThread();
return action;
}
La classe EcouteurCom hérite de la classe Thread, j'utilise Struts 1.3.8 et non Struts 2.
Voici la methode serialEvent qui se trouve dans la Classe EcouteurCom cette classe implémente l'interface SerialPortEventListener.
public void serialEvent(SerialPortEvent event) {
// gestion des événements sur le port :
// on ne fait rien sauf quand les données sont disponibles
switch (event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE:
String codeBarre = new String();
try {
// lecture du buffer et affichage
codeBarre = (String) fluxLecture.readLine();
System.out.println(codeBarre);
String[] tabCodes = codeBarre.split(";");
if(tabCodes.length >= 2){
String numProg = tabCodes[0];
String numSeq = tabCodes[1];
//TODO tester si le programme et la séquence existe
this.action = new ActionForward("/accueil.do");
this.action.setProperty("numProg", numProg);
this.action.setProperty("numSeq", numSeq);
}
} catch (IOException e) {
}
break;
}
}
Je vois que l'implémentation n'est pas trop mauvaise. Ce qui m'inquiète ce que je ne vois pas start(), stop() ou run() dans le cas où vous aurriez implementé runnable.
De plus dans le dernier morceau de code , j'aurais ajouter un while pour la lecture du code barre dans le cas elle ratterait.
__________________________
La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. Ici, nous avons réuni théorie et pratique : rien ne fonctionne et personne ne sait pourquoi...
Aucun problème start, sop et run sont implémenté dans la classe EcouteurCom je ne les ai pas mis pour ne pas surcharger mon Post de code mais la voici en entier :
/**
*
*/
package modele;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;
import org.apache.struts.action.ActionForward;
import com.sun.comm.Win32Driver;
/**
* @author sprodhomme
*
*/
public class EcouteurCom extends Thread implements SerialPortEventListener {
private CommPortIdentifier portId;
private SerialPort serialPort;
private BufferedReader fluxLecture;
private ActionForward action;
private boolean running;
/**
*
*/
public EcouteurCom() {
// TODO Auto-generated constructor stub
}
/**
* @param name
*/
public EcouteurCom(String port) {
// initialisation du driver
Win32Driver w32Driver = new Win32Driver();
w32Driver.initialize();
// récupération de l'identifiant du port
try {
portId = CommPortIdentifier.getPortIdentifier(port);
} catch (NoSuchPortException e) {
}
// ouverture du port
try {
serialPort = (SerialPort) portId.open("EcouteurCom", 2000);
} catch (PortInUseException e) {
}
// récupération du flux
try {
fluxLecture = new BufferedReader(new InputStreamReader(serialPort
.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
// ajout du listener
try {
serialPort.addEventListener(this);
} catch (TooManyListenersException e) {
}
// paramétrage du port
serialPort.notifyOnDataAvailable(true);
try {
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_7,
SerialPort.STOPBITS_1, SerialPort.PARITY_EVEN);
} catch (UnsupportedCommOperationException e) {
}
System.out.println("port ouvert, attente de lecture");
}
// Méthode appelé quand on fait thread.start
public void run() {
running = true;
while (running) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
// fermeture du flux et port
try {
fluxLecture.close();
} catch (IOException e) {
}
serialPort.close();
}
/*
* (non-Javadoc)
*
* @see javax.comm.SerialPortEventListener#serialEvent(javax.comm.SerialPortEvent)
*/
public void serialEvent(SerialPortEvent event) {
// gestion des événements sur le port :
// on ne fait rien sauf quand les données sont disponibles
switch (event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE:
String codeBarre = new String();
try {
// lecture du buffer et affichage
codeBarre = (String) fluxLecture.readLine();
System.out.println(codeBarre);
String[] tabCodes = codeBarre.split(";");
if(tabCodes.length >= 2){
String numProg = tabCodes[0];
String numSeq = tabCodes[1];
//TODO tester si le programme et la séquence existe
this.action = new ActionForward("/accueil.do");
this.action.setProperty("numProg", numProg);
this.action.setProperty("numSeq", numSeq);
}
} catch (IOException e) {
}
break;
}
}
/**
* Permet l'arrêt du thread
*/
public void stopThread() {
running = false;
}
/**
* @return the action
*/
public ActionForward getAction() {
return action;
}
/**
* @param action the action to set
*/
public void setAction(ActionForward action) {
this.action = action;
}
}
Je veux bien une piste par rapport à "un service en standalone" via une interface. Parce que plus je réfléchis plus je me rend compte que mon code c'est le chien qui se mort la queue, il faut donc que j'explore d'autres pistes.
Avez-vous des noms d'API ou autres qui pourrait faire ça ?