giannino1995 ha scritto:
Quando si istanzia un oggetto java prima vengono create le variabili della classe e poi vengono eseguiti i costruttori ed infine i metodi. E' così?
NO.
Innanzitutto la prima istruzione di un costruttore deve sempre essere una invocazione
super( .... ); o
this( .... ); (con o senza argomenti, dipende ovviamente dal costruttore che si vuole invocare). Se non scrivi una di queste due invocazioni esplicitamente, il compilatore mette come prima istruzione una invocazione
super(); (senza argomenti!)
Quindi nel tuo caso di prima il codice reale diventa:
DBMS db;
public DBMSConnessione() {
super(); // <---- inserito dal compilatore!
try {
ObjectMapper objectMapper = new ObjectMapper();
this.db = objectMapper.readValue(new FileReader("/DBMS.json"), DBMS.class);
System.out.println("Credenziali del DBMS lette dal file con successo.");
} catch (Exception e){
throw new DBMSEccezione("Non è stato possibile recuperare le credenziali del DBMS dal file.", e);
}
}
private final String url = db.getUrl(); // qui c'è l'eccezione.........
private final String user = db.getUser();
private final String password = db.getPassword();
Quando fai
new DBMSConnessione() quindi avverrebbe tecnicamente/teoricamente questo:
1) PRIMA viene innanzitutto eseguita la invocazione super() che invoca il super-costruttore. Se la super-classe è Object (come presumo nel tuo caso), il costruttore di Object viene eseguito, che non fa nulla di speciale. Se la super-classe facesse altro di particolare la logica di questi 3 passi si ripeterebbe a sua volta.
2) POI, appena dopo che la chiamata super() termina, vengono eseguiti tutti gli inizializzatori delle variabili di istanza e tutti gli
instance initialization block. In ordine rigorosamente testuale, cioè come si presentano nel sorgente dall'alto verso il basso.
Quindi in sequenza:
db resta a valore di default (null)
url = db.getUrl()
user = db.getUser()
password = db.getPassword()
3) POI solo dopo che le variabili di istanza sono state inizializzate e gli (eventuali)
instance initialization block eseguiti, allora il codice nel tuo costruttore prosegue, quindi viene eseguito:
try {
ObjectMapper objectMapper = new ObjectMapper();
this.db = objectMapper.readValue(new FileReader("/DBMS.json"), DBMS.class);
System.out.println("Credenziali del DBMS lette dal file con successo.");
} catch (Exception e){
throw new DBMSEccezione("Non è stato possibile recuperare le credenziali del DBMS dal file.", e);
}
Credo (spero..) che ci arrivi da solo: alla luce di questi passi, perché al db.getUrl() hai un NullPointerException?
giannino1995 ha scritto:
L'unico cosa che mi preoccupa è che java deve leggere un file ad ogni connessione e questo sovraccarica in modo sproporzionato il server.
No, non è affatto così "sproporzionato". E' la Connection che a crearla è più "costosa".
E comunque nessuno vieta di fare logiche più "furbe" del tipo:
- rileggo il file ma solo dopo che è passato (almeno) es. 1 minuto dall'ultima lettura
o meglio ancora
- rileggo il file ma solo se risulta "modificato" dopo l'ultima lettura
giannino1995 ha scritto:
Il software funziona ma temo che sia una porcheria.
Giannino, stai facendo una ESERCITAZIONE. Oltretutto avendo mille dubbi a più livelli e dimostrando anche lacune abbastanza grosse.
I risultati sono ovviamente quelli che sono per un tale livello ..... e dovrebbero/dovranno servirti per migliorare ... perlomeno per far sì che in successive esercitazioni non "caschi" nelle stesse questioni ...
giannino1995 ha scritto:
DBMS db = objectMapper.readValue(new FileReader("/WEB-INF/DBMS.json"), DBMS.class);
No. Per FileReader il "/" iniziale vuol dire "radice del file-system" (non la
context-root della webapp, di cui ovviamente non "sa" nulla).
giannino1995 ha scritto:
Se devo scrivere C: allora non ci siamo proprio neppure su questo punto.
La questione semmai è: vuoi che il file di configurazione sia "dentro" la webapp ... o "fuori"?
Se fuori, si intende ovunque sul file-system, allora hai almeno 2 possibilità:
- te lo aspetti e lo rintracci in una locazione "notevole" es. da qualche parte sotto la "home" dell'utente
- lo metti dove vuoi e poi "configuri" il path nella webapp, ad esempio con un
context param nel web.xml o un file di properties sempre nella webapp.
giannino1995 ha scritto:
Altra cosa che mi preoccupa è non poter usare qualche metodo per mascherare la password.
Anche qui, nessuno vieta di usare forme di crittografia. Chiaramente ci vuole poi una "chiave" di decifratura e la si può o generare lato codice con un algoritmo che dà sempre la stessa chiave oppure la si "occulta" un pochino in qualche modo nelle classi.
Non è una sicurezza totale in senso assoluto ma perlomeno impedisce ai "pischelli" di carpire le password aprendo file di configurazione a destra e a manca per sbirciarne il contenuto ..
giannino1995 ha scritto:
ma credo che sia troppo per me occuparmi anche di questo aspetto.
Sì, come "esercitazione" non credo serva ..