Ciao a tutti/e,
premetto che prima di postare ho cercato su Internet e ho utilizzato la ricerca del forum, ma forse per distrazione mia non ho trovato ciò che cercavo.
Sto utilizzando le swing, i Task e Kettle per eseguire delle lavorazioni.
Quello che devo fare è eseguire un Task che esegue una lavorazione kettle per l'aggiornamento di un DB Derby tramite actionPerformed di un JButton.
Il tutto funziona bene fino a quando non mi hanno chiesto di aggiungere una barra di progressione per vedere a che punto è la lavorazione essendo molto lunga (un paio d'ore).
Ho scritto una classe KettleTask che estende Task: la classe esegue le lavorazioni e cerca di determinare a che punto è la lavorazione:
DI seguito inserisco il codice che dovrebbe mostrare la progressione:codice:package herarc; import java.util.List; import javax.swing.JButton; import javax.swing.JLabel; import org.jdesktop.application.Application; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.Result; import org.pentaho.di.core.util.EnvUtil; import org.pentaho.di.job.Job; import org.pentaho.di.job.JobEntryListener; import org.pentaho.di.job.JobMeta; import org.pentaho.di.job.entry.JobEntryCopy; import org.pentaho.di.job.entry.JobEntryInterface; /** * * @author marco */ public class KettleTask extends org.jdesktop.application.Task<Object, Void> { /* * ATTRIBUTI */ private int constructor; //Contiene il costruttore utilizzato private int process; //numero del processo Kettle da eseguire private Job job; //contiene il job etl in esecuzione private JobMeta jobMeta; //contiene il meta job, utile per job private String res; //contiene il risultato del job private JButton button; //pulsante da abilitare una volta terminata l'esecuzione etl private JLabel label; //Label per mostrare i messaggi kettle all'utente private String file; //contiene il nome del file etl da eseguire /* * COSTRUTTORI */ //esegue il file in base al numero del processo public KettleTask(Application app, int p, JButton b, JLabel l) { super(app); this.setConstructor(0); this.setProcess(p); this.setFile(); this.setButton(b); this.setLabel(l); } //esegue il file che gli viene passato come parametro public KettleTask(Application app, String file, JButton b, JLabel l) { super(app); this.setConstructor(1); this.setFile(file); this.setButton(b); this.setLabel(l); } /* * METODI DI OVERRIDES */ @Override //metodo che viene eseguito durante l'esecuzione del job protected Void doInBackground() throws Exception { this.initKettle(); this.setProcessProgressValues(); this.runKettle(); return null; } @Override //metodo che viene eseguito quando il processo è terminato protected void finished() { this.getButton().setEnabled(true); super.finished(); } /* * METODI */ //metodo che inizializza Kettle public void initKettle() { this.getButton().setEnabled(false); try { KettleEnvironment.init(); EnvUtil.environmentInit(); this.setJobMeta(new JobMeta(this.getFile(), null)); this.setJob(new Job(null, this.getJobMeta())); } catch (Exception ex) { System.out.print("Errore kettle:\n" + ex); } } //metodo che lancia Kettle public void runKettle() { this.getJob().start(); this.getJob().waitUntilFinished(); if (this.getJob().getErrors() == 0) { this.updateRes("\nTrasformazione eseguita.\nErrori Rilevati: " + job.getResult().getNrErrors()); } else { this.setRes("Errore durante la trasformazione!"); } } //Controlla lo stato delle lavorazioni kettle e lo manda alla maschera public void setProcessProgressValues() { this.getJob().addJobEntryListener(new JobEntryListener() { int i = 0; public void beforeExecution(Job job, JobEntryCopy jec, JobEntryInterface jei) { i++; List<JobEntryCopy> jobCopies1 = job.getJobMeta().getJobCopies(); int size = jobCopies1.size() - 2; float perc = ((float) i / (float) size) * 100; System.out.print("inizio job " + i + " di " + size + " (" + (int) perc + "%)\n"); setProgress((int) perc); } public void afterExecution(Job job, JobEntryCopy jec, JobEntryInterface jei, Result result) { //System.out.print("termino un job\n"); } }); } public void setProcessFile() { switch (this.getProcess()) { case 0: this.setFile("kettle/job_recre.kjb"); break; case 1: this.setFile("kettle/carica_importi.kjb"); break; } } /* * METODI DI SET/GET E UPDATE */ //setter private void setConstructor(int c) { this.constructor = c; } private void setProcess(int n) { this.process = n; } private void setJob(Job j) { this.job = j; } private void setJobMeta(JobMeta j) { this.jobMeta = j; } private void setRes(String r) { this.res = r; } private void setButton(JButton b) { this.button = b; } private void setLabel(JLabel l) { this.label = l; } private void setFile(String f) { this.file = f; } private void setFile() { this.setProcessFile(); } //getter public int getConstructor() { return this.constructor; } public int getProcess() { return this.process; } public Job getJob() { return this.job; } public JobMeta getJobMeta() { return this.jobMeta; } public String getRes() { return this.res; } public JButton getButton() { return this.button; } public JLabel getLabel() { return this.label; } public String getFile() { return this.file; } //update private void updateRes(String s) { this.res = this.res + s; } }
E questo invece è il codice che viene eseguito alla pressione del JButton:codice:public void propertyChange(java.beans.PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); if ("started".equals(propertyName)) { //mostro la progressBar showProgressBar(); if (!busyIconTimer.isRunning()) { statusAnimationLabel.setIcon(busyIcons[0]); busyIconIndex = 0; busyIconTimer.start(); } } else if ("done".equals(propertyName)) { //nascondo la progressBar if (bar.isVisible()) { hideProgressBar(); } busyIconTimer.stop(); statusAnimationLabel.setIcon(idleIcon); } else if ("message".equals(propertyName)) { String text = (String) (evt.getNewValue()); statusMessageLabel.setText((text == null) ? "" : text); messageTimer.restart(); } else if ("progress".equals(propertyName)) { //setto valore nella progressBar int value = (Integer) evt.getNewValue(); bar.setValue(value); } } });
Uso NetBeans 6.9.1 e quindi la gestione del progress tramite TaskMonitor è quella di default del progetto che ho creato con l'IDE in questione.codice:private void aggiornaDBButtonActionPerformed(java.awt.event.ActionEvent evt) { Task kettleTask = new KettleTask(getApplication(), 0, aggiornaDBButton, progressLabel); org.jdesktop.application.ApplicationContext appC = Application.getInstance().getContext(); TaskService ts = appC.getTaskService(); TaskMonitor tm = appC.getTaskMonitor(); ts.execute(kettleTask); tm.setForegroundTask(kettleTask); }
Il tutto funziona se non per il setProgress() che non ne vuole sapere di essere eseguito, come se qualcosa tenesse tutto bloccato fino alla fine del doInBackground(), nonostante setProcessProgressValues() comunque funzioni perché il System.out.print(...) viene eseguito correttamente con i dati giusti.
Facendo delle prove ho notato che modificando la classe KettleTask in questo modo il progresso mi funziona e la progressBar viene aggiornata:
Se invece invoco setProgress(50); dopo this.setJobMeta(...); come di seguito la progressBar non viene aggiornata:codice:... ... ... ... @Override //metodo che viene eseguito durante l'esecuzione del job protected Void doInBackground() throws Exception { this.initKettle(); this.runKettle(); return null; } ... ... ... ... public void initKettle() { this.getButton().setEnabled(false); try { KettleEnvironment.init(); EnvUtil.environmentInit(); setProgress(50); this.setJobMeta(new JobMeta(this.getFile(), null)); this.setJob(new Job(null, this.getJobMeta())); } catch (Exception ex) { System.out.print("Errore kettle:\n" + ex); } }
Non posso chiaramente richiamare setProcessProgressValues(); prima della creazione dell'oggetto Job o JobMeta perché incorrerei in un nullPointerException.codice:... ... ... ... @Override //metodo che viene eseguito durante l'esecuzione del job protected Void doInBackground() throws Exception { this.initKettle(); this.runKettle(); return null; } ... ... ... ... public void initKettle() { this.getButton().setEnabled(false); try { KettleEnvironment.init(); EnvUtil.environmentInit(); this.setJobMeta(new JobMeta(this.getFile(), null)); setProgress(50); this.setJob(new Job(null, this.getJobMeta())); } catch (Exception ex) { System.out.print("Errore kettle:\n" + ex); } }
Nessuno di voi conosce un modo per far si che setProgress(50) funzioni anche dopo la creazione dell'oggetto JobMeta() e Job()?
Ringrazio in anticipo chiunque dedicherà il suo tempo e le sue competenze a questo problema.

Rispondi quotando