IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

[Thread] Lancer la couche métier dans un thread dédié


Sujet :

Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 103
    Points : 60
    Points
    60
    Par défaut [Thread] Lancer la couche métier dans un thread dédié
    Bonjour à tous,

    Je développe une application dont la partie présentation est assurée par Swing. La couché métier est accessible via un Singleton appelé Middleware. Ce singleton possède des méthodes du type newProject, recordProject, simulate, etc... appelées par la couche Swing (par exemple en faisant Middleware.getInstance().newProject()).

    J'ai bien compris les problématiques d'exécution dans les threads qui vont bien (thread EDT pour les "actions" graphiques et thread dédié pour les "actions" métier en tache de fond). Je me suis également penché du coté de SwingWorker dispo depuis java 6. Je trouve tous cela élégant dans le cadre de simples petits exemples.

    Pour une application de taille supérieur, (à moins que je sois passé à coté d'un truc énorme) je trouve ces mécanismes assez lourd à gérer notamment par le fait de devoir créer des threads ou d'implémenter des SwingWorkers de manière systèmatique. Je me vois par exemple mal implémenté un SwingWorker par tâche de fond que j'ai à effectuer... surtout qu'ils doivent embarquer du code métier si je veux par exemple gérer des Progress Bar.

    Je me posais donc la question de savoir s'il existait un moyen de faire exécuter automatiquement toutes les méthodes du Singleton Middleware dans un thread dédié (par exemple en le lanceant d'une manière spécifique) ?

    Merci d'avance pour votre aide

  2. #2
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Je pense que tu peux y arriver par le biais des aspects avec spring, par exemple. Mais il faut springuifier ton appli, ce n'est pas forcément un mal. (mais vérifie que j'ai pas dit de bêtises avant).

    Sinon, coté swing, tu as la notion d'Action, censée factoriser les... actions ; l'intention est bonne, mais je trouve pas toujours pratique la mise en oeuvre.

    Perso je lance un thread ou un SwingWorker par tâche de fond à lancer ; vu les problèmes de synchro que ça pose, je ne suis même pas sûr que ce soit gérable de façon générique ?...
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 103
    Points : 60
    Points
    60
    Par défaut
    Bonjour,

    Merci pour ces quelques pistes. En ayant creuser pas mal aujourd'hui je me rend compte que faire quelques choses de générique n'est pas forcément gagner et dans tous les cas, je serais obligé dans le code métier de faire remonter l'information sur l'état d'avancement de la tache.

    En ce qui concerne Spring, je comptais pas vraiment l'utiliser pour le moment... je sais que je devrais me pencher dessus un jour ou l'autre mais difficile de tout faire en même temps.

    En fait j'utilise le "Swing Application Framework" défini dans la JSR 296 et qui je trouve simplifie pas mal la vie même s'il pourrait être amélioré (Je crois que son intégration est prévu dans Java 7).

    J'ai donc pensé à me concocté un mini-framework pour faire ce dont j'ai besoin.

    Le framework se compose des classes suivantes :

    Une interface que doivent implémenter les composants graphiques permettant de montrer l'état d'avancement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface ProgressListener {
    	public void setProgress(Integer value);
    }
    Une interface que doit implémenter la classe que va appeler le métier pour informer de sa progression
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface WorkerInterface {
    	public void setWorkProgress(Integer value);
    }
    Une classe abstraite AbstractSwingWorker que vont étendre mes SwingWorker:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    public abstract class AbstractSwingWorker extends SwingWorker<Integer, String> {
     
    	protected List<ProgressListener> listProgressListener;
     
    	public AbstractSwingWorker() {
     
    		super();
    		listProgressListener = new ArrayList<ProgressListener>();
     
    		/* On ajoute le listener sur la proprieté "progress" */
    		addPropertyChangeListener(new PropertyChangeListener() {
    			public void propertyChange(PropertyChangeEvent evt) {
    				if ("progress".equals(evt.getPropertyName())) {
    					for (Iterator<ProgressListener> iterator = listProgressListener.iterator(); iterator.hasNext();) {
    						ProgressListener progressListener = iterator.next();
    						progressListener.setProgress((Integer) evt.getNewValue());
    					}
    				}
    			}
    		});
     
    	}
     
    	/**
             * 
             * @param progressListener
             */
    	public void addProgressListener(ProgressListener progressListener) {
    		listProgressListener.add(progressListener);
    	}
     
    	/**
             * 
             * @param progressListener
             */
    	public void removeProgressListener(ProgressListener progressListener) {
    		listProgressListener.remove(progressListener);
    	}
     
    }
    Un exemple d'extension :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public class SwingWorkerOpenProject extends AbstractSwingWorker implements WorkerInterface {
     
        /**
         * 
         */
        private File file;
     
        /**
         * 
         */
        private MyFrame myFrame;
     
    	/**
             * @param myFrame 
             * @param file 
             * 
             */
    	public SwingWorkerOpenProject(MyFrame myFrame, File file) {
    		super();
    		this.myFrame = myFrame;
    		this.file = file;
    	}
     
    	@Override
    	protected Integer doInBackground() throws Exception {
    		Middleware.getInstance().openProject(file, this);
    		return 0;
    	}
     
    	@Override
    	protected void process(List<String> strings) {
    		// A implementer
    	}
     
    	@Override
    	protected void done() {
    		try {
    			/* Le traitement est terminé. */
    			setProgress(100);
    			/*
    			 * À la fin du traitement, affichage dans myFrame de l'interface
    			 */
    			this.myFrame.finishOpenProject();
     
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
     
    	@Override
    	public void setWorkProgress(Integer value) {
    		this.setProgress(value);
    	}
     
    }
    Dans le code de appelant (la classe MyFrame), j'ai donc défini 2 méthodes : une méthode exécuté lors du clique par exemple sur un bouton et une autre une fois que le métier c'est exécuté :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Action public void openProject() {
     
    		JFileChooser jfc = new JFileChooser();
    		jfc.setCurrentDirectory(new File("." + File.separator + "project"));
     
    		int resultat = jfc.showOpenDialog(this.getMainFrame());
    		if (resultat == JFileChooser.APPROVE_OPTION) {
     
    			File file = jfc.getSelectedFile();
     
    			JDialogProgress jDialogProgress = new JDialogProgress();
     
    			SwingWorkerOpenProject swingWorkerOpenProject = new SwingWorkerOpenProject(this, file);
    			swingWorkerOpenProject.addProgressListener(jDialogProgress);
    			swingWorkerOpenProject.execute();
                }
    }
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void finishOpenProject() {	
    	// Action d'affichage	
    }
    La classe JDialogProgress qui implémente l'interface ProgressListener :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class JDialogProgress extends JDialog implements ProgressListener {
     
    	/**
             * 
             */
    	private static final long serialVersionUID = 4960191407679629756L;
     
    	/**
             * 
             */
    	JProgressBar jProgressBar = new JProgressBar();
     
    	/**
             * 
             */
    	public JDialogProgress() {
     
    		Container container = this.getContentPane();
    		container.add(jProgressBar);
     
    		container.validate();
    		container.repaint();
     
    		this.setSize(300, 50);
    		this.setVisible(true);
     
    	}
     
    	public void setProgress(Integer value) {
     
    		jProgressBar.setValue(value);
     
    	}
     
    }
    Et pour terminer la méthode openProject de la classe Middleware :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    /**
    * Open the project from a file
    * @param file 
    * @param workerInterface
    */
    public void openProject(File file, WorkerInterface workerInterface) {
     
    	//---
    	workerInterface.setWorkProgress(10);
    	try {
                    Thread.sleep(1000);
            } catch(InterruptedException e) {
                    e.printStackTrace();
            }
     
    	File fileBin = new File(file.getParent()+File.separator+"bin");
    	ClassLoader classLoader = this.loadClasses(fileBin);
     
    	//---
    	workerInterface.setWorkProgress(20);
    	try {
                    Thread.sleep(1000);
            } catch(InterruptedException e) {
                    e.printStackTrace();
             }
     
    	//etc...
     
    }
    Avis et commentaire bienvenus

    On verra demain pour le paufinage...

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    pour spring et les aspect. C'est sur que c'est puissant (possibilité de rajouter dynamiquement des surcouche de code sur des appel de méthode (comme par exemple lancer un thread :p)) mais j'éviterais de jouer avec ca sans avoir au préalable une connaissance approfondie du java. Par ce que, avec la programmation aspect, le programme peut se retrouver a faire totalement autre chose que ce que dit le code, et c'est pas facile à digérer pour le programmeur

  5. #5
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Pour ProgressListener, attention que un listener est censé étendre l'interface EventListener ; ok, ça ne sert absolument à rien, ni de près ni de loin, ok avec un nom pareil on ne sait pas si c'est un event ou si c'est un listener, mais c'est quelque part dans la spec des javabeans, comprenne qui pourra.

    Mais en fait je ne suis pas sûr à te lire que ton ProgressListener soit un listener au sens java bean ?

    Méfie toi qu'utiliser sleep pour pauser un thread c'est courir au devant des ennuis si c'est dans l'edt.

    Pour ce qui concerne le Swing Application Framework, j'avais regardé au début, et cela m'avait paru... complètement nul. Spring propose une bien meilleure, bien que différente, approche pour la notion d'application, me semble-t-il et sous toute réserve bien sûr et avec tout le respect que je dois à tous.

    Et merci à tchize_ pour ses précisions : j'avais parlé sans vraiment connaître, et c'est toujours un plaisir d'avoir raison sur les choses qu'on connait pas.
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 103
    Points : 60
    Points
    60
    Par défaut
    Merci pour ces quelques précisions.

    @tchize_ : Je ne connaissais absolument pas ces aspects là de Spring. Il faudra que je m'y penche car cela à l'air d'être intéressant. J'avais juste utilisé l'outil pour codé un pattern MVC au niveau application mais finalement j'avais abandonnée l'idée car j'avais du mal à créer une application flexible.

    @gifffftane : Pour le ProgressListener, le nom doit être mal choisi c'est juste un composant graphique qui doit être capable d'afficher l'état de la progression. Rien à voir donc avec un EventListener ou autre chose mais il faudrait que je regarde la spec java bean pour voir ce qu'il y a d'écrit dedans à ce sujet.

    Pour les sleeps, justement ils ne sont pas dans l'edt mais dans un autre thread créer automatiquement lors de l'appel à la méthode doInBackground du SwingWorker.

    Et pour le Swing Application Framework, en effet, il n'y a pas grand chose dedans (à moins que je sois passé à coté de grosses choses) mais ça facilite un peu certaines opérations redondantes. Heu... d'ailleurs en ressortant ce lien, je viens de voir qu'il y avait quelque chose pour la gestion des taches longues... je verrais tous ça demain...

    Encore merci

Discussions similaires

  1. Comment lancer Word dans un thread séparé
    Par Tony49 dans le forum C++Builder
    Réponses: 3
    Dernier message: 22/03/2009, 12h43
  2. Intégration des couches métiers dans Rails
    Par MeMyself&I dans le forum Ruby on Rails
    Réponses: 2
    Dernier message: 19/03/2008, 12h00
  3. Réponses: 3
    Dernier message: 19/03/2008, 09h38
  4. lancer un thread dans un thread
    Par andromeda dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 27/07/2007, 23h29
  5. [threading][logging] erreur de loggage dans un thread
    Par Guigui_ dans le forum Général Python
    Réponses: 5
    Dernier message: 12/10/2005, 15h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo