mercoledì 6 giugno 2012

Virtuoso Universal Server: un DBMS per tutto

Salve :)
In questo post volevo parlare di un DBMS che ho scoperto recentemente e ho trovato molto interessante.

Parlo di Virtuoso Universal Server (http://virtuoso.openlinksw.com/), un DBMS che, un po come tutti, promette di risolvere tutti i problemi del mondo :)
La particolarità di questo server è che effettivamente può fare un po' di tutto, nel senso che può essere usato sia come DBMS relazionale, sia come un NoSQL Database, come XML Store e come Triple Store.

Come DBMS relazionale offre un po' tutte le caratteristiche che offrono gli RDBMS tipici come MySQL e simili. Ovviamente supporta il linguaggio SQL, inoltre mette a disposizione molte funzioni utili.

Per quanto riguarda le sue funzionalità come XML Database, Virtuoso non è uno store nativo, cioè il documento XML non è visto come unità fondamentale di memorizzazione e i dati fisicamente non vengono memorizzato secondo la struttura di questi documenti. Infatti questi vengono memorizzati in tabelle SQL, come tipo di dato XML appunto. In pratica questo tipo di dato sarebbe un long varchar, ma utilizzando il tipo XML viene fatto anche il parsing dei documenti, in modo tale che, se durante un inserimento viene passato qualcosa che non è un documento ben formato, viene notificato direttamente un errore.
Ha diverse funzioni per l'utilizzo dei documenti XML e supporta XPath, XQuery e le trasformazioni XSLT.

Per quanto riguarda invece le sue funzionalità come Triple Store, il modello di dati utilizzato è il modello a grafo, che è quello utilizzato dalla maggior parte dei Triple Store che non si basano su database relazionali. In realtà non so il modello di dati fisico quale sia, ma il modello utilizzato per i dati in memoria è sicuramente a grafo.
E' possibile interrogarlo tramite il linguaggio SPARQL , eseguire update tramite SPARUL ed è possibile importare ed esportare dati in formato RDF. I formati di serializzazione RDF supportati sono HTML+RDFa, RDF-JSON, N3, Turtle, TriG, TriX e RDF/XML.


Virtuoso permette di essere utilizzato sia come SQL che NoSQL Database grazie alla virtualizzazione dei dati. Il modello fisico di memorizzazione è comune a tutti i motori DBMS, ma ognuno di essi vede i dati come se fossero memorizzati nel formato che più si adatta a loro.
La cosa penalizza le prestazioni?
In teoria potrebbe, ma in pratica leggendo in giro sembra sia abbastanza veloce. Personalmente l'ho provato solo su pochi dati e non ho eseguito nessuno stress test quindi non ho elementi per giudicare.
Come Triple Store sembra si comporti particolarmente bene. Ho visto diversi benchmark che lo confermano e anche in questa classifica W3C sembra si comporti abbastanza bene: http://www.w3.org/wiki/LargeTripleStores.

Questa immagine riassume un po la virtualizzazione dei dati e i vari moduli da cui è composto Virtuoso:


Un'altra caratteristica molto interessante è che è molto semplice esporre le funzionalità di Virtuoso come web services. Infatti supporta può essere interrogato sia utilizzando SOAP che REST.
Si possono scrivere delle stored procedures e pubblicarle direttamente come servizi, con tanto di generazione automatica del WSDL.
Inoltre è possibile in qualche modo riutilizzare anche i web service scritti in Java, modificando un po il codice per eseguire una sorta di wrap. E' possibile riutilizzare anche i servizi scritti in linguaggi della piattaforma .NET.
Infine è disponibile un'estensione per poter utilizzare Virtuoso come motore BPEL4WS!
Grazie a questa è possibile organizzare le orchestrazioni dei servizi facendone il deploy direttamente nel DBMS.

Insomma, a mio parere le potenzialità sono molte, soprattutto negli scenari in cui si ha bisogno di dover gestire diversi tipi di dati ed avere la gestione migliore per ognuno di essi.
Inoltre poter gestire i dati, i servizi e magari anche le orchestrazioni da un unico punto semplifica parecchio la gestione..

Per concludere, Virtuoso è disponibile sia in versione commerciale che open source. La versione open source ovviamente ha qualche limitazione, non supporta infatti la replicazione dei dati e quello che chiamano "Virtual Database Engine", che permette di eseguire query SQL su database multipli remoti.
Personalmente ho fatto qualche sperimentazione con la versione opensource. Credo che sia molto più comodo utilizzarlo su sistemi Unix che non su Windows. Su sistemi come Ubuntu, per esempio, sono disponibili già i binari installabili dal gestore di pacchetti. Su Windows invece per poterlo compilare c'è bisogno di strimenti come Visual Studio ed altra roba..

Bene, direi che ho concluso con questo post pubblicitario :)
In questi giorni ho accantonato Virtuoso per fare delle prove con l'XML Database eXist. Se lo trovo interessante magari scriverò qualcosina anche su quello :)

