Problema:volete fare unit test del codice ma avete progettato il vostro sistema perchè recuperi la connessione al database attraverso JNDIesposto da Tomcat.
Non volete / potete eseguire unit test all'interno del tomcat ma volete utilizzare alcune classi di test scritte apposta per farlo.
Soluzione: create una istanza di JNDI prima di fare eseguire il vostro codice, così tutto funzionerà normalmente!
Per farlo vi occorrono un po' di cose:
- commons-dbcp
- commons-pool
- un provider jndi (nel nostro esempio, utilizzeremo quello basato su file system)
- il driver JDBC per il vostro database (nel nostro esempio useremo quello per Postgresql)
Una volta che avete scaricato e aggiunto al classpath della vostra applicazione questi quattro jar, siete pronti a creare la vostra istanza di JNDI stand alone!
Ecco come fare:
// Diciamo a JNDI quale factory vogliamo utilizzare
// per salvare gli oggetti che binderemo
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
// Diciamo quale percorso sul file system dovrà essere
// usato per salvare i dati
System.setProperty(Context.PROVIDER_URL, "file:///tmp/store");
// Configuriamo il datasource
InitialContext ic = new InitialContext();
Reference ref = new Reference("javax.sql.DataSource",
"org.apache.commons.dbcp.BasicDataSourceFactory", null);
ref.add(new StringRefAddr("driverClassName", "org.postgresql.Driver"));
ref.add(new StringRefAddr("url", "jdbc:postgresql:mydb"));
ref.add(new StringRefAddr("username", "dvel"));
ref.add(new StringRefAddr("password", "password"));
// Il nome con cui lo bindate sarà il nome che il
// vostro codice utilizzerà per recuperarlo
ic.rebind("java:comp/env/jdbc/myDbReference", ref);
Ecco fatto!
Ora potrete testare il vostro codice chiamandolo come fareste dall'applicazione web:questo funzionerà come se sotto ci fosse Tomcat a servirgli le connessioni attraverso il DataSource!
Ovviamente questo codice dev'essere eseguito prima di invocare il vostro codice, pena un'eccezione che dice che il nome non è stato bindato nel contesto!
Un po' di suggerimenti.
Il file system provider che utilizziamo in questo esempio scriverà i file nel percorso che gli avete detto. Nel nostro caso in questo:
System.setProperty(Context.PROVIDER_URL, "file:///tmp/store");
È necessario che all'interno di questo percorso voi creiate anche il percorso che utilizzate per salvare l'oggetto, ovvero:
ic.rebind("java:comp/env/jdbc/myDbReference", ref);
altrimenti otterrete una eccezione da parte del SecurityManager.
In pratica, sul vostro file system, dovrete trovarvi questa gerarchia di cartelle:
/tmp/store/java:comp/env/jdbc
Un'ultima nota:se i jar che ho proposto qui sopra li avete aggiunti come librerie del progetto, fate in modo che queste non vengano poi deployate sulla webapp in tomcat. Questi jar, infatti, dovreste averli già presenti nella vostra <$tomcat_dist>/common/lib
e andrebbero in conflitto causando malfunzionamenti dell'applicazione!
Reference:
- Java Naming and Directory Interface (JNDI)
- Tomcat 5.5 e JNDI