2009-06-08 9 views
35

Desidero memorizzare la configurazione per un progetto Web al di fuori del progetto Web (file ear/war). L'applicazione non deve sapere in quale contenitore è in esecuzione (WebSphere/JBoss ecc.).Come posso memorizzare i parametri di configurazione di Java EE al di fuori di un EAR o WAR?

Qual è il modo migliore per gestire questo?

JNDI è un modo pulito? Se JNDI può risolvere i miei problemi, come dovrei configurarlo? (Oggetti personalizzati?)

Nel mio caso ci sono solo Key = coppie di valori (String, String) per endpoint SOAP/WS.

+2

Java EE 8 potrebbe introdurre qualcosa chiamato "servizio di configurazione" per cose come questa. Vedi http://www.jfokus.se/jfokus13/preso/jf13_JavaEEConfiguration.pdf vedi anche http: // java.net/jira/browse/JAVAEE_SPEC-19 –

+0

Perché non utilizzare gli argomenti jva? – djmj

risposta

26

Vai a questa question per la lettura di file di proprietà al di fuori del file WAR.

Vedere questo question per leggere i valori delle variabili da JNDI. Credo che questa sia la soluzione migliore. È possibile leggere una variabile String con questo codice:

Context initialContext = new InitialContext(); 
String myvar = (String) initialContext.lookup("java:comp/env/myvar"); 

Il codice sopra funzionerà su tutti i contenitori. In Tomcat dichiari quanto segue in conf/server.xml:

<GlobalNamingResources ...> 
    <Environment name="myvar" value="..." 
     type="java.lang.String" override="false"/> 
</GlobalNamingResources> 

Quanto sopra creerà una risorsa globale. È anche possibile definire una risorsa nel contesto dell'applicazione. Nella maggior parte dei contenitori le risorse JNDI sono disponibili tramite una Management Console MBeans. Alcuni di loro offrono un'interfaccia grafica per modificarli. Al massimo è necessario un riavvio dell'applicazione, quando viene apportata una modifica.

Come le risorse JNDI sono definite e modificate è specifica del contenitore. È compito del configuratore/amministratore applicare le impostazioni appropriate.

Questi sono i vantaggi offerti da JNDI:

  • È possibile definire valori di default dei parametri nel file WAR/EAR.
  • I parametri sono facilmente configurabili nel contenitore.
  • Non è necessario riavviare il contenitore quando si modifica il valore di un parametro.
+2

Nel mio caso, l'impostazione dei parametri doveva essere eseguita da utenti "non addestrati": la navigazione di un file XML complesso per trovare l'unica cosa che doveva essere cambiata non era un'opzione (troppo rischio avrebbero cambiato qualcosa non dovrebbe e rompere l'intero contenitore.) – Jared

+0

Che cos'è un utente finale non addestrato che sta amministrando un container? – Draemon

+4

In molte organizzazioni la configurazione viene eseguita dagli amministratori di rete. In alcuni casi solo un manager è autorizzato a configurare password o altri dati sensibili. Queste persone potrebbero avere poca esperienza con XML. – kgiannakakis

10