Al prossimo post!

lunedì 4 giugno 2012

Java e la ridirezione con processi esterni

Salve di nuovo :)

Visto che ultimamente ho scritto un post con tante chiacchiere e 2 righe di codice che servivano ad eseguire il redirect dello standard output e lo standard error su altri stream, ora voglio scrivere un post che parla di una cosa molto simile: eseguire il redirect di standard output e standard error, ma di processi esterni.

Ovviamente la cosa si può fare solo su processi di cui si ha il controllo via codice. per esempio dopo averli eseguiti con il metodo exec() di  java.io.Runtime.

Siccome il processo lanciato è indipendente da quello che l'ha generato allora l'I/O e l'error saranno su stream separati. In poche parole sul video non viene visualizzato nulla di quello che il nuovo processo stampa.
Quindi per poter ottenere comunque i dati che vengono stampati bisogna catturare lo stream di tale processo e successivamente stamparlo su qualche altro stream, magari lo standard I/O ed error del processo padre.

Il codice per fare tutto ciò è il seguente:

try {
   Process p = Runtime.getRuntime().exec("comando");
  
   String line;

   BufferedReader in = new BufferedReader(
               new InputStreamReader(p.getInputStream()) );

   while ((line = in.readLine()) != null) 
       System.out.println(line);
        
   in.close();
        
   in = new BufferedReader(
               new InputStreamReader(p.getErrorStream()) );

   while ((line = in.readLine()) != null)
       System.err.println(line);
        
   in.close();
}
catch(IOException | InterruptedException e) {
   e.printStackTrace();
}

E questo è quanto.
Ovviamente questo funziona con Java 7, altrimenti non si può fare la cosa figa del multi catch :)

Al prossimo post!

giovedì 31 maggio 2012

Tomcat e i file stream "pendenti"

Bene, oggi voglio parlare di un problemino che ho avuto un paio di giorni fa.

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 :)

mercoledì 30 maggio 2012

Invio e ricezione di file da web services

Eccomi qui con un nuovo posto..
Ultimamente sto tenendo una bella media, chissà se riuscirò a tenere questa costanza.. :)

Bene, oggi volevo scrivere un post sull'invio e la ricezione di file verso e da un web service, visto che è una cosa che mi sono ritrovato a fare solo recentemente.

In questo post sia i servizi1 che i client saranno scritti in Java. Il web service engine che utilizzato è Apache Axis (installato su Tomcat 7) ed il protocollo di comunicazione è SOAP.

Per la generazione del pacchetto .aar contenente le classi per "deployare" il servizio in Axis è stato utilizzato il plugin per Eclipse "Service Archiver", mentre per creare il file WSDL dal codice del servizio e generare il client dal WSDL creato sono stati utilizzati Java2WSDL e WSDL2Java, entrambi contenuti nel plugin "Code Generator". Questi tool sono disponibili all'indirizzo: http://axis.apache.org/axis2/java/core/tools/index.html.

Prenderemo in considerazione un servizio, FileService che mette a disposizione 2 operazioni: UploadFile e GetFile.
La cosa importante affinchè le cose funzionino è definire la firma dei metodi corrispondenti alle operazioni affinchè il Code Generator possa generare un file WSDL con il giusto mapping tra i tipi.

Una prima prova potrebbe essere fatta specificando come parametro dell'operazione UploadFile e come tipo restituito dall'operazione GetFile semplicemente java.io.File. 
Purtroppo questa non è una buona soluzione. Se si prova ad utilizzare Java2WSDL con i metodi così definiti, verrà generato un correttamente il file WSDL desiderato. Il problema, però, nasce quando si utilizza WSDL2Java per generare il client. Dalle classi create si vede che il mapping dei tipi è abbastanza sballato, infatti ci sono delle classi come java.io.xsd.File che per essere utilizzate come minimo dovrebbero essere incluse in un package diverso, in quanto l'uso del nome java.io per un package è ovviamente proibito.
Non so se sia possibile utilizzare comunque java.io.File per il trasferimento dei dati, probabilmente definendo a mano i tipi complessi nel WSDL e costruento i messaggi SOAP tramite codice è possibile, ma se uno non ha tempo, o non ha voglia, o una combinazione delle 2, allora sarebbe preferibile percorrere un'altra strada :)

