Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    41

    TimerTask dentro Tomcat

    Buongiorno, metto subito le mani avanti dicendo che ho già cercato sia tramite Google che nel forum ed ho visto che l'argomento è trattato ampiamente ma tutto ciò che ho provato non funziona nel mio caso.
    La mia applicazione è un web service che espone diversi servizi tra cui la possibilità di impostare un periodo di ripetizione per i backup. In pratica quando il periodo impostato scade viene effettuato un backup del DB che viene salvato in una cartella appositamente creata.
    Per fare questa operazione ho utilizzato le classi Timer e TimerTask in questo modo:
    codice:
    public class BackupAutomaticoServlet extends HttpServlet {
    
    	private static final long serialVersionUID = 1L;
    	private Date delay;
    	private Long tempo;
    
    	public BackupAutomaticoServlet(Date delay, Long tempo) {
    		super();
    		this.delay=delay;
    		this.tempo=tempo;
    	}
    	
    	public void init(){
    		Timer autoBackup=new Timer();
    		if(delay!=null) autoBackup.scheduleAtFixedRate(BackupAutomaticoTask.getSingleton(), delay, tempo);
    		else autoBackup.scheduleAtFixedRate(BackupAutomaticoTask.getSingleton(), 0, tempo);
    	}
    	
    private static class BackupAutomaticoTask extends TimerTask{
    		
    	private String dbName;
    	private String host;
    	private static BackupAutomaticoTask istanza;
    	
    	public BackupAutomaticoTask(){
    		String[] s=SystemManager.URL_DB.split("/");
    		host=s[0];
    		dbName=s[1];
    	}
    
    	public void eseguiBackup(){
    		try {
    	        SimpleDateFormat sdf=new SimpleDateFormat("dd-MM-yyyy");
    	        String dataFormattata=sdf.format(new Date());
    	        SimpleDateFormat sdf2=new SimpleDateFormat("HH mm");
    	        String oraFormattata=sdf2.format(new Date());
    	        System.out.println(oraFormattata);
    	        System.out.println(dataFormattata);
    	        String path = "backup/crm_backup_";
    	        path+=dataFormattata;
    	        path+="_"+oraFormattata;
    	        path+=".backup";
    	        ProcessBuilder pb = new ProcessBuilder("pg_dump", "-h", host, "-Fc", "-f", path, "-U", SystemManager.USERNAME_DB, dbName);
    	        pb.start();
    	        SystemManager.salvaConfUltimoBackup(dataFormattata, oraFormattata);
    	    } catch (IOException e) {
    	    	e.printStackTrace();
    	 	    SystemManager.logger.info(e.getMessage());
    		}
    	}
    		@Override
    	public void run() {
    		try {
    			DateFormat formatter=new SimpleDateFormat("HH.mm");
    			Calendar orarioRipetizioneBackup=Calendar.getInstance();
    			orarioRipetizioneBackup.setTime(formatter.parse(SystemManager.ORARIO_RIPETIZIONE_BACKUP));
    			Calendar orarioAttuale=Calendar.getInstance();
    			orarioAttuale.setTime(formatter.parse(formatter.format(new Date())));
    			if(orarioAttuale.compareTo(orarioRipetizioneBackup)>=0){
    				System.out.println("Inizio backup");
    				this.eseguiBackup();
    				System.out.println("Metodo eseguiBackup eseguito");
    			}
    		} catch (ParseException e) {}
    	}
    	
    	public static BackupAutomaticoTask getSingleton(){
    		if(istanza==null) {
    			istanza=new BackupAutomaticoTask();
    		}
    		return istanza;
    	}
    }
    
    }
    Scrivo qui perchè ovviamente non vuole saperne di funzionare...
    Ora come ora il backup viene eseguito una sola volta dopodichè avviene un crash e tomcat fa il restart dell'applicazione perchè avviene un memory leak.
    Ho provato diverse configurazioni del file web.xml:

    -loadOnStartup 1
    -loadOnStartup 10
    -loadOnStartup 100
    -senza loadOnStartup

    tutto rimane invariato.
    Potete illuminarmi su come fare a utilizzare un benedetto TimerTask dentro Tomcat?
    Grazie!

  2. #2
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    8,013
    ciao, premesso che io userei un cronjob / processo in esecuzione automatica (che succede se casca il sistema e tomcat o altro servlet container non si riavvia?), potresti postare eventuali log del crash e gestire l'eccezione nel run? (anche una stampata dello StackTrace, dovesse succedere qualcosa a partire da quel metodo)
    <´¯)(¯`¤._)(¯`»ANDREA«´¯)(_.¤´¯)(¯`>
    "The answer to your question is: welcome to tomorrow"

  3. #3
    Originariamente inviato da Andrea1979
    ciao, premesso che io userei un cronjob / processo in esecuzione automatica (che succede se casca il sistema e tomcat o altro servlet container non si riavvia?), potresti postare eventuali log del crash e gestire l'eccezione nel run? (anche una stampata dello StackTrace, dovesse succedere qualcosa a partire da quel metodo)
    Quoto. E' il modo più affidabile.
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  4. #4
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    41
    Piano piano ci sto riuscendo...
    Ora sono incastrato in un'altra cosa, cioè nel salvataggio di un file di configurazione all'interno di una servlet.
    Mi spiego meglio:

    codice:
    public static void salvaConfUltimoBackup(String data, String orario){
    	DATA_ULTIMO_BACKUP=data;
    	ORA_ULTIMO_BACKUP=orario;
    	Properties p=new Properties();
    	try{
    		p.load(SystemManager.class.getResourceAsStream("../../../conf/Sys.conf"));
    		p.setProperty("dataUltimoBackup", SystemManager.DATA_ULTIMO_BACKUP);
    		p.setProperty("oraUltimoBackup", SystemManager.ORA_ULTIMO_BACKUP);
    		OutputStreamWriter os = new OutputStreamWriter(
                                   SystemManager.class.getResource("../../../conf/Sys.conf")
                                    .openConnection().getOutputStream());
    		p.store(os, null);
    	} catch(Exception e){
    		e.printStackTrace();
    		logger.fatal("Errore: forse il file di configurazione di sistema è stato spostato
                                  oppure non esiste. Controllare il file di configurazione di sistema.");
    	}
    }
    In pratica quando il tempo che ho settato scade il backup viene eseguito e poi dovrei salvare nel file di configurazione la data e l'ora in cui il backup è stato effettuato.
    Quando vado a salvare (usando il codice che ho postato) ottengo la seguente eccezione:

    java.net.UnknownServiceException: protocol doesn't support output
    at java.net.URLConnection.getOutputStream(Unknown Source)
    at server.utility.SystemManager.salvaConfUltimoBackup (SystemManager.java:228)
    at server.utility.BackupAutomaticoServlet$BackupAutom aticoTask.run(BackupAutomaticoServlet.java:113)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

    Leggendo in giro credo di aver capito che una connessione ad una servlet non consente di usare un outputStrem a meno di non aprirlo in qualche modo prima.
    Ho provato anche a salvare il file aprendo "a mano" un outputStrem (esattamente un FileOutputStream) ma neanchè così sono riuscito nell'intento (così però non viene generata l'eccezione di sopra ma tomcat ripubblica l'applicazione direttamente).
    Quindi la domanda è: come posso aprire un outputStream in modo tale da salvare il file?

  5. #5
    una connessione ad una servlet non consente di usare un outputStrem a meno di non aprirlo in qualche modo prima.
    Non ho capito bene quello che vuoi fare....In ogni modo hai deciso di ignorare del tutto il suggerimento che ti è stato dato di affidare la temporizzazione del backup a un servizio esterno al tomcat (ad esempio cronjob) in modo da rendere il sistema affidabile? Se si per quale motivo? Tieni anche presente che ti semplificheresti la vita.
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  6. #6
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    41
    Non l'ho ignorato, è solo che per necessità didattiche DEVO fare tutto in java... (Leggi: alla proposta di usare cron o simili per win il professore ha risposto "No!" in modo secco). La soluzione del cronjob l'avrei scelta anch'io se avessi potuto.

    Quello che sto cercando di fare è semplicemente salvare un file testuale su filesystem utilizzando una servlet..

  7. #7
    Originariamente inviato da rama1987
    Non l'ho ignorato, è solo che per necessità didattiche DEVO fare tutto in java... (Leggi: alla proposta di usare cron o simili per win il professore ha risposto "No!" in modo secco). La soluzione del cronjob l'avrei scelta anch'io se avessi potuto.

    Quello che sto cercando di fare è semplicemente salvare un file testuale su filesystem utilizzando una servlet..
    Ok tutto chiaro hai un vincolo dal prof.
    Per quanto riguarda il raggiungimento del tuo obiettivo l'unico problema che vedo è che lo stai facendo male

    codice:
    SystemManager.class.getResource("../../../conf/Sys.conf")
                                    .openConnection().getOutputStream());
    Non mi sembra il modo adatto. Perchè non lavori semplicemente su un File e ci apri sopra un FileInputStream?
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  8. #8
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    41
    Intendi dire così:
    codice:
    ...
    bla bla bla
    ...
    
    InputStream is=SystemManager.class.getResourceAsStream("../../../conf/Sys.conf");
    p.load(is);
    is.close();
    p.setProperty("dataUltimoBackup", SystemManager.DATA_ULTIMO_BACKUP);
    p.setProperty("oraUltimoBackup", SystemManager.ORA_ULTIMO_BACKUP);
    File file=new File(path);    //path è il percorso al file da scrivere
    FileOutputStream fos=new FileOutputStream(file);
    p.store(fos, null);
    fos.close();
    
    ...
    Ci ho già provato (anche senza creare l'oggetto File) ma in questo caso ottengo un nullPointerException... vorrei solo dire che sono sicuro che non il path che specifico è quello giusto, infatti il file viene salvato ma poi Tomcat si riavvia.
    Quindi anche l'eccezione nullPointerException mi è piuttosto difficile da comprendere...

    Sono anche sicuro che il problema sia proprio il salvataggio del file perchè facendo delle prove commentando le righe FileOutputStream fos=... e fos.close() non ho errori e Tomcat continua l'esecuzione normalmente (ovviamente avendo commentato quelle righe il file non viene salvato!)...

    Ho fatto anche delle prove con FileWriter o OutputStream piuttosto che FileOutputStream ma è sempre la stessa cosa...

    Cosa può essere?

  9. #9
    Il fatto che addirittura si riavvii il tomcat mi stupisce tantissimo. Io comunque comincerei con l'evirtare di usare "SystemManager.class.getResourceAsStream" per recuperare il path del file.Per il path usa una property nel file di configurazione o (se proprio devi) inettata come parameter alla servlet dal web.xml. Ma quel file Sys.conf non è che è un file di sistema di qualche tipo che non può essere toccato? Cioè se tu lavori su un altro file da gli stessi problemi? Fai un po di prove
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  10. #10
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    41

    [RISOLTO]

    Come mi è stato suggerito ho evitato l'uso di getResourceAsStream e tutto è andato a posto.
    L'ho sostituito con il metodo ServletConfig.getServletContext().getRealPath("/") che restituisce il path assoluto alla cartella root del Web Service.
    Poi a questo path ho cancatenato il path relativo al file Sys.conf e ho passato la nuova stringa come parametro al costruttore di FileOutputStream. Così funziona tutto.

    codice:
    .....
    String path=context.getServletContext().getRealPath("/");
    Properties p=new Properties();
    	try{
    		FileInputStream fis=new FileInputStream(path+"WEB-INF/conf/Sys.conf");
    		p.load(fis);
    		fis.close();
    		p.setProperty("dataUltimoBackup", SystemManager.DATA_ULTIMO_BACKUP);
    		p.setProperty("oraUltimoBackup", SystemManager.ORA_ULTIMO_BACKUP);
    		FileOutputStream fos=new FileOutputStream(path+"WEB-INF/conf/Sys.conf");
    		p.store(fos, null);
    		fos.close();
    	} catch(Exception e){
    		logger.fatal("Errore: forse il file di configurazione di sistema è stato spostato 
                                  oppure non esiste. Controllare il file di configurazione di sistema.");
    	}
    ....
    Grazie mille!!!! Non credo che da solo ci sarei riuscito!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.