Uso una variabile di ambiente per puntare a un URL (che probabilmente è un file: // URL) che contiene la mia configurazione. Questo è molto semplice da configurare e non richiede l'infrastruttura JNDI.

Ecco alcuni esempi di codice (digitato dalla memoria - non ho compilato/testato questo):

public void loadConfiguration() { 
    String configUrlStr = System.getenv("CONFIG_URL"); // You'd want to use a more 
                 // Specific variable name. 
    if(configUrlStr == null || configUrlStr.equals("") { 
     // You would probably want better exception handling, too. 
     throw new RuntimeException("CONFIG_URL is not set in the environment."); 
    } 


    try { 
     URI uri = new URI(configUrlStr); 
     File configFile = new File(uri); 
     if(!configFile.exists()) { 
      throw new RuntimeException("CONFIG_URL points to non-existant file"); 
     } 
     if(!configFile.canRead()) { 
      throw new RuntimeException("CONFIG_URL points to a file that cannot be read."); 
     } 
     this.readConfiguration(configFile); 
    } catch (URISyntaxException e) { 
     throw new RuntimeException("Malformed URL/URI in CONFIG_URL"); 
    } 



} 
+0

Per quanto semplice possa essere, ha lo svantaggio che è necessario riavviare il contenitore se è necessario modificare un valore. – kgiannakakis

+1

È necessario riavviare il contenitore solo se è necessario modificare la posizione del file - è possibile eseguire loadConfiguration() ogni volta che è necessario rileggere il contenuto del file. – Jared

4

I miei posti preferiti sono: variabili di ambiente e file di proprietà

Tabella Database proprietà dell'ambiente memorizzazione

comunque uno altre soluzioni più semplici è quello di avere dei database (come suggerito da Jared e kgiannakakis sopra.) tabella che memorizza le proprietà dell'ambiente.

Se l'applicazione utilizza database di

  • questo è relativamente facile da installare
  • lascia il posto veramente facile da controllare Valori/cambiamento
  • Può essere integrato nel processo ben rendendola parte di DB script
+2

+1: se si sta già utilizzando un database, la memorizzazione dei parametri di configurazione in una tabella è la soluzione più semplice. Dal momento che avrai già database di produzione/sviluppo/test, puoi facilmente memorizzare diversi valori per le diverse distribuzioni. Non è nemmeno necessario riavviare l'applicazione, quando viene apportata una modifica. – kgiannakakis

+2

Ma come si ottengono le informazioni di connessione per la connessione al database (questo è esattamente il tipo di informazioni che vorrei poter uscire da questa soluzione)? Questo è un problema dell'uovo di gallina. – Jared

+1

Concordato - Jared. Direi per DB ti affidi a JNDI con la stessa stringa JNDI. Quindi la tua app punta sempre su java: comp/db/datasource. Le informazioni di configurazione su DB (URL, utente, pwd, ecc.) Sono memorizzate all'esterno nel contenitore. Le proprietà DB funzioneranno per cose come URL, stringhe esterne, env. valori costanti dipendenti, ecc. Alcuni container forniscono tutti questi valori come JNDI, ma non tutti (ad esempio Websphere consente di associare valori stringa a JNDI, Weblogic a mia conoscenza no) –

9

si può solo memorizzare quindi è un normale file di proprietà java che si trova sul percorso classe e basta caricare le proprietà?

è semplice e abbastanza semplice .. a meno che non mi manca qualcosa

+2

Anche se questo sembra troppo semplice per essere buono, è davvero un buona alternativa Molti server di app hanno percorsi che vengono aggiunti al classpath, quindi è possibile rilasciare file .properties lì. – alex

+0

Un sacco di applicazioni che passano da jndi a questo modo alterante, aggiungendo/etc al classpath –

11

Abbiamo avuto un requisito configurazione simile durante la distribuzione di una webapp per i diversi sviluppatori, e su EC2 di Amazon: come si fa a separare configurazione dal codice binario? Nella mia esperienza, JNDI è troppo complesso e varia troppo tra i contenitori da utilizzare. Inoltre, l'XML di modifica manuale è molto suscettibile agli errori di sintassi, quindi l'idea è stata buttata fuori. Abbiamo risolto questo con un design basato su alcune regole:

1) solo il nome semplice = voci di valore devono essere utilizzati

2) nuove configurazioni dovrebbe essere caricabile modificando solo un parametro

3) la nostra GUERRA binario deve essere riconfigurabile w/o il riconfezionamento è

4) parametri sensibili (password) non potrà mai essere confezionati nel binario

utilizzando .properties file per tutte le configurazioni, e l'utilizzo di System.getProperty("domain"); per caricare i file delle proprietà appropriate, siamo stati in grado di soddisfare i requisiti. Tuttavia, la proprietà di sistema non punta a un URL di file, ma abbiamo creato un concetto che chiamiamo "dominio" per specificare la configurazione da utilizzare. La posizione della configurazione è sempre:
$HOME/appName/config/$DOMAIN.properties.

Quindi, se voglio fare funzionare il mio app usando il mio propria configurazione, io avviare l'applicazione impostando il dominio al mio nome:
-Ddomain=jason
all'avvio, e l'applicazione carica il file:
/home/jason/appName/config/jason.properties
Questo consente agli sviluppatori di condividere configurazioni in modo da ricreare lo stesso stato dell'app per test e distribuzione senza ricompilare o riconfezionare. Il valore del dominio viene quindi utilizzato per caricare .properties da una posizione standard, all'esterno del WAR in bundle.

posso completamente ricreare l'ambiente di produzione sulla mia workstation utilizzando la configurazione di produzione come:
-Ddomain=ec2 che caricare:
/home/jason/appName/config/ec2.properties

Questa configurazione ci permette di fare avere cicli dev/QA/rilascio con esattamente un set di binari compilati, utilizzando diverse configurazioni in ogni ambiente. Non c'è il rischio di avere password/etc in bundle nei binari, e le persone possono condividere le loro configurazioni per ricreare i problemi che stiamo vedendo.

+0

Funziona con diversi server delle applicazioni? –

+0

Ciao Martin, sì, funziona con diversi server di applicazioni, in quanto non esiste dipendenza dall'app. Lo stiamo utilizzando per Tomcat e Jetty e si comportano allo stesso modo. Dovrebbe funzionare anche per qualsiasi app non web. –

+0

Bello. Credo, tuttavia, che alcuni server applicativi possano limitare il tuo accesso al file system, e quindi questo non funzionerà per loro. –

Problemi correlati