Bene, dopo aver visto questa non-soluzione passiamo alle 2 che ho sperimentato:
  • trasferire dati tramite array di byte e DataHandler
  • trasferire dati tramite DataHandler utilizzando MTOM per gli allegati SOAP

Array di Byte
Questo metodo è abbastanza intuitivo, per fare l'upload di un file si passa un'array di byte che rappresenta il contenuto del file e il web service che lo riceve lo scrive su file. Lato client, però, non si può passare semplicemente un array di byte, ma dev'essere passato un DataHandler.

Il servizio può essere per esempio il seguente:

public class ImportService { 
  public String importSingleFile(String name, byte[] content) {
     try {
       File f = new File(name); 
       BufferedWriter out = new BufferedWriter(new FileWriter(f));
       out.write(s);
       out.close();

       return "Import Successful!";
    } 
    catch(IOException e) {
       e.printStackTrace();
    }
  } 
 }  

Con Java2WSDL si può creare il file che descrive il servizio e con WSDL2Java si può generare il client che lo interroga. Il client sarà composto da una serie di classi,tra cui ImportStub e ImportSingleFile che corrispondono rispettivamente al servizio ed all'operazione da richiamare.

Il client, per poter trasferire il file al servizio, dovrà:
  • aprire il file che vuole trasferire
  • associare il file ad un DataSource (presente in javax.activation)
  • associare il DataSource ad un DataHandler (sempre in javax.activation)
  • richiamare il servizio
Ecco il codice:


public class Client { 
  public static void main(String args[]) {
     try {
       ImportStub stub = new ImportStub(); 
       ImportSingleFile single = new ImportSingleFile();
       
       File f = new File("upload.txt");
       FileDataSource ds = new FileDataSource(f);
       DataHandler dh = new DataHandler(ds);

       single.setName(f.getName());
       single.setContent(dh);

       ImportSingleFileResponse res = stub.importSingleFile(single);

       System.out.println(res.get_return());
    } 
    catch(IOException | AxisFault e) {
       e.printStackTrace();
    }
  } 
 }  

 E questo è quanto.
Il problema con questa soluzione è che i dati binari vengono codificati come testo per poi venire spediti in messaggi SOAP. Per ovviare a questo problema è possibile utilizzare MTOM.


MTOM e DataHandlers
MTOM  (Message Transmission Optimization Mechanism) è una raccomandazione W3C per inviare e ricevere dati binari da web services. Altri meccanismi possono essere utilizzati per lo stesso scopo, come SwA (SOAP with Attachments) e i DIME Attachments, ma a MTOM sembra sia migliore di questi ultimi.

Per poterlo utilizzare in Axis è necessario abilitarlo: bisogna editare il file di configurazione axis/WEB-INF/conf/axis2.xml e settare a true il parametro enableMTOM.

Fatto ciò si può scrivere il servizio. In realtà cambia molto poco: invece di un array di byte come parametro prende un DataHandler. Ecco il codice:


public class ImportService { 
  public String importSingleFile(String name, DataHandler dh) {
     try {
       File f = new File(name); 
       FileOutputStream fos = new FileOutputStream(f);

       dh.writeTo(fos);
       fos.close();

       return "Import Successful!";
    } 
    catch(IOException e) {
       e.printStackTrace();
    }
  } 
 }  

Il client invece resta esattamente uguale.

E così si conclude questo post..spero di scrivere qualche altra cosa presto! :)

sabato 26 maggio 2012

Java e la redirezione

Salve :)
Eccomi qui con un nuovo post. Voglio parlare di una questione che ho affrontato pochi giorni fa.

