Mi ritrovavo a scrivere un web service e come engine usavo il solito Axis (eh si, ultimamente ho lavorato solo sui web services :P).
Il servizio utilizzava una libreria esterna che doveva fare delle conversioni e come output creava dei file. Dopo la conversione, il servizio creava un archivio zippato dell'output della libreria e cancellava i singoli file creati.
O almeno, questo era quello che volevo fare.
Infatti mi sono accorto che alcuni file non venivano cancellati. Sullo stesso output, a volte non riuscivo a cancellare dei file e a volte altri.
Il dubbio iniziale era che ci potesse essere qualche problema di permessi di Tomcat, ma ho scartato subito questa possibilità perchè altrimenti i file avrebbe dovuto cancellarmeli o tutti o nessuno.
Quindi ho capito che semplicemente restavano dei file aperti. La conferma l'ho avuta controllando con Process Explorer.
In un servlet container come Tomcat, quando restano dei file handler aperti, questi non vengono chiusi per tutta la vita del processo. Solo riavviando Tomcat questi vengono chiusi in quanto muore il processo che li tiene aperti.
Infatti nel mio caso, la prima esecuzione funzionava benissimo, erano le successive che mi davano problemi!
Ora, la libreria che utilizzavo fortunatamente era opensource, ma visto che non avevo tempo (e soprattutto perchè sono pigro :P), non potevo mettermi a capire quando e come la libreria apriva e chiudeva file, anche perchè non era così semplice il codice..
L'idea che ho avuto è questa: visto che gli handler vengono chiusi quando muore il processo, se questi vengono aperti in un processo esterno, vengono chiusi quando questo muore.
La libreria era un jar eseguibile anche da riga di comando, quindi potevo eseguirla tranquillamente con il metodo exec() della classe java.io.Runtime.
Il codice per fare ciò è questo:
try { Process p = Runtime.getRuntime().exec("java -jar library.jar parameters"); p.waitFor(); } catch (InterruptedException | IOException e) { e.printStackTrace(); }
In caso non sia possibile eseguire il jar da linea di comando basta creare un jar composto da una semplice classe che fa da wrapper ed utilizza il jar.
Magari questa non è la migliore soluzione a questo tipo di problemi..però è quella che mi è venuta in mente, ha funzionato e la condivido :)
Nessun commento:
Posta un commento