In C in ambiente Unix è molto semplice fare la ridirezione di flussi come lo Standard I/O o lo Standard Error. In Java, come si può immaginare, è altrettanto semplice :)
Mi sono ritrovato ad utilizzare la ridirezione utilizzando delle librerie in un progetto. Era una libreria opensource per eseguire delle conversioni di manualistica che segue lo standard S1000D. Funziona bene, fa il suo sporco lavoro, ma sfortunatamente quando c'è qualcosa che non va invece di lanciare eccezioni, restituire qualcosa in particolare o qualsiasi altra cosa, scrive semplicemente sullo Standard IO l'eccezione avvenuta.
Questo fin quando la si utilizza da riga di comando è tranquillamente accettabile, ma quando la si utilizza attraverso un web service deployato sotto Axis fallisce "silenziosamente", infatti non è possibile visualizzare eventuali messaggi di errore.
Da bravo pigro e per sbrigarmi non sono stato a modificare i sorgenti della libreria, ma ho rididezionato l'I/O e gli errori su file.

E' un'operazione estremamente semplice, facile anche da cercare su google, ma visto che avevo voglia di scrivere un post, che non fosse troppo lungo o impegnativo, la riporto qui :)

I passi da seguire sono 2:
  1. Aprire un PrintStream sul file nel quale si desidera siano scritti i contenuti
  2. Settare il System.out affinchè utilizzi lo stream
Di seguito c'è un esempio su come ridirigere lo standard I/O e lo standard error su 2 file diversi:


PrintStream ioStream = new PrintStream(new File("IO.txt")); 
PrintStream errorStream = new PrintStream(new File("error.txt"));  


System.setOut(ioStream); 
System.setErr(errorStream);
 

Bene, un post intero per 4 righe di codice!
Ma avevo voglia di scrivere, cosa alquanto rara e non avevo voglia di scrivere niente di impegnativo :)

venerdì 25 maggio 2012

Cotton Candy, una smart pen Android!

E' da una vita che non scrivo qualcosa su questo blog...
Ogni tanto però ritorno :)

Ultimamente mi sono trovato ad affrontare molte problematiche interessanti in ambito lavorativo e spero di avere tempo e soprattutto voglia di scrivere qualcosa sulle problematiche che mi sono trovato ad affrontare e che mi hanno fatto impazzire.

 Per ora voglio buttare giù 2 righe su questa Cotton Candy (http://www.fxitech.com/products/).

Praticamente un mini PC in una chiavetta, che permette di utilizzare un qualsiasi televisore che abbia una porta HDMI come un PC, con la comodità di poterla portare sempre con sè viste le ridotte dimensioni.
La cosa interessante è che le caretteristiche tecniche non hanno nulla da invidiare agli smartphone più avanzati:
  • CPU ARM Cortex-A9, 1.2GHz (non so se dual o quad core)
  • GPU ARM Mali, 400MP Quad Core
  • 1 GB di Ram
  • Storage fino a 64GB con micro SD
 I sistemi operativi a che può montare sono Ubuntu o Android, ma dispone persino di un client per la virtualizzazione per Windows e Mac OS!
Inoltre ha connettività Bluetooth e Wifi b/g e persino n.

Questo apparecchietto dovrebbe essere commercializzato in italia a fine estate, il costo approssimativo si stima essere intorno ai 200 dollari..
In questo articolo è presente anche un bel video dove dimostrano il suo utilizzo.

Intanto che l'apparecchio venga commercializzato, la FXI permette di preordinare la Cotton Candy :)
http://www.fxitech.com/2012/02/fxi-launches-cotton-candy-developers-site-take-pre-orders/

Beh, sarebbe molto interessante poter "giocare" con un apparecchietto simile, chissà in Italia se e a che prezzo verrà messo in vendita!!

venerdì 15 aprile 2011

Gladinet - Montare dischi remoti come cartelle locali

Salve a tutti!
Sono mesi che non scrivo nulla su questo blog e ho scritto pochissimi post...colpa degli impegni ma soprattutto della mia pigrizia..

Beh, ho appena scoperto un programmino molto utile, si chiama Gladinet ed è disponibile all'indirizzo: http://www.gladinet.com/

Come il titolo del post suggerisce, questo programma consente di montare dischi remoti come se fossero cartelle locali, modificarne i contenuti, avere copie da utilizzare offline e sincronizzare il contenuto su diversi pc.
La cosa che personalmente ho trovato molto utile è che permette di montare localmente servizi di storage come Google Docs, Picasa, Microsoft Skydrive e molti altri ancora.
Io ho provato la versione free e sembra che non manchi nulla di necessario :)
Certo, magari ce ne sono altri 1000 di programmi che fanno la stessa cosa..ma io ho provato questo e mi sono trovato bene :P

Beh..il minipost finisce qui..vi saluto sperando di scrivere qualcosa di più interessante al più presto.